blob: 2b248cc10fb387dd1858df2af91371789a448f2c [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"
Stephen Hinesc568f1e2014-07-21 00:47:37 -070018#include "clang/Sema/LoopHint.h"
Tareq A. Siraj6afcf882013-04-16 19:37:38 +000019#include "clang/Sema/Scope.h"
Reid Kleckner7adf79a2013-05-06 21:02:12 +000020#include "llvm/ADT/StringSwitch.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000021using namespace clang;
22
Stephen Hines651f13c2014-04-23 16:59:28 -070023namespace {
24
25struct PragmaAlignHandler : public PragmaHandler {
26 explicit PragmaAlignHandler() : PragmaHandler("align") {}
27 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
28 Token &FirstToken) override;
29};
30
31struct PragmaGCCVisibilityHandler : public PragmaHandler {
32 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
33 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
34 Token &FirstToken) override;
35};
36
37struct PragmaOptionsHandler : public PragmaHandler {
38 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
39 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
40 Token &FirstToken) override;
41};
42
43struct PragmaPackHandler : public PragmaHandler {
44 explicit PragmaPackHandler() : PragmaHandler("pack") {}
45 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
46 Token &FirstToken) override;
47};
48
49struct PragmaMSStructHandler : public PragmaHandler {
50 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
51 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
52 Token &FirstToken) override;
53};
54
55struct PragmaUnusedHandler : public PragmaHandler {
56 PragmaUnusedHandler() : PragmaHandler("unused") {}
57 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
58 Token &FirstToken) override;
59};
60
61struct PragmaWeakHandler : public PragmaHandler {
62 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
63 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
64 Token &FirstToken) override;
65};
66
67struct PragmaRedefineExtnameHandler : public PragmaHandler {
68 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
69 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
70 Token &FirstToken) override;
71};
72
73struct PragmaOpenCLExtensionHandler : public PragmaHandler {
74 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
75 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
76 Token &FirstToken) override;
77};
78
79
80struct PragmaFPContractHandler : public PragmaHandler {
81 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
82 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
83 Token &FirstToken) override;
84};
85
86struct PragmaNoOpenMPHandler : public PragmaHandler {
87 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
88 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
89 Token &FirstToken) override;
90};
91
92struct PragmaOpenMPHandler : public PragmaHandler {
93 PragmaOpenMPHandler() : PragmaHandler("omp") { }
94 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
95 Token &FirstToken) override;
96};
97
98/// PragmaCommentHandler - "\#pragma comment ...".
99struct PragmaCommentHandler : public PragmaHandler {
100 PragmaCommentHandler(Sema &Actions)
101 : PragmaHandler("comment"), Actions(Actions) {}
102 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
103 Token &FirstToken) override;
104private:
105 Sema &Actions;
106};
107
108struct PragmaDetectMismatchHandler : public PragmaHandler {
109 PragmaDetectMismatchHandler(Sema &Actions)
110 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
111 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
112 Token &FirstToken) override;
113private:
114 Sema &Actions;
115};
116
117struct PragmaMSPointersToMembers : public PragmaHandler {
118 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
119 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
120 Token &FirstToken) override;
121};
122
123struct PragmaMSVtorDisp : public PragmaHandler {
124 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
125 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
126 Token &FirstToken) override;
127};
128
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700129struct PragmaMSPragma : public PragmaHandler {
130 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
131 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
132 Token &FirstToken) override;
133};
134
135/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
136struct PragmaOptimizeHandler : public PragmaHandler {
137 PragmaOptimizeHandler(Sema &S)
138 : PragmaHandler("optimize"), Actions(S) {}
139 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
140 Token &FirstToken) override;
141private:
142 Sema &Actions;
143};
144
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700145struct PragmaLoopHintHandler : public PragmaHandler {
146 PragmaLoopHintHandler() : PragmaHandler("loop") {}
147 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
148 Token &FirstToken) override;
149};
150
Stephen Hines651f13c2014-04-23 16:59:28 -0700151} // end namespace
152
153void Parser::initializePragmaHandlers() {
154 AlignHandler.reset(new PragmaAlignHandler());
155 PP.AddPragmaHandler(AlignHandler.get());
156
157 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
158 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
159
160 OptionsHandler.reset(new PragmaOptionsHandler());
161 PP.AddPragmaHandler(OptionsHandler.get());
162
163 PackHandler.reset(new PragmaPackHandler());
164 PP.AddPragmaHandler(PackHandler.get());
165
166 MSStructHandler.reset(new PragmaMSStructHandler());
167 PP.AddPragmaHandler(MSStructHandler.get());
168
169 UnusedHandler.reset(new PragmaUnusedHandler());
170 PP.AddPragmaHandler(UnusedHandler.get());
171
172 WeakHandler.reset(new PragmaWeakHandler());
173 PP.AddPragmaHandler(WeakHandler.get());
174
175 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
176 PP.AddPragmaHandler(RedefineExtnameHandler.get());
177
178 FPContractHandler.reset(new PragmaFPContractHandler());
179 PP.AddPragmaHandler("STDC", FPContractHandler.get());
180
181 if (getLangOpts().OpenCL) {
182 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
183 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
184
185 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
186 }
187 if (getLangOpts().OpenMP)
188 OpenMPHandler.reset(new PragmaOpenMPHandler());
189 else
190 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
191 PP.AddPragmaHandler(OpenMPHandler.get());
192
193 if (getLangOpts().MicrosoftExt) {
194 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
195 PP.AddPragmaHandler(MSCommentHandler.get());
196 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
197 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
198 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
199 PP.AddPragmaHandler(MSPointersToMembers.get());
200 MSVtorDisp.reset(new PragmaMSVtorDisp());
201 PP.AddPragmaHandler(MSVtorDisp.get());
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700202 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
203 PP.AddPragmaHandler(MSInitSeg.get());
204 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
205 PP.AddPragmaHandler(MSDataSeg.get());
206 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
207 PP.AddPragmaHandler(MSBSSSeg.get());
208 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
209 PP.AddPragmaHandler(MSConstSeg.get());
210 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
211 PP.AddPragmaHandler(MSCodeSeg.get());
212 MSSection.reset(new PragmaMSPragma("section"));
213 PP.AddPragmaHandler(MSSection.get());
Stephen Hines651f13c2014-04-23 16:59:28 -0700214 }
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700215
216 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
217 PP.AddPragmaHandler("clang", OptimizeHandler.get());
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700218
219 LoopHintHandler.reset(new PragmaLoopHintHandler());
220 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Stephen Hines651f13c2014-04-23 16:59:28 -0700221}
222
223void Parser::resetPragmaHandlers() {
224 // Remove the pragma handlers we installed.
225 PP.RemovePragmaHandler(AlignHandler.get());
226 AlignHandler.reset();
227 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
228 GCCVisibilityHandler.reset();
229 PP.RemovePragmaHandler(OptionsHandler.get());
230 OptionsHandler.reset();
231 PP.RemovePragmaHandler(PackHandler.get());
232 PackHandler.reset();
233 PP.RemovePragmaHandler(MSStructHandler.get());
234 MSStructHandler.reset();
235 PP.RemovePragmaHandler(UnusedHandler.get());
236 UnusedHandler.reset();
237 PP.RemovePragmaHandler(WeakHandler.get());
238 WeakHandler.reset();
239 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
240 RedefineExtnameHandler.reset();
241
242 if (getLangOpts().OpenCL) {
243 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
244 OpenCLExtensionHandler.reset();
245 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
246 }
247 PP.RemovePragmaHandler(OpenMPHandler.get());
248 OpenMPHandler.reset();
249
250 if (getLangOpts().MicrosoftExt) {
251 PP.RemovePragmaHandler(MSCommentHandler.get());
252 MSCommentHandler.reset();
253 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
254 MSDetectMismatchHandler.reset();
255 PP.RemovePragmaHandler(MSPointersToMembers.get());
256 MSPointersToMembers.reset();
257 PP.RemovePragmaHandler(MSVtorDisp.get());
258 MSVtorDisp.reset();
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700259 PP.RemovePragmaHandler(MSInitSeg.get());
260 MSInitSeg.reset();
261 PP.RemovePragmaHandler(MSDataSeg.get());
262 MSDataSeg.reset();
263 PP.RemovePragmaHandler(MSBSSSeg.get());
264 MSBSSSeg.reset();
265 PP.RemovePragmaHandler(MSConstSeg.get());
266 MSConstSeg.reset();
267 PP.RemovePragmaHandler(MSCodeSeg.get());
268 MSCodeSeg.reset();
269 PP.RemovePragmaHandler(MSSection.get());
270 MSSection.reset();
Stephen Hines651f13c2014-04-23 16:59:28 -0700271 }
272
273 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
274 FPContractHandler.reset();
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700275
276 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
277 OptimizeHandler.reset();
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700278
279 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
280 LoopHintHandler.reset();
Stephen Hines651f13c2014-04-23 16:59:28 -0700281}
282
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000283/// \brief Handle the annotation token produced for #pragma unused(...)
284///
285/// Each annot_pragma_unused is followed by the argument token so e.g.
286/// "#pragma unused(x,y)" becomes:
287/// annot_pragma_unused 'x' annot_pragma_unused 'y'
288void Parser::HandlePragmaUnused() {
289 assert(Tok.is(tok::annot_pragma_unused));
290 SourceLocation UnusedLoc = ConsumeToken();
291 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
292 ConsumeToken(); // The argument token.
293}
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000294
Rafael Espindola426fc942012-01-26 02:02:57 +0000295void Parser::HandlePragmaVisibility() {
296 assert(Tok.is(tok::annot_pragma_vis));
297 const IdentifierInfo *VisType =
298 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
299 SourceLocation VisLoc = ConsumeToken();
300 Actions.ActOnPragmaVisibility(VisType, VisLoc);
301}
302
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000303struct PragmaPackInfo {
304 Sema::PragmaPackKind Kind;
305 IdentifierInfo *Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000306 Token Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000307 SourceLocation LParenLoc;
308 SourceLocation RParenLoc;
309};
310
311void Parser::HandlePragmaPack() {
312 assert(Tok.is(tok::annot_pragma_pack));
313 PragmaPackInfo *Info =
314 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
315 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman9595c7e2012-10-04 02:36:51 +0000316 ExprResult Alignment;
317 if (Info->Alignment.is(tok::numeric_constant)) {
318 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
319 if (Alignment.isInvalid())
320 return;
321 }
322 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000323 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000324}
325
Eli Friedman9595c7e2012-10-04 02:36:51 +0000326void Parser::HandlePragmaMSStruct() {
327 assert(Tok.is(tok::annot_pragma_msstruct));
328 Sema::PragmaMSStructKind Kind =
329 static_cast<Sema::PragmaMSStructKind>(
330 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
331 Actions.ActOnPragmaMSStruct(Kind);
332 ConsumeToken(); // The annotation token.
333}
334
335void Parser::HandlePragmaAlign() {
336 assert(Tok.is(tok::annot_pragma_align));
337 Sema::PragmaOptionsAlignKind Kind =
338 static_cast<Sema::PragmaOptionsAlignKind>(
339 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
340 SourceLocation PragmaLoc = ConsumeToken();
341 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
342}
343
344void Parser::HandlePragmaWeak() {
345 assert(Tok.is(tok::annot_pragma_weak));
346 SourceLocation PragmaLoc = ConsumeToken();
347 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
348 Tok.getLocation());
349 ConsumeToken(); // The weak name.
350}
351
352void Parser::HandlePragmaWeakAlias() {
353 assert(Tok.is(tok::annot_pragma_weakalias));
354 SourceLocation PragmaLoc = ConsumeToken();
355 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
356 SourceLocation WeakNameLoc = Tok.getLocation();
357 ConsumeToken();
358 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
359 SourceLocation AliasNameLoc = Tok.getLocation();
360 ConsumeToken();
361 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
362 WeakNameLoc, AliasNameLoc);
363
364}
365
366void Parser::HandlePragmaRedefineExtname() {
367 assert(Tok.is(tok::annot_pragma_redefine_extname));
368 SourceLocation RedefLoc = ConsumeToken();
369 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
370 SourceLocation RedefNameLoc = Tok.getLocation();
371 ConsumeToken();
372 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
373 SourceLocation AliasNameLoc = Tok.getLocation();
374 ConsumeToken();
375 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
376 RedefNameLoc, AliasNameLoc);
377}
378
379void Parser::HandlePragmaFPContract() {
380 assert(Tok.is(tok::annot_pragma_fp_contract));
381 tok::OnOffSwitch OOS =
382 static_cast<tok::OnOffSwitch>(
383 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
384 Actions.ActOnPragmaFPContract(OOS);
385 ConsumeToken(); // The annotation token.
386}
387
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000388StmtResult Parser::HandlePragmaCaptured()
389{
390 assert(Tok.is(tok::annot_pragma_captured));
391 ConsumeToken();
392
393 if (Tok.isNot(tok::l_brace)) {
Stephen Hines651f13c2014-04-23 16:59:28 -0700394 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000395 return StmtError();
396 }
397
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000398 SourceLocation Loc = Tok.getLocation();
399
400 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir8c045ac2013-05-03 19:00:33 +0000401 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
402 /*NumParams=*/1);
Tareq A. Siraj6afcf882013-04-16 19:37:38 +0000403
404 StmtResult R = ParseCompoundStatement();
405 CapturedRegionScope.Exit();
406
407 if (R.isInvalid()) {
408 Actions.ActOnCapturedRegionError();
409 return StmtError();
410 }
411
412 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000413}
414
Eli Friedman9595c7e2012-10-04 02:36:51 +0000415namespace {
416 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
417}
418
419void Parser::HandlePragmaOpenCLExtension() {
420 assert(Tok.is(tok::annot_pragma_opencl_extension));
421 OpenCLExtData data =
422 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
423 unsigned state = data.getInt();
424 IdentifierInfo *ename = data.getPointer();
425 SourceLocation NameLoc = Tok.getLocation();
426 ConsumeToken(); // The annotation token.
427
428 OpenCLOptions &f = Actions.getOpenCLOptions();
429 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
430 // overriding all previously issued extension directives, but only if the
431 // behavior is set to disable."
432 if (state == 0 && ename->isStr("all")) {
433#define OPENCLEXT(nm) f.nm = 0;
434#include "clang/Basic/OpenCLExtensions.def"
435 }
436#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
437#include "clang/Basic/OpenCLExtensions.def"
438 else {
439 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
440 return;
441 }
442}
443
Stephen Hines651f13c2014-04-23 16:59:28 -0700444void Parser::HandlePragmaMSPointersToMembers() {
445 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
446 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
447 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
448 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
449 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
450 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
451}
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000452
Stephen Hines651f13c2014-04-23 16:59:28 -0700453void Parser::HandlePragmaMSVtorDisp() {
454 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
455 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
456 Sema::PragmaVtorDispKind Kind =
457 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
458 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
459 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
460 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
461}
Tareq A. Siraj85192c72013-04-16 18:41:26 +0000462
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700463void Parser::HandlePragmaMSPragma() {
464 assert(Tok.is(tok::annot_pragma_ms_pragma));
465 // Grab the tokens out of the annotation and enter them into the stream.
466 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
467 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
468 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
469 assert(Tok.isAnyIdentifier());
470 llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
471 PP.Lex(Tok); // pragma kind
472 // Figure out which #pragma we're dealing with. The switch has no default
473 // because lex shouldn't emit the annotation token for unrecognized pragmas.
474 typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
475 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
476 .Case("data_seg", &Parser::HandlePragmaMSSegment)
477 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
478 .Case("const_seg", &Parser::HandlePragmaMSSegment)
479 .Case("code_seg", &Parser::HandlePragmaMSSegment)
480 .Case("section", &Parser::HandlePragmaMSSection)
481 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
482 if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
483 PP.Diag(PragmaLocation, DiagID) << PragmaName;
484 while (Tok.isNot(tok::eof))
485 PP.Lex(Tok);
486 PP.Lex(Tok);
487 }
488}
489
490unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
491 SourceLocation PragmaLocation) {
492 if (Tok.isNot(tok::l_paren))
493 return diag::warn_pragma_expected_lparen;
494 PP.Lex(Tok); // (
495 // Parsing code for pragma section
496 if (Tok.isNot(tok::string_literal))
497 return diag::warn_pragma_expected_section_name;
498 StringLiteral *SegmentName =
499 cast<StringLiteral>(ParseStringLiteralExpression().get());
500 int SectionFlags = 0;
501 while (Tok.is(tok::comma)) {
502 PP.Lex(Tok); // ,
503 if (!Tok.isAnyIdentifier())
504 return diag::warn_pragma_expected_action_or_r_paren;
505 Sema::PragmaSectionFlag Flag =
506 llvm::StringSwitch<Sema::PragmaSectionFlag>(
507 Tok.getIdentifierInfo()->getName())
508 .Case("read", Sema::PSF_Read)
509 .Case("write", Sema::PSF_Write)
510 .Case("execute", Sema::PSF_Execute)
511 .Case("shared", Sema::PSF_Invalid)
512 .Case("nopage", Sema::PSF_Invalid)
513 .Case("nocache", Sema::PSF_Invalid)
514 .Case("discard", Sema::PSF_Invalid)
515 .Case("remove", Sema::PSF_Invalid)
516 .Default(Sema::PSF_None);
517 if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
518 PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
519 diag::warn_pragma_invalid_specific_action :
520 diag::warn_pragma_unsupported_action)
521 << PragmaName << Tok.getIdentifierInfo()->getName();
522 while (Tok.isNot(tok::eof))
523 PP.Lex(Tok);
524 PP.Lex(Tok);
525 return 0;
526 }
527 SectionFlags |= Flag;
528 PP.Lex(Tok); // Identifier
529 }
530 if (Tok.isNot(tok::r_paren))
531 return diag::warn_pragma_expected_rparen;
532 PP.Lex(Tok); // )
533 if (Tok.isNot(tok::eof))
534 return diag::warn_pragma_extra_tokens_at_eol;
535 PP.Lex(Tok); // eof
536 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
537 return 0;
538}
539
540unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
541 SourceLocation PragmaLocation) {
542 if (Tok.isNot(tok::l_paren))
543 return diag::warn_pragma_expected_lparen;
544 PP.Lex(Tok); // (
545 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
546 llvm::StringRef SlotLabel;
547 if (Tok.isAnyIdentifier()) {
548 llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
549 if (PushPop == "push")
550 Action = Sema::PSK_Push;
551 else if (PushPop == "pop")
552 Action = Sema::PSK_Pop;
553 else
554 return diag::warn_pragma_expected_section_push_pop_or_name;
555 if (Action != Sema::PSK_Reset) {
556 PP.Lex(Tok); // push | pop
557 if (Tok.is(tok::comma)) {
558 PP.Lex(Tok); // ,
559 // If we've got a comma, we either need a label or a string.
560 if (Tok.isAnyIdentifier()) {
561 SlotLabel = Tok.getIdentifierInfo()->getName();
562 PP.Lex(Tok); // identifier
563 if (Tok.is(tok::comma))
564 PP.Lex(Tok);
565 else if (Tok.isNot(tok::r_paren))
566 return diag::warn_pragma_expected_punc;
567 }
568 } else if (Tok.isNot(tok::r_paren))
569 return diag::warn_pragma_expected_punc;
570 }
571 }
572 // Grab the string literal for our section name.
573 StringLiteral *SegmentName = nullptr;
574 if (Tok.isNot(tok::r_paren)) {
575 if (Tok.isNot(tok::string_literal))
576 return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
577 diag::warn_pragma_expected_section_name :
578 diag::warn_pragma_expected_section_label_or_name :
579 diag::warn_pragma_expected_section_push_pop_or_name;
580 SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
581 // Setting section "" has no effect
582 if (SegmentName->getLength())
583 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
584 }
585 if (Tok.isNot(tok::r_paren))
586 return diag::warn_pragma_expected_rparen;
587 PP.Lex(Tok); // )
588 if (Tok.isNot(tok::eof))
589 return diag::warn_pragma_extra_tokens_at_eol;
590 PP.Lex(Tok); // eof
591 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
592 SegmentName, PragmaName);
593 return 0;
594}
595
596unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
597 SourceLocation PragmaLocation) {
598 return PP.getDiagnostics().getCustomDiagID(
599 DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
600}
601
Stephen Hinesc568f1e2014-07-21 00:47:37 -0700602struct PragmaLoopHintInfo {
603 Token Loop;
604 Token Value;
605 Token Option;
606};
607
608LoopHint Parser::HandlePragmaLoopHint() {
609 assert(Tok.is(tok::annot_pragma_loop_hint));
610 PragmaLoopHintInfo *Info =
611 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
612
613 LoopHint Hint;
614 Hint.LoopLoc =
615 IdentifierLoc::create(Actions.Context, Info->Loop.getLocation(),
616 Info->Loop.getIdentifierInfo());
617 Hint.OptionLoc =
618 IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
619 Info->Option.getIdentifierInfo());
620 Hint.ValueLoc =
621 IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
622 Info->Value.getIdentifierInfo());
623 Hint.Range =
624 SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
625
626 // FIXME: We should allow non-type template parameters for the loop hint
627 // value. See bug report #19610
628 if (Info->Value.is(tok::numeric_constant))
629 Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
630 else
631 Hint.ValueExpr = nullptr;
632
633 return Hint;
634}
635
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000636// #pragma GCC visibility comes in two variants:
637// 'push' '(' [visibility] ')'
638// 'pop'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000639void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
640 PragmaIntroducerKind Introducer,
641 Token &VisTok) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000642 SourceLocation VisLoc = VisTok.getLocation();
643
644 Token Tok;
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000645 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000646
647 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
648
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000649 const IdentifierInfo *VisType;
650 if (PushPop && PushPop->isStr("pop")) {
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700651 VisType = nullptr;
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000652 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000653 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000654 if (Tok.isNot(tok::l_paren)) {
655 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
656 << "visibility";
657 return;
658 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000659 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000660 VisType = Tok.getIdentifierInfo();
661 if (!VisType) {
662 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
663 << "visibility";
664 return;
665 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000666 PP.LexUnexpandedToken(Tok);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000667 if (Tok.isNot(tok::r_paren)) {
668 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
669 << "visibility";
670 return;
671 }
672 } else {
673 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
674 << "visibility";
675 return;
676 }
Joerg Sonnenbergere23af2a2011-07-20 01:03:50 +0000677 PP.LexUnexpandedToken(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000678 if (Tok.isNot(tok::eod)) {
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000679 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
680 << "visibility";
681 return;
682 }
683
Rafael Espindola426fc942012-01-26 02:02:57 +0000684 Token *Toks = new Token[1];
685 Toks[0].startToken();
686 Toks[0].setKind(tok::annot_pragma_vis);
687 Toks[0].setLocation(VisLoc);
688 Toks[0].setAnnotationValue(
689 const_cast<void*>(static_cast<const void*>(VisType)));
690 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
691 /*OwnsTokens=*/true);
Eli Friedmanaa8b0d12010-08-05 06:57:20 +0000692}
693
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000694// #pragma pack(...) comes in the following delicious flavors:
695// pack '(' [integer] ')'
696// pack '(' 'show' ')'
697// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregor80c60f72010-09-09 22:45:38 +0000698void PragmaPackHandler::HandlePragma(Preprocessor &PP,
699 PragmaIntroducerKind Introducer,
700 Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000701 SourceLocation PackLoc = PackTok.getLocation();
702
703 Token Tok;
704 PP.Lex(Tok);
705 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000706 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000707 return;
708 }
709
John McCallf312b1e2010-08-26 23:41:50 +0000710 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Stephen Hines6bcf27b2014-05-29 04:14:42 -0700711 IdentifierInfo *Name = nullptr;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000712 Token Alignment;
713 Alignment.startToken();
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000714 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000715 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000716 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000717 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000718
719 PP.Lex(Tok);
Eli Friedman19bda3a2011-11-02 01:53:16 +0000720
721 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
722 // the push/pop stack.
723 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikie4e4d0842012-03-11 07:00:24 +0000724 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman19bda3a2011-11-02 01:53:16 +0000725 Kind = Sema::PPK_Push;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000726 } else if (Tok.is(tok::identifier)) {
727 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000728 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000729 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000730 PP.Lex(Tok);
731 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000732 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000733 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000734 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000735 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000736 } else {
Stephen Hines651f13c2014-04-23 16:59:28 -0700737 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000738 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000739 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000740 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000741
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000742 if (Tok.is(tok::comma)) {
743 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000744
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000745 if (Tok.is(tok::numeric_constant)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000746 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000747
748 PP.Lex(Tok);
749 } else if (Tok.is(tok::identifier)) {
750 Name = Tok.getIdentifierInfo();
751 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000752
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000753 if (Tok.is(tok::comma)) {
754 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000755
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000756 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000757 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000758 return;
759 }
Mike Stump1eb44332009-09-09 15:08:12 +0000760
Eli Friedman9595c7e2012-10-04 02:36:51 +0000761 Alignment = Tok;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000762
763 PP.Lex(Tok);
764 }
765 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000766 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000767 return;
768 }
769 }
770 }
David Blaikie4e4d0842012-03-11 07:00:24 +0000771 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman19bda3a2011-11-02 01:53:16 +0000772 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
773 // the push/pop stack.
774 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
775 Kind = Sema::PPK_Pop;
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000776 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000777
778 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000779 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000780 return;
781 }
782
Daniel Dunbar861800c2010-05-26 23:29:06 +0000783 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000784 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000785 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000786 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
787 return;
788 }
789
Daniel Dunbarb0939552012-02-29 01:38:22 +0000790 PragmaPackInfo *Info =
791 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
792 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
793 new (Info) PragmaPackInfo();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000794 Info->Kind = Kind;
795 Info->Name = Name;
Eli Friedman9595c7e2012-10-04 02:36:51 +0000796 Info->Alignment = Alignment;
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000797 Info->LParenLoc = LParenLoc;
798 Info->RParenLoc = RParenLoc;
799
Daniel Dunbarb0939552012-02-29 01:38:22 +0000800 Token *Toks =
801 (Token*) PP.getPreprocessorAllocator().Allocate(
802 sizeof(Token) * 1, llvm::alignOf<Token>());
803 new (Toks) Token();
Eli Friedmanaa5ab262012-02-23 23:47:16 +0000804 Toks[0].startToken();
805 Toks[0].setKind(tok::annot_pragma_pack);
806 Toks[0].setLocation(PackLoc);
807 Toks[0].setAnnotationValue(static_cast<void*>(Info));
808 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbarb0939552012-02-29 01:38:22 +0000809 /*OwnsTokens=*/false);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000810}
811
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000812// #pragma ms_struct on
813// #pragma ms_struct off
814void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
815 PragmaIntroducerKind Introducer,
816 Token &MSStructTok) {
817 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
818
819 Token Tok;
820 PP.Lex(Tok);
821 if (Tok.isNot(tok::identifier)) {
822 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
823 return;
824 }
825 const IdentifierInfo *II = Tok.getIdentifierInfo();
826 if (II->isStr("on")) {
827 Kind = Sema::PMSST_ON;
828 PP.Lex(Tok);
829 }
830 else if (II->isStr("off") || II->isStr("reset"))
831 PP.Lex(Tok);
832 else {
833 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
834 return;
835 }
836
837 if (Tok.isNot(tok::eod)) {
Daniel Dunbarb0939552012-02-29 01:38:22 +0000838 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
839 << "ms_struct";
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000840 return;
841 }
Eli Friedman9595c7e2012-10-04 02:36:51 +0000842
843 Token *Toks =
844 (Token*) PP.getPreprocessorAllocator().Allocate(
845 sizeof(Token) * 1, llvm::alignOf<Token>());
846 new (Toks) Token();
847 Toks[0].startToken();
848 Toks[0].setKind(tok::annot_pragma_msstruct);
849 Toks[0].setLocation(MSStructTok.getLocation());
850 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
851 static_cast<uintptr_t>(Kind)));
852 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
853 /*OwnsTokens=*/false);
Fariborz Jahanian62c92582011-04-25 18:49:15 +0000854}
855
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000856// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
857// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman9595c7e2012-10-04 02:36:51 +0000858static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000859 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000860 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000861
862 if (IsOptions) {
863 PP.Lex(Tok);
864 if (Tok.isNot(tok::identifier) ||
865 !Tok.getIdentifierInfo()->isStr("align")) {
866 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
867 return;
868 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000869 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000870
Daniel Dunbar861800c2010-05-26 23:29:06 +0000871 PP.Lex(Tok);
872 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000873 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
874 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000875 return;
876 }
877
878 PP.Lex(Tok);
879 if (Tok.isNot(tok::identifier)) {
880 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000881 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000882 return;
883 }
884
John McCallf312b1e2010-08-26 23:41:50 +0000885 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000886 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000887 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000888 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000889 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000890 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000891 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000892 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000893 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000894 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000895 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000896 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000897 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000898 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000899 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000900 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
901 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000902 return;
903 }
904
Daniel Dunbar861800c2010-05-26 23:29:06 +0000905 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000906 if (Tok.isNot(tok::eod)) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000907 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000908 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000909 return;
910 }
911
Eli Friedman9595c7e2012-10-04 02:36:51 +0000912 Token *Toks =
913 (Token*) PP.getPreprocessorAllocator().Allocate(
914 sizeof(Token) * 1, llvm::alignOf<Token>());
915 new (Toks) Token();
916 Toks[0].startToken();
917 Toks[0].setKind(tok::annot_pragma_align);
918 Toks[0].setLocation(FirstTok.getLocation());
919 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
920 static_cast<uintptr_t>(Kind)));
921 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
922 /*OwnsTokens=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000923}
924
Douglas Gregor80c60f72010-09-09 22:45:38 +0000925void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
926 PragmaIntroducerKind Introducer,
927 Token &AlignTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000928 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000929}
930
Douglas Gregor80c60f72010-09-09 22:45:38 +0000931void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
932 PragmaIntroducerKind Introducer,
933 Token &OptionsTok) {
Eli Friedman9595c7e2012-10-04 02:36:51 +0000934 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000935}
936
Ted Kremenek4726d032009-03-23 22:28:25 +0000937// #pragma unused(identifier)
Douglas Gregor80c60f72010-09-09 22:45:38 +0000938void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
939 PragmaIntroducerKind Introducer,
940 Token &UnusedTok) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000941 // FIXME: Should we be expanding macros here? My guess is no.
942 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000943
Ted Kremenek4726d032009-03-23 22:28:25 +0000944 // Lex the left '('.
945 Token Tok;
946 PP.Lex(Tok);
947 if (Tok.isNot(tok::l_paren)) {
948 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
949 return;
950 }
Mike Stump1eb44332009-09-09 15:08:12 +0000951
Ted Kremenek4726d032009-03-23 22:28:25 +0000952 // Lex the declaration reference(s).
Chris Lattner5f9e2722011-07-23 10:55:15 +0000953 SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000954 SourceLocation RParenLoc;
955 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000956
Ted Kremenek4726d032009-03-23 22:28:25 +0000957 while (true) {
958 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000959
Ted Kremenek4726d032009-03-23 22:28:25 +0000960 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000961 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000962 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000963 LexID = false;
964 continue;
965 }
966
Ted Kremenek7a02a372009-08-03 23:24:57 +0000967 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000968 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
969 return;
970 }
Mike Stump1eb44332009-09-09 15:08:12 +0000971
Ted Kremenek4726d032009-03-23 22:28:25 +0000972 // We are execting a ')' or a ','.
973 if (Tok.is(tok::comma)) {
974 LexID = true;
975 continue;
976 }
Mike Stump1eb44332009-09-09 15:08:12 +0000977
Ted Kremenek4726d032009-03-23 22:28:25 +0000978 if (Tok.is(tok::r_paren)) {
979 RParenLoc = Tok.getLocation();
980 break;
981 }
Mike Stump1eb44332009-09-09 15:08:12 +0000982
Ted Kremenek7a02a372009-08-03 23:24:57 +0000983 // Illegal token!
Stephen Hines651f13c2014-04-23 16:59:28 -0700984 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenek4726d032009-03-23 22:28:25 +0000985 return;
986 }
Eli Friedman99914792009-06-05 00:49:58 +0000987
988 PP.Lex(Tok);
Peter Collingbourne84021552011-02-28 02:37:51 +0000989 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +0000990 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
991 "unused";
992 return;
993 }
994
Ted Kremenek4726d032009-03-23 22:28:25 +0000995 // Verify that we have a location for the right parenthesis.
996 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000997 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000998
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +0000999 // For each identifier token, insert into the token stream a
1000 // annot_pragma_unused token followed by the identifier token.
1001 // This allows us to cache a "#pragma unused" that occurs inside an inline
1002 // C++ member function.
1003
Daniel Dunbarb0939552012-02-29 01:38:22 +00001004 Token *Toks =
1005 (Token*) PP.getPreprocessorAllocator().Allocate(
1006 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisb918d0f2011-01-17 18:58:44 +00001007 for (unsigned i=0; i != Identifiers.size(); i++) {
1008 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1009 pragmaUnusedTok.startToken();
1010 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1011 pragmaUnusedTok.setLocation(UnusedLoc);
1012 idTok = Identifiers[i];
1013 }
Daniel Dunbarb0939552012-02-29 01:38:22 +00001014 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1015 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenek4726d032009-03-23 22:28:25 +00001016}
Eli Friedman99914792009-06-05 00:49:58 +00001017
1018// #pragma weak identifier
1019// #pragma weak identifier '=' identifier
Douglas Gregor80c60f72010-09-09 22:45:38 +00001020void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1021 PragmaIntroducerKind Introducer,
1022 Token &WeakTok) {
Eli Friedman99914792009-06-05 00:49:58 +00001023 SourceLocation WeakLoc = WeakTok.getLocation();
1024
1025 Token Tok;
1026 PP.Lex(Tok);
1027 if (Tok.isNot(tok::identifier)) {
1028 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1029 return;
1030 }
1031
Eli Friedman9595c7e2012-10-04 02:36:51 +00001032 Token WeakName = Tok;
1033 bool HasAlias = false;
1034 Token AliasName;
Eli Friedman99914792009-06-05 00:49:58 +00001035
1036 PP.Lex(Tok);
1037 if (Tok.is(tok::equal)) {
Eli Friedman9595c7e2012-10-04 02:36:51 +00001038 HasAlias = true;
Eli Friedman99914792009-06-05 00:49:58 +00001039 PP.Lex(Tok);
1040 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +00001041 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +00001042 << "weak";
1043 return;
1044 }
Eli Friedman9595c7e2012-10-04 02:36:51 +00001045 AliasName = Tok;
Eli Friedman99914792009-06-05 00:49:58 +00001046 PP.Lex(Tok);
1047 }
1048
Peter Collingbourne84021552011-02-28 02:37:51 +00001049 if (Tok.isNot(tok::eod)) {
Eli Friedman99914792009-06-05 00:49:58 +00001050 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1051 return;
1052 }
1053
Eli Friedman9595c7e2012-10-04 02:36:51 +00001054 if (HasAlias) {
1055 Token *Toks =
1056 (Token*) PP.getPreprocessorAllocator().Allocate(
1057 sizeof(Token) * 3, llvm::alignOf<Token>());
1058 Token &pragmaUnusedTok = Toks[0];
1059 pragmaUnusedTok.startToken();
1060 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1061 pragmaUnusedTok.setLocation(WeakLoc);
1062 Toks[1] = WeakName;
1063 Toks[2] = AliasName;
1064 PP.EnterTokenStream(Toks, 3,
1065 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +00001066 } else {
Eli Friedman9595c7e2012-10-04 02:36:51 +00001067 Token *Toks =
1068 (Token*) PP.getPreprocessorAllocator().Allocate(
1069 sizeof(Token) * 2, llvm::alignOf<Token>());
1070 Token &pragmaUnusedTok = Toks[0];
1071 pragmaUnusedTok.startToken();
1072 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1073 pragmaUnusedTok.setLocation(WeakLoc);
1074 Toks[1] = WeakName;
1075 PP.EnterTokenStream(Toks, 2,
1076 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedman99914792009-06-05 00:49:58 +00001077 }
1078}
Peter Collingbourne321b8172011-02-14 01:42:35 +00001079
David Chisnall5f3c1632012-02-18 16:12:34 +00001080// #pragma redefine_extname identifier identifier
1081void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1082 PragmaIntroducerKind Introducer,
1083 Token &RedefToken) {
1084 SourceLocation RedefLoc = RedefToken.getLocation();
1085
1086 Token Tok;
1087 PP.Lex(Tok);
1088 if (Tok.isNot(tok::identifier)) {
1089 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1090 "redefine_extname";
1091 return;
1092 }
1093
Eli Friedman9595c7e2012-10-04 02:36:51 +00001094 Token RedefName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +00001095 PP.Lex(Tok);
Eli Friedman9595c7e2012-10-04 02:36:51 +00001096
David Chisnall5f3c1632012-02-18 16:12:34 +00001097 if (Tok.isNot(tok::identifier)) {
1098 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1099 << "redefine_extname";
1100 return;
1101 }
Eli Friedman9595c7e2012-10-04 02:36:51 +00001102
1103 Token AliasName = Tok;
David Chisnall5f3c1632012-02-18 16:12:34 +00001104 PP.Lex(Tok);
1105
1106 if (Tok.isNot(tok::eod)) {
1107 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1108 "redefine_extname";
1109 return;
1110 }
1111
Eli Friedman9595c7e2012-10-04 02:36:51 +00001112 Token *Toks =
1113 (Token*) PP.getPreprocessorAllocator().Allocate(
1114 sizeof(Token) * 3, llvm::alignOf<Token>());
1115 Token &pragmaRedefTok = Toks[0];
1116 pragmaRedefTok.startToken();
1117 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1118 pragmaRedefTok.setLocation(RedefLoc);
1119 Toks[1] = RedefName;
1120 Toks[2] = AliasName;
1121 PP.EnterTokenStream(Toks, 3,
1122 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall5f3c1632012-02-18 16:12:34 +00001123}
1124
1125
Peter Collingbourne321b8172011-02-14 01:42:35 +00001126void
1127PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1128 PragmaIntroducerKind Introducer,
1129 Token &Tok) {
1130 tok::OnOffSwitch OOS;
1131 if (PP.LexOnOffSwitch(OOS))
1132 return;
1133
Eli Friedman9595c7e2012-10-04 02:36:51 +00001134 Token *Toks =
1135 (Token*) PP.getPreprocessorAllocator().Allocate(
1136 sizeof(Token) * 1, llvm::alignOf<Token>());
1137 new (Toks) Token();
1138 Toks[0].startToken();
1139 Toks[0].setKind(tok::annot_pragma_fp_contract);
1140 Toks[0].setLocation(Tok.getLocation());
1141 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1142 static_cast<uintptr_t>(OOS)));
1143 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1144 /*OwnsTokens=*/false);
Peter Collingbourne321b8172011-02-14 01:42:35 +00001145}
Peter Collingbournef315fa82011-02-14 01:42:53 +00001146
1147void
1148PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1149 PragmaIntroducerKind Introducer,
1150 Token &Tok) {
Tanya Lattnerb38b6a72011-04-14 23:35:31 +00001151 PP.LexUnexpandedToken(Tok);
Peter Collingbournef315fa82011-02-14 01:42:53 +00001152 if (Tok.isNot(tok::identifier)) {
1153 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1154 "OPENCL";
1155 return;
1156 }
1157 IdentifierInfo *ename = Tok.getIdentifierInfo();
1158 SourceLocation NameLoc = Tok.getLocation();
1159
1160 PP.Lex(Tok);
1161 if (Tok.isNot(tok::colon)) {
1162 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1163 return;
1164 }
1165
1166 PP.Lex(Tok);
1167 if (Tok.isNot(tok::identifier)) {
1168 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1169 return;
1170 }
1171 IdentifierInfo *op = Tok.getIdentifierInfo();
1172
1173 unsigned state;
1174 if (op->isStr("enable")) {
1175 state = 1;
1176 } else if (op->isStr("disable")) {
1177 state = 0;
1178 } else {
1179 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1180 return;
1181 }
Pekka Jaaskelainena0950e82013-10-12 09:29:48 +00001182 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbournef315fa82011-02-14 01:42:53 +00001183
Eli Friedman9595c7e2012-10-04 02:36:51 +00001184 PP.Lex(Tok);
1185 if (Tok.isNot(tok::eod)) {
1186 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1187 "OPENCL EXTENSION";
Peter Collingbournef315fa82011-02-14 01:42:53 +00001188 return;
1189 }
Eli Friedman9595c7e2012-10-04 02:36:51 +00001190
1191 OpenCLExtData data(ename, state);
1192 Token *Toks =
1193 (Token*) PP.getPreprocessorAllocator().Allocate(
1194 sizeof(Token) * 1, llvm::alignOf<Token>());
1195 new (Toks) Token();
1196 Toks[0].startToken();
1197 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1198 Toks[0].setLocation(NameLoc);
1199 Toks[0].setAnnotationValue(data.getOpaqueValue());
1200 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1201 /*OwnsTokens=*/false);
Pekka Jaaskelainena0950e82013-10-12 09:29:48 +00001202
1203 if (PP.getPPCallbacks())
1204 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1205 StateLoc, state);
Peter Collingbournef315fa82011-02-14 01:42:53 +00001206}
1207
Alexey Bataevc6400582013-03-22 06:34:35 +00001208/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1209///
1210void
1211PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1212 PragmaIntroducerKind Introducer,
1213 Token &FirstTok) {
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001214 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1215 FirstTok.getLocation())) {
Alexey Bataevc6400582013-03-22 06:34:35 +00001216 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001217 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1218 diag::Severity::Ignored, SourceLocation());
Alexey Bataevc6400582013-03-22 06:34:35 +00001219 }
1220 PP.DiscardUntilEndOfDirective();
1221}
1222
1223/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1224///
1225void
1226PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1227 PragmaIntroducerKind Introducer,
1228 Token &FirstTok) {
1229 SmallVector<Token, 16> Pragma;
1230 Token Tok;
1231 Tok.startToken();
1232 Tok.setKind(tok::annot_pragma_openmp);
1233 Tok.setLocation(FirstTok.getLocation());
1234
1235 while (Tok.isNot(tok::eod)) {
1236 Pragma.push_back(Tok);
1237 PP.Lex(Tok);
1238 }
1239 SourceLocation EodLoc = Tok.getLocation();
1240 Tok.startToken();
1241 Tok.setKind(tok::annot_pragma_openmp_end);
1242 Tok.setLocation(EodLoc);
1243 Pragma.push_back(Tok);
1244
1245 Token *Toks = new Token[Pragma.size()];
1246 std::copy(Pragma.begin(), Pragma.end(), Toks);
1247 PP.EnterTokenStream(Toks, Pragma.size(),
1248 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1249}
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001250
Stephen Hines651f13c2014-04-23 16:59:28 -07001251/// \brief Handle '#pragma pointers_to_members'
1252// The grammar for this pragma is as follows:
1253//
1254// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1255//
1256// #pragma pointers_to_members '(' 'best_case' ')'
1257// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1258// #pragma pointers_to_members '(' inheritance-model ')'
1259void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1260 PragmaIntroducerKind Introducer,
1261 Token &Tok) {
1262 SourceLocation PointersToMembersLoc = Tok.getLocation();
1263 PP.Lex(Tok);
1264 if (Tok.isNot(tok::l_paren)) {
1265 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1266 << "pointers_to_members";
1267 return;
1268 }
1269 PP.Lex(Tok);
1270 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1271 if (!Arg) {
1272 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1273 << "pointers_to_members";
1274 return;
1275 }
1276 PP.Lex(Tok);
1277
1278 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1279 if (Arg->isStr("best_case")) {
1280 RepresentationMethod = LangOptions::PPTMK_BestCase;
1281 } else {
1282 if (Arg->isStr("full_generality")) {
1283 if (Tok.is(tok::comma)) {
1284 PP.Lex(Tok);
1285
1286 Arg = Tok.getIdentifierInfo();
1287 if (!Arg) {
1288 PP.Diag(Tok.getLocation(),
1289 diag::err_pragma_pointers_to_members_unknown_kind)
1290 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1291 return;
1292 }
1293 PP.Lex(Tok);
1294 } else if (Tok.is(tok::r_paren)) {
1295 // #pragma pointers_to_members(full_generality) implicitly specifies
1296 // virtual_inheritance.
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001297 Arg = nullptr;
Stephen Hines651f13c2014-04-23 16:59:28 -07001298 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1299 } else {
1300 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1301 << "full_generality";
1302 return;
1303 }
1304 }
1305
1306 if (Arg) {
1307 if (Arg->isStr("single_inheritance")) {
1308 RepresentationMethod =
1309 LangOptions::PPTMK_FullGeneralitySingleInheritance;
1310 } else if (Arg->isStr("multiple_inheritance")) {
1311 RepresentationMethod =
1312 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1313 } else if (Arg->isStr("virtual_inheritance")) {
1314 RepresentationMethod =
1315 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1316 } else {
1317 PP.Diag(Tok.getLocation(),
1318 diag::err_pragma_pointers_to_members_unknown_kind)
1319 << Arg << /*HasPointerDeclaration*/ 1;
1320 return;
1321 }
1322 }
1323 }
1324
1325 if (Tok.isNot(tok::r_paren)) {
1326 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1327 << (Arg ? Arg->getName() : "full_generality");
1328 return;
1329 }
1330
1331 PP.Lex(Tok);
1332 if (Tok.isNot(tok::eod)) {
1333 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1334 << "pointers_to_members";
1335 return;
1336 }
1337
1338 Token AnnotTok;
1339 AnnotTok.startToken();
1340 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1341 AnnotTok.setLocation(PointersToMembersLoc);
1342 AnnotTok.setAnnotationValue(
1343 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1344 PP.EnterToken(AnnotTok);
1345}
1346
1347/// \brief Handle '#pragma vtordisp'
1348// The grammar for this pragma is as follows:
1349//
1350// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1351//
1352// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1353// #pragma vtordisp '(' 'pop' ')'
1354// #pragma vtordisp '(' ')'
1355void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1356 PragmaIntroducerKind Introducer,
1357 Token &Tok) {
1358 SourceLocation VtorDispLoc = Tok.getLocation();
1359 PP.Lex(Tok);
1360 if (Tok.isNot(tok::l_paren)) {
1361 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1362 return;
1363 }
1364 PP.Lex(Tok);
1365
1366 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1367 const IdentifierInfo *II = Tok.getIdentifierInfo();
1368 if (II) {
1369 if (II->isStr("push")) {
1370 // #pragma vtordisp(push, mode)
1371 PP.Lex(Tok);
1372 if (Tok.isNot(tok::comma)) {
1373 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1374 return;
1375 }
1376 PP.Lex(Tok);
1377 Kind = Sema::PVDK_Push;
1378 // not push, could be on/off
1379 } else if (II->isStr("pop")) {
1380 // #pragma vtordisp(pop)
1381 PP.Lex(Tok);
1382 Kind = Sema::PVDK_Pop;
1383 }
1384 // not push or pop, could be on/off
1385 } else {
1386 if (Tok.is(tok::r_paren)) {
1387 // #pragma vtordisp()
1388 Kind = Sema::PVDK_Reset;
1389 }
1390 }
1391
1392
1393 uint64_t Value = 0;
1394 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1395 const IdentifierInfo *II = Tok.getIdentifierInfo();
1396 if (II && II->isStr("off")) {
1397 PP.Lex(Tok);
1398 Value = 0;
1399 } else if (II && II->isStr("on")) {
1400 PP.Lex(Tok);
1401 Value = 1;
1402 } else if (Tok.is(tok::numeric_constant) &&
1403 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1404 if (Value > 2) {
1405 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1406 << 0 << 2 << "vtordisp";
1407 return;
1408 }
1409 } else {
1410 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1411 << "vtordisp";
1412 return;
1413 }
1414 }
1415
1416 // Finish the pragma: ')' $
1417 if (Tok.isNot(tok::r_paren)) {
1418 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1419 return;
1420 }
1421 PP.Lex(Tok);
1422 if (Tok.isNot(tok::eod)) {
1423 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1424 << "vtordisp";
1425 return;
1426 }
1427
1428 // Enter the annotation.
1429 Token AnnotTok;
1430 AnnotTok.startToken();
1431 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1432 AnnotTok.setLocation(VtorDispLoc);
1433 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1434 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1435 PP.EnterToken(AnnotTok);
1436}
1437
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001438/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1439/// an annotation token.
1440void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1441 PragmaIntroducerKind Introducer,
1442 Token &Tok) {
1443 Token EoF, AnnotTok;
1444 EoF.startToken();
1445 EoF.setKind(tok::eof);
1446 AnnotTok.startToken();
1447 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1448 AnnotTok.setLocation(Tok.getLocation());
1449 SmallVector<Token, 8> TokenVector;
1450 // Suck up all of the tokens before the eod.
1451 for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1452 TokenVector.push_back(Tok);
1453 // Add a sentinal EoF token to the end of the list.
1454 TokenVector.push_back(EoF);
1455 // We must allocate this array with new because EnterTokenStream is going to
1456 // delete it later.
1457 Token *TokenArray = new Token[TokenVector.size()];
1458 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1459 auto Value = new (PP.getPreprocessorAllocator())
1460 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1461 AnnotTok.setAnnotationValue(Value);
1462 PP.EnterToken(AnnotTok);
1463}
1464
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001465/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1466///
1467/// The syntax is:
1468/// \code
1469/// #pragma detect_mismatch("name", "value")
1470/// \endcode
1471/// Where 'name' and 'value' are quoted strings. The values are embedded in
1472/// the object file and passed along to the linker. If the linker detects a
1473/// mismatch in the object file's values for the given name, a LNK2038 error
1474/// is emitted. See MSDN for more details.
1475void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1476 PragmaIntroducerKind Introducer,
1477 Token &Tok) {
1478 SourceLocation CommentLoc = Tok.getLocation();
1479 PP.Lex(Tok);
1480 if (Tok.isNot(tok::l_paren)) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001481 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001482 return;
1483 }
1484
1485 // Read the name to embed, which must be a string literal.
1486 std::string NameString;
1487 if (!PP.LexStringLiteral(Tok, NameString,
1488 "pragma detect_mismatch",
1489 /*MacroExpansion=*/true))
1490 return;
1491
1492 // Read the comma followed by a second string literal.
1493 std::string ValueString;
1494 if (Tok.isNot(tok::comma)) {
1495 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1496 return;
1497 }
1498
1499 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1500 /*MacroExpansion=*/true))
1501 return;
1502
1503 if (Tok.isNot(tok::r_paren)) {
Stephen Hines651f13c2014-04-23 16:59:28 -07001504 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballmana7ff62f2013-06-04 02:07:14 +00001505 return;
1506 }
1507 PP.Lex(Tok); // Eat the r_paren.
1508
1509 if (Tok.isNot(tok::eod)) {
1510 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1511 return;
1512 }
1513
1514 // If the pragma is lexically sound, notify any interested PPCallbacks.
1515 if (PP.getPPCallbacks())
1516 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1517 ValueString);
1518
1519 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1520}
1521
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001522/// \brief Handle the microsoft \#pragma comment extension.
1523///
1524/// The syntax is:
1525/// \code
1526/// #pragma comment(linker, "foo")
1527/// \endcode
1528/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1529/// "foo" is a string, which is fully macro expanded, and permits string
1530/// concatenation, embedded escape characters etc. See MSDN for more details.
1531void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1532 PragmaIntroducerKind Introducer,
1533 Token &Tok) {
1534 SourceLocation CommentLoc = Tok.getLocation();
1535 PP.Lex(Tok);
1536 if (Tok.isNot(tok::l_paren)) {
1537 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1538 return;
1539 }
1540
1541 // Read the identifier.
1542 PP.Lex(Tok);
1543 if (Tok.isNot(tok::identifier)) {
1544 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1545 return;
1546 }
1547
1548 // Verify that this is one of the 5 whitelisted options.
Reid Kleckner3190ca92013-05-08 13:44:39 +00001549 IdentifierInfo *II = Tok.getIdentifierInfo();
1550 Sema::PragmaMSCommentKind Kind =
1551 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1552 .Case("linker", Sema::PCK_Linker)
1553 .Case("lib", Sema::PCK_Lib)
1554 .Case("compiler", Sema::PCK_Compiler)
1555 .Case("exestr", Sema::PCK_ExeStr)
1556 .Case("user", Sema::PCK_User)
1557 .Default(Sema::PCK_Unknown);
1558 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001559 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1560 return;
1561 }
1562
1563 // Read the optional string if present.
1564 PP.Lex(Tok);
1565 std::string ArgumentString;
1566 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1567 "pragma comment",
1568 /*MacroExpansion=*/true))
1569 return;
1570
Reid Kleckner3190ca92013-05-08 13:44:39 +00001571 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001572 // FIXME: If the kind is "compiler" warn if the string is present (it is
1573 // ignored).
Reid Kleckner3190ca92013-05-08 13:44:39 +00001574 // The MSDN docs say that "lib" and "linker" require a string and have a short
1575 // whitelist of linker options they support, but in practice MSVC doesn't
1576 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001577
1578 if (Tok.isNot(tok::r_paren)) {
1579 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1580 return;
1581 }
1582 PP.Lex(Tok); // eat the r_paren.
1583
1584 if (Tok.isNot(tok::eod)) {
1585 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1586 return;
1587 }
1588
1589 // If the pragma is lexically sound, notify any interested PPCallbacks.
1590 if (PP.getPPCallbacks())
1591 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
Reid Kleckner3190ca92013-05-08 13:44:39 +00001592
1593 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner7adf79a2013-05-06 21:02:12 +00001594}
Stephen Hines6bcf27b2014-05-29 04:14:42 -07001595
1596// #pragma clang optimize off
1597// #pragma clang optimize on
1598void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1599 PragmaIntroducerKind Introducer,
1600 Token &FirstToken) {
1601 Token Tok;
1602 PP.Lex(Tok);
1603 if (Tok.is(tok::eod)) {
1604 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
1605 return;
1606 }
1607 if (Tok.isNot(tok::identifier)) {
1608 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1609 << PP.getSpelling(Tok);
1610 return;
1611 }
1612 const IdentifierInfo *II = Tok.getIdentifierInfo();
1613 // The only accepted values are 'on' or 'off'.
1614 bool IsOn = false;
1615 if (II->isStr("on")) {
1616 IsOn = true;
1617 } else if (!II->isStr("off")) {
1618 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1619 << PP.getSpelling(Tok);
1620 return;
1621 }
1622 PP.Lex(Tok);
1623
1624 if (Tok.isNot(tok::eod)) {
1625 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1626 << PP.getSpelling(Tok);
1627 return;
1628 }
1629
1630 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1631}
Stephen Hinesc568f1e2014-07-21 00:47:37 -07001632
1633/// \brief Handle the \#pragma clang loop directive.
1634/// #pragma clang 'loop' loop-hints
1635///
1636/// loop-hints:
1637/// loop-hint loop-hints[opt]
1638///
1639/// loop-hint:
1640/// 'vectorize' '(' loop-hint-keyword ')'
1641/// 'interleave' '(' loop-hint-keyword ')'
1642/// 'unroll' '(' loop-hint-keyword ')'
1643/// 'vectorize_width' '(' loop-hint-value ')'
1644/// 'interleave_count' '(' loop-hint-value ')'
1645/// 'unroll_count' '(' loop-hint-value ')'
1646///
1647/// loop-hint-keyword:
1648/// 'enable'
1649/// 'disable'
1650///
1651/// loop-hint-value:
1652/// constant-expression
1653///
1654/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1655/// try vectorizing the instructions of the loop it precedes. Specifying
1656/// interleave(enable) or interleave_count(_value_) instructs llvm to try
1657/// interleaving multiple iterations of the loop it precedes. The width of the
1658/// vector instructions is specified by vectorize_width() and the number of
1659/// interleaved loop iterations is specified by interleave_count(). Specifying a
1660/// value of 1 effectively disables vectorization/interleaving, even if it is
1661/// possible and profitable, and 0 is invalid. The loop vectorizer currently
1662/// only works on inner loops.
1663///
1664/// The unroll and unroll_count directives control the concatenation
1665/// unroller. Specifying unroll(enable) instructs llvm to try to
1666/// unroll the loop completely, and unroll(disable) disables unrolling
1667/// for the loop. Specifying unroll_count(_value_) instructs llvm to
1668/// try to unroll the loop the number of times indicated by the value.
1669/// If unroll(enable) and unroll_count are both specified only
1670/// unroll_count takes effect.
1671void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1672 PragmaIntroducerKind Introducer,
1673 Token &Tok) {
1674 Token Loop = Tok;
1675 SmallVector<Token, 1> TokenList;
1676
1677 // Lex the optimization option and verify it is an identifier.
1678 PP.Lex(Tok);
1679 if (Tok.isNot(tok::identifier)) {
1680 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1681 << /*MissingOption=*/true << "";
1682 return;
1683 }
1684
1685 while (Tok.is(tok::identifier)) {
1686 Token Option = Tok;
1687 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
1688
1689 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
1690 .Case("vectorize", true)
1691 .Case("interleave", true)
1692 .Case("unroll", true)
1693 .Case("vectorize_width", true)
1694 .Case("interleave_count", true)
1695 .Case("unroll_count", true)
1696 .Default(false);
1697 if (!OptionValid) {
1698 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1699 << /*MissingOption=*/false << OptionInfo;
1700 return;
1701 }
1702
1703 // Read '('
1704 PP.Lex(Tok);
1705 if (Tok.isNot(tok::l_paren)) {
1706 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
1707 return;
1708 }
1709
1710 // FIXME: All tokens between '(' and ')' should be stored and parsed as a
1711 // constant expression.
1712 PP.Lex(Tok);
1713 if (Tok.is(tok::r_paren)) {
1714 // Nothing between the parentheses.
1715 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_missing_argument)
1716 << OptionInfo;
1717 return;
1718 }
1719 Token Value = Tok;
1720
1721 // Read ')'
1722 PP.Lex(Tok);
1723 if (Tok.isNot(tok::r_paren)) {
1724 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1725 return;
1726 }
1727
1728 // Get next optimization option.
1729 PP.Lex(Tok);
1730
1731 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
1732 Info->Loop = Loop;
1733 Info->Option = Option;
1734 Info->Value = Value;
1735
1736 // Generate the vectorization hint token.
1737 Token LoopHintTok;
1738 LoopHintTok.startToken();
1739 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
1740 LoopHintTok.setLocation(Loop.getLocation());
1741 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
1742 TokenList.push_back(LoopHintTok);
1743 }
1744
1745 if (Tok.isNot(tok::eod)) {
1746 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1747 << "clang loop";
1748 return;
1749 }
1750
1751 Token *TokenArray = new Token[TokenList.size()];
1752 std::copy(TokenList.begin(), TokenList.end(), TokenArray);
1753
1754 PP.EnterTokenStream(TokenArray, TokenList.size(),
1755 /*DisableMacroExpansion=*/false,
1756 /*OwnsTokens=*/true);
1757}