1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the language specific #pragma handlers.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "RAIIObjectsForParser.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Parse/ParseDiagnostic.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Sema/LoopHint.h"
21 #include "clang/Sema/Scope.h"
22 #include "llvm/ADT/StringSwitch.h"
23 using namespace clang;
24
25 namespace {
26
27 struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon302a61390111::PragmaAlignHandler28 explicit PragmaAlignHandler() : PragmaHandler("align") {}
29 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
30 Token &FirstToken) override;
31 };
32
33 struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon302a61390111::PragmaGCCVisibilityHandler34 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
35 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
36 Token &FirstToken) override;
37 };
38
39 struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon302a61390111::PragmaOptionsHandler40 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
41 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
42 Token &FirstToken) override;
43 };
44
45 struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon302a61390111::PragmaPackHandler46 explicit PragmaPackHandler() : PragmaHandler("pack") {}
47 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
48 Token &FirstToken) override;
49 };
50
51 struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon302a61390111::PragmaMSStructHandler52 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
53 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
54 Token &FirstToken) override;
55 };
56
57 struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon302a61390111::PragmaUnusedHandler58 PragmaUnusedHandler() : PragmaHandler("unused") {}
59 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
60 Token &FirstToken) override;
61 };
62
63 struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon302a61390111::PragmaWeakHandler64 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
65 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
66 Token &FirstToken) override;
67 };
68
69 struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon302a61390111::PragmaRedefineExtnameHandler70 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
71 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
72 Token &FirstToken) override;
73 };
74
75 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon302a61390111::PragmaOpenCLExtensionHandler76 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
77 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
78 Token &FirstToken) override;
79 };
80
81
82 struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon302a61390111::PragmaFPContractHandler83 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
84 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
85 Token &FirstToken) override;
86 };
87
88 struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon302a61390111::PragmaNoOpenMPHandler89 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
90 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
91 Token &FirstToken) override;
92 };
93
94 struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon302a61390111::PragmaOpenMPHandler95 PragmaOpenMPHandler() : PragmaHandler("omp") { }
96 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
97 Token &FirstToken) override;
98 };
99
100 /// PragmaCommentHandler - "\#pragma comment ...".
101 struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon302a61390111::PragmaCommentHandler102 PragmaCommentHandler(Sema &Actions)
103 : PragmaHandler("comment"), Actions(Actions) {}
104 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
105 Token &FirstToken) override;
106 private:
107 Sema &Actions;
108 };
109
110 struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon302a61390111::PragmaDetectMismatchHandler111 PragmaDetectMismatchHandler(Sema &Actions)
112 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
113 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
114 Token &FirstToken) override;
115 private:
116 Sema &Actions;
117 };
118
119 struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon302a61390111::PragmaMSPointersToMembers120 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
121 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
122 Token &FirstToken) override;
123 };
124
125 struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon302a61390111::PragmaMSVtorDisp126 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
127 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
128 Token &FirstToken) override;
129 };
130
131 struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon302a61390111::PragmaMSPragma132 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
133 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
134 Token &FirstToken) override;
135 };
136
137 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
138 struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon302a61390111::PragmaOptimizeHandler139 PragmaOptimizeHandler(Sema &S)
140 : PragmaHandler("optimize"), Actions(S) {}
141 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
142 Token &FirstToken) override;
143 private:
144 Sema &Actions;
145 };
146
147 struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon302a61390111::PragmaLoopHintHandler148 PragmaLoopHintHandler() : PragmaHandler("loop") {}
149 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
150 Token &FirstToken) override;
151 };
152
153 struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon302a61390111::PragmaUnrollHintHandler154 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
155 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
156 Token &FirstToken) override;
157 };
158
159 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler__anon302a61390111::PragmaMSRuntimeChecksHandler160 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
161 };
162
163 } // end namespace
164
initializePragmaHandlers()165 void Parser::initializePragmaHandlers() {
166 AlignHandler.reset(new PragmaAlignHandler());
167 PP.AddPragmaHandler(AlignHandler.get());
168
169 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
170 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
171
172 OptionsHandler.reset(new PragmaOptionsHandler());
173 PP.AddPragmaHandler(OptionsHandler.get());
174
175 PackHandler.reset(new PragmaPackHandler());
176 PP.AddPragmaHandler(PackHandler.get());
177
178 MSStructHandler.reset(new PragmaMSStructHandler());
179 PP.AddPragmaHandler(MSStructHandler.get());
180
181 UnusedHandler.reset(new PragmaUnusedHandler());
182 PP.AddPragmaHandler(UnusedHandler.get());
183
184 WeakHandler.reset(new PragmaWeakHandler());
185 PP.AddPragmaHandler(WeakHandler.get());
186
187 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
188 PP.AddPragmaHandler(RedefineExtnameHandler.get());
189
190 FPContractHandler.reset(new PragmaFPContractHandler());
191 PP.AddPragmaHandler("STDC", FPContractHandler.get());
192
193 if (getLangOpts().OpenCL) {
194 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
195 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
196
197 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
198 }
199 if (getLangOpts().OpenMP)
200 OpenMPHandler.reset(new PragmaOpenMPHandler());
201 else
202 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
203 PP.AddPragmaHandler(OpenMPHandler.get());
204
205 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
206 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
207 PP.AddPragmaHandler(MSCommentHandler.get());
208 }
209
210 if (getLangOpts().MicrosoftExt) {
211 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
212 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
213 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
214 PP.AddPragmaHandler(MSPointersToMembers.get());
215 MSVtorDisp.reset(new PragmaMSVtorDisp());
216 PP.AddPragmaHandler(MSVtorDisp.get());
217 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
218 PP.AddPragmaHandler(MSInitSeg.get());
219 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
220 PP.AddPragmaHandler(MSDataSeg.get());
221 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
222 PP.AddPragmaHandler(MSBSSSeg.get());
223 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
224 PP.AddPragmaHandler(MSConstSeg.get());
225 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
226 PP.AddPragmaHandler(MSCodeSeg.get());
227 MSSection.reset(new PragmaMSPragma("section"));
228 PP.AddPragmaHandler(MSSection.get());
229 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
230 PP.AddPragmaHandler(MSRuntimeChecks.get());
231 }
232
233 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
234 PP.AddPragmaHandler("clang", OptimizeHandler.get());
235
236 LoopHintHandler.reset(new PragmaLoopHintHandler());
237 PP.AddPragmaHandler("clang", LoopHintHandler.get());
238
239 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
240 PP.AddPragmaHandler(UnrollHintHandler.get());
241
242 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
243 PP.AddPragmaHandler(NoUnrollHintHandler.get());
244 }
245
resetPragmaHandlers()246 void Parser::resetPragmaHandlers() {
247 // Remove the pragma handlers we installed.
248 PP.RemovePragmaHandler(AlignHandler.get());
249 AlignHandler.reset();
250 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
251 GCCVisibilityHandler.reset();
252 PP.RemovePragmaHandler(OptionsHandler.get());
253 OptionsHandler.reset();
254 PP.RemovePragmaHandler(PackHandler.get());
255 PackHandler.reset();
256 PP.RemovePragmaHandler(MSStructHandler.get());
257 MSStructHandler.reset();
258 PP.RemovePragmaHandler(UnusedHandler.get());
259 UnusedHandler.reset();
260 PP.RemovePragmaHandler(WeakHandler.get());
261 WeakHandler.reset();
262 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
263 RedefineExtnameHandler.reset();
264
265 if (getLangOpts().OpenCL) {
266 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
267 OpenCLExtensionHandler.reset();
268 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
269 }
270 PP.RemovePragmaHandler(OpenMPHandler.get());
271 OpenMPHandler.reset();
272
273 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
274 PP.RemovePragmaHandler(MSCommentHandler.get());
275 MSCommentHandler.reset();
276 }
277
278 if (getLangOpts().MicrosoftExt) {
279 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
280 MSDetectMismatchHandler.reset();
281 PP.RemovePragmaHandler(MSPointersToMembers.get());
282 MSPointersToMembers.reset();
283 PP.RemovePragmaHandler(MSVtorDisp.get());
284 MSVtorDisp.reset();
285 PP.RemovePragmaHandler(MSInitSeg.get());
286 MSInitSeg.reset();
287 PP.RemovePragmaHandler(MSDataSeg.get());
288 MSDataSeg.reset();
289 PP.RemovePragmaHandler(MSBSSSeg.get());
290 MSBSSSeg.reset();
291 PP.RemovePragmaHandler(MSConstSeg.get());
292 MSConstSeg.reset();
293 PP.RemovePragmaHandler(MSCodeSeg.get());
294 MSCodeSeg.reset();
295 PP.RemovePragmaHandler(MSSection.get());
296 MSSection.reset();
297 PP.RemovePragmaHandler(MSRuntimeChecks.get());
298 MSRuntimeChecks.reset();
299 }
300
301 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
302 FPContractHandler.reset();
303
304 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
305 OptimizeHandler.reset();
306
307 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
308 LoopHintHandler.reset();
309
310 PP.RemovePragmaHandler(UnrollHintHandler.get());
311 UnrollHintHandler.reset();
312
313 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
314 NoUnrollHintHandler.reset();
315 }
316
317 /// \brief Handle the annotation token produced for #pragma unused(...)
318 ///
319 /// Each annot_pragma_unused is followed by the argument token so e.g.
320 /// "#pragma unused(x,y)" becomes:
321 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()322 void Parser::HandlePragmaUnused() {
323 assert(Tok.is(tok::annot_pragma_unused));
324 SourceLocation UnusedLoc = ConsumeToken();
325 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
326 ConsumeToken(); // The argument token.
327 }
328
HandlePragmaVisibility()329 void Parser::HandlePragmaVisibility() {
330 assert(Tok.is(tok::annot_pragma_vis));
331 const IdentifierInfo *VisType =
332 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
333 SourceLocation VisLoc = ConsumeToken();
334 Actions.ActOnPragmaVisibility(VisType, VisLoc);
335 }
336
337 namespace {
338 struct PragmaPackInfo {
339 Sema::PragmaPackKind Kind;
340 IdentifierInfo *Name;
341 Token Alignment;
342 SourceLocation LParenLoc;
343 SourceLocation RParenLoc;
344 };
345 } // end anonymous namespace
346
HandlePragmaPack()347 void Parser::HandlePragmaPack() {
348 assert(Tok.is(tok::annot_pragma_pack));
349 PragmaPackInfo *Info =
350 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
351 SourceLocation PragmaLoc = ConsumeToken();
352 ExprResult Alignment;
353 if (Info->Alignment.is(tok::numeric_constant)) {
354 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
355 if (Alignment.isInvalid())
356 return;
357 }
358 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
359 Info->LParenLoc, Info->RParenLoc);
360 }
361
HandlePragmaMSStruct()362 void Parser::HandlePragmaMSStruct() {
363 assert(Tok.is(tok::annot_pragma_msstruct));
364 Sema::PragmaMSStructKind Kind =
365 static_cast<Sema::PragmaMSStructKind>(
366 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
367 Actions.ActOnPragmaMSStruct(Kind);
368 ConsumeToken(); // The annotation token.
369 }
370
HandlePragmaAlign()371 void Parser::HandlePragmaAlign() {
372 assert(Tok.is(tok::annot_pragma_align));
373 Sema::PragmaOptionsAlignKind Kind =
374 static_cast<Sema::PragmaOptionsAlignKind>(
375 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
376 SourceLocation PragmaLoc = ConsumeToken();
377 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
378 }
379
HandlePragmaWeak()380 void Parser::HandlePragmaWeak() {
381 assert(Tok.is(tok::annot_pragma_weak));
382 SourceLocation PragmaLoc = ConsumeToken();
383 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
384 Tok.getLocation());
385 ConsumeToken(); // The weak name.
386 }
387
HandlePragmaWeakAlias()388 void Parser::HandlePragmaWeakAlias() {
389 assert(Tok.is(tok::annot_pragma_weakalias));
390 SourceLocation PragmaLoc = ConsumeToken();
391 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
392 SourceLocation WeakNameLoc = Tok.getLocation();
393 ConsumeToken();
394 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
395 SourceLocation AliasNameLoc = Tok.getLocation();
396 ConsumeToken();
397 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
398 WeakNameLoc, AliasNameLoc);
399
400 }
401
HandlePragmaRedefineExtname()402 void Parser::HandlePragmaRedefineExtname() {
403 assert(Tok.is(tok::annot_pragma_redefine_extname));
404 SourceLocation RedefLoc = ConsumeToken();
405 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
406 SourceLocation RedefNameLoc = Tok.getLocation();
407 ConsumeToken();
408 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
409 SourceLocation AliasNameLoc = Tok.getLocation();
410 ConsumeToken();
411 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
412 RedefNameLoc, AliasNameLoc);
413 }
414
HandlePragmaFPContract()415 void Parser::HandlePragmaFPContract() {
416 assert(Tok.is(tok::annot_pragma_fp_contract));
417 tok::OnOffSwitch OOS =
418 static_cast<tok::OnOffSwitch>(
419 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
420 Actions.ActOnPragmaFPContract(OOS);
421 ConsumeToken(); // The annotation token.
422 }
423
HandlePragmaCaptured()424 StmtResult Parser::HandlePragmaCaptured()
425 {
426 assert(Tok.is(tok::annot_pragma_captured));
427 ConsumeToken();
428
429 if (Tok.isNot(tok::l_brace)) {
430 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
431 return StmtError();
432 }
433
434 SourceLocation Loc = Tok.getLocation();
435
436 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
437 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
438 /*NumParams=*/1);
439
440 StmtResult R = ParseCompoundStatement();
441 CapturedRegionScope.Exit();
442
443 if (R.isInvalid()) {
444 Actions.ActOnCapturedRegionError();
445 return StmtError();
446 }
447
448 return Actions.ActOnCapturedRegionEnd(R.get());
449 }
450
451 namespace {
452 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
453 }
454
HandlePragmaOpenCLExtension()455 void Parser::HandlePragmaOpenCLExtension() {
456 assert(Tok.is(tok::annot_pragma_opencl_extension));
457 OpenCLExtData data =
458 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
459 unsigned state = data.getInt();
460 IdentifierInfo *ename = data.getPointer();
461 SourceLocation NameLoc = Tok.getLocation();
462 ConsumeToken(); // The annotation token.
463
464 OpenCLOptions &f = Actions.getOpenCLOptions();
465 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
466 // overriding all previously issued extension directives, but only if the
467 // behavior is set to disable."
468 if (state == 0 && ename->isStr("all")) {
469 #define OPENCLEXT(nm) f.nm = 0;
470 #include "clang/Basic/OpenCLExtensions.def"
471 }
472 #define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
473 #include "clang/Basic/OpenCLExtensions.def"
474 else {
475 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
476 return;
477 }
478 }
479
HandlePragmaMSPointersToMembers()480 void Parser::HandlePragmaMSPointersToMembers() {
481 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
482 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
483 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
484 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
485 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
486 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
487 }
488
HandlePragmaMSVtorDisp()489 void Parser::HandlePragmaMSVtorDisp() {
490 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
491 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
492 Sema::PragmaVtorDispKind Kind =
493 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
494 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
495 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
496 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
497 }
498
HandlePragmaMSPragma()499 void Parser::HandlePragmaMSPragma() {
500 assert(Tok.is(tok::annot_pragma_ms_pragma));
501 // Grab the tokens out of the annotation and enter them into the stream.
502 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
503 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
504 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
505 assert(Tok.isAnyIdentifier());
506 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
507 PP.Lex(Tok); // pragma kind
508
509 // Figure out which #pragma we're dealing with. The switch has no default
510 // because lex shouldn't emit the annotation token for unrecognized pragmas.
511 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
512 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
513 .Case("data_seg", &Parser::HandlePragmaMSSegment)
514 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
515 .Case("const_seg", &Parser::HandlePragmaMSSegment)
516 .Case("code_seg", &Parser::HandlePragmaMSSegment)
517 .Case("section", &Parser::HandlePragmaMSSection)
518 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
519
520 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
521 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
522 // until eof (really end of line) to prevent follow-on errors.
523 while (Tok.isNot(tok::eof))
524 PP.Lex(Tok);
525 PP.Lex(Tok);
526 }
527 }
528
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)529 bool Parser::HandlePragmaMSSection(StringRef PragmaName,
530 SourceLocation PragmaLocation) {
531 if (Tok.isNot(tok::l_paren)) {
532 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
533 return false;
534 }
535 PP.Lex(Tok); // (
536 // Parsing code for pragma section
537 if (Tok.isNot(tok::string_literal)) {
538 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
539 << PragmaName;
540 return false;
541 }
542 ExprResult StringResult = ParseStringLiteralExpression();
543 if (StringResult.isInvalid())
544 return false; // Already diagnosed.
545 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
546 if (SegmentName->getCharByteWidth() != 1) {
547 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
548 << PragmaName;
549 return false;
550 }
551 int SectionFlags = ASTContext::PSF_Read;
552 bool SectionFlagsAreDefault = true;
553 while (Tok.is(tok::comma)) {
554 PP.Lex(Tok); // ,
555 // Ignore "long" and "short".
556 // They are undocumented, but widely used, section attributes which appear
557 // to do nothing.
558 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
559 PP.Lex(Tok); // long/short
560 continue;
561 }
562
563 if (!Tok.isAnyIdentifier()) {
564 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
565 << PragmaName;
566 return false;
567 }
568 ASTContext::PragmaSectionFlag Flag =
569 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
570 Tok.getIdentifierInfo()->getName())
571 .Case("read", ASTContext::PSF_Read)
572 .Case("write", ASTContext::PSF_Write)
573 .Case("execute", ASTContext::PSF_Execute)
574 .Case("shared", ASTContext::PSF_Invalid)
575 .Case("nopage", ASTContext::PSF_Invalid)
576 .Case("nocache", ASTContext::PSF_Invalid)
577 .Case("discard", ASTContext::PSF_Invalid)
578 .Case("remove", ASTContext::PSF_Invalid)
579 .Default(ASTContext::PSF_None);
580 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
581 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
582 ? diag::warn_pragma_invalid_specific_action
583 : diag::warn_pragma_unsupported_action)
584 << PragmaName << Tok.getIdentifierInfo()->getName();
585 return false;
586 }
587 SectionFlags |= Flag;
588 SectionFlagsAreDefault = false;
589 PP.Lex(Tok); // Identifier
590 }
591 // If no section attributes are specified, the section will be marked as
592 // read/write.
593 if (SectionFlagsAreDefault)
594 SectionFlags |= ASTContext::PSF_Write;
595 if (Tok.isNot(tok::r_paren)) {
596 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
597 return false;
598 }
599 PP.Lex(Tok); // )
600 if (Tok.isNot(tok::eof)) {
601 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
602 << PragmaName;
603 return false;
604 }
605 PP.Lex(Tok); // eof
606 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
607 return true;
608 }
609
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)610 bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
611 SourceLocation PragmaLocation) {
612 if (Tok.isNot(tok::l_paren)) {
613 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
614 return false;
615 }
616 PP.Lex(Tok); // (
617 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
618 StringRef SlotLabel;
619 if (Tok.isAnyIdentifier()) {
620 StringRef PushPop = Tok.getIdentifierInfo()->getName();
621 if (PushPop == "push")
622 Action = Sema::PSK_Push;
623 else if (PushPop == "pop")
624 Action = Sema::PSK_Pop;
625 else {
626 PP.Diag(PragmaLocation,
627 diag::warn_pragma_expected_section_push_pop_or_name)
628 << PragmaName;
629 return false;
630 }
631 if (Action != Sema::PSK_Reset) {
632 PP.Lex(Tok); // push | pop
633 if (Tok.is(tok::comma)) {
634 PP.Lex(Tok); // ,
635 // If we've got a comma, we either need a label or a string.
636 if (Tok.isAnyIdentifier()) {
637 SlotLabel = Tok.getIdentifierInfo()->getName();
638 PP.Lex(Tok); // identifier
639 if (Tok.is(tok::comma))
640 PP.Lex(Tok);
641 else if (Tok.isNot(tok::r_paren)) {
642 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
643 << PragmaName;
644 return false;
645 }
646 }
647 } else if (Tok.isNot(tok::r_paren)) {
648 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
649 return false;
650 }
651 }
652 }
653 // Grab the string literal for our section name.
654 StringLiteral *SegmentName = nullptr;
655 if (Tok.isNot(tok::r_paren)) {
656 if (Tok.isNot(tok::string_literal)) {
657 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
658 diag::warn_pragma_expected_section_name :
659 diag::warn_pragma_expected_section_label_or_name :
660 diag::warn_pragma_expected_section_push_pop_or_name;
661 PP.Diag(PragmaLocation, DiagID) << PragmaName;
662 return false;
663 }
664 ExprResult StringResult = ParseStringLiteralExpression();
665 if (StringResult.isInvalid())
666 return false; // Already diagnosed.
667 SegmentName = cast<StringLiteral>(StringResult.get());
668 if (SegmentName->getCharByteWidth() != 1) {
669 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
670 << PragmaName;
671 return false;
672 }
673 // Setting section "" has no effect
674 if (SegmentName->getLength())
675 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
676 }
677 if (Tok.isNot(tok::r_paren)) {
678 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
679 return false;
680 }
681 PP.Lex(Tok); // )
682 if (Tok.isNot(tok::eof)) {
683 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
684 << PragmaName;
685 return false;
686 }
687 PP.Lex(Tok); // eof
688 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
689 SegmentName, PragmaName);
690 return true;
691 }
692
693 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)694 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
695 SourceLocation PragmaLocation) {
696 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
697 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
698 return false;
699 }
700
701 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
702 PragmaName))
703 return false;
704
705 // Parse either the known section names or the string section name.
706 StringLiteral *SegmentName = nullptr;
707 if (Tok.isAnyIdentifier()) {
708 auto *II = Tok.getIdentifierInfo();
709 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
710 .Case("compiler", "\".CRT$XCC\"")
711 .Case("lib", "\".CRT$XCL\"")
712 .Case("user", "\".CRT$XCU\"")
713 .Default("");
714
715 if (!Section.empty()) {
716 // Pretend the user wrote the appropriate string literal here.
717 Token Toks[1];
718 Toks[0].startToken();
719 Toks[0].setKind(tok::string_literal);
720 Toks[0].setLocation(Tok.getLocation());
721 Toks[0].setLiteralData(Section.data());
722 Toks[0].setLength(Section.size());
723 SegmentName =
724 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
725 PP.Lex(Tok);
726 }
727 } else if (Tok.is(tok::string_literal)) {
728 ExprResult StringResult = ParseStringLiteralExpression();
729 if (StringResult.isInvalid())
730 return false;
731 SegmentName = cast<StringLiteral>(StringResult.get());
732 if (SegmentName->getCharByteWidth() != 1) {
733 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
734 << PragmaName;
735 return false;
736 }
737 // FIXME: Add support for the '[, func-name]' part of the pragma.
738 }
739
740 if (!SegmentName) {
741 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
742 return false;
743 }
744
745 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
746 PragmaName) ||
747 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
748 PragmaName))
749 return false;
750
751 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
752 return true;
753 }
754
755 namespace {
756 struct PragmaLoopHintInfo {
757 Token PragmaName;
758 Token Option;
759 ArrayRef<Token> Toks;
760 };
761 } // end anonymous namespace
762
PragmaLoopHintString(Token PragmaName,Token Option)763 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
764 std::string PragmaString;
765 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
766 PragmaString = "clang loop ";
767 PragmaString += Option.getIdentifierInfo()->getName();
768 } else {
769 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
770 "Unexpected pragma name");
771 PragmaString = "unroll";
772 }
773 return PragmaString;
774 }
775
HandlePragmaLoopHint(LoopHint & Hint)776 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
777 assert(Tok.is(tok::annot_pragma_loop_hint));
778 PragmaLoopHintInfo *Info =
779 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
780
781 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
782 Hint.PragmaNameLoc = IdentifierLoc::create(
783 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
784
785 // It is possible that the loop hint has no option identifier, such as
786 // #pragma unroll(4).
787 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
788 ? Info->Option.getIdentifierInfo()
789 : nullptr;
790 Hint.OptionLoc = IdentifierLoc::create(
791 Actions.Context, Info->Option.getLocation(), OptionInfo);
792
793 const Token *Toks = Info->Toks.data();
794 size_t TokSize = Info->Toks.size();
795
796 // Return a valid hint if pragma unroll or nounroll were specified
797 // without an argument.
798 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
799 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
800 if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) {
801 ConsumeToken(); // The annotation token.
802 Hint.Range = Info->PragmaName.getLocation();
803 return true;
804 }
805
806 // The constant expression is always followed by an eof token, which increases
807 // the TokSize by 1.
808 assert(TokSize > 0 &&
809 "PragmaLoopHintInfo::Toks must contain at least one token.");
810
811 // If no option is specified the argument is assumed to be a constant expr.
812 bool OptionUnroll = false;
813 bool StateOption = false;
814 if (OptionInfo) { // Pragma Unroll does not specify an option.
815 OptionUnroll = OptionInfo->isStr("unroll");
816 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
817 .Case("vectorize", true)
818 .Case("interleave", true)
819 .Case("unroll", true)
820 .Default(false);
821 }
822
823 // Verify loop hint has an argument.
824 if (Toks[0].is(tok::eof)) {
825 ConsumeToken(); // The annotation token.
826 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
827 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll;
828 return false;
829 }
830
831 // Validate the argument.
832 if (StateOption) {
833 ConsumeToken(); // The annotation token.
834 SourceLocation StateLoc = Toks[0].getLocation();
835 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
836 if (!StateInfo ||
837 (!StateInfo->isStr("enable") && !StateInfo->isStr("disable") &&
838 ((OptionUnroll && !StateInfo->isStr("full")) ||
839 (!OptionUnroll && !StateInfo->isStr("assume_safety"))))) {
840 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
841 << /*FullKeyword=*/OptionUnroll;
842 return false;
843 }
844 if (TokSize > 2)
845 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
846 << PragmaLoopHintString(Info->PragmaName, Info->Option);
847 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
848 } else {
849 // Enter constant expression including eof terminator into token stream.
850 PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false,
851 /*OwnsTokens=*/false);
852 ConsumeToken(); // The annotation token.
853
854 ExprResult R = ParseConstantExpression();
855
856 // Tokens following an error in an ill-formed constant expression will
857 // remain in the token stream and must be removed.
858 if (Tok.isNot(tok::eof)) {
859 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
860 << PragmaLoopHintString(Info->PragmaName, Info->Option);
861 while (Tok.isNot(tok::eof))
862 ConsumeAnyToken();
863 }
864
865 ConsumeToken(); // Consume the constant expression eof terminator.
866
867 if (R.isInvalid() ||
868 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
869 return false;
870
871 // Argument is a constant expression with an integer type.
872 Hint.ValueExpr = R.get();
873 }
874
875 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
876 Info->Toks[TokSize - 1].getLocation());
877 return true;
878 }
879
880 // #pragma GCC visibility comes in two variants:
881 // 'push' '(' [visibility] ')'
882 // 'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & VisTok)883 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
884 PragmaIntroducerKind Introducer,
885 Token &VisTok) {
886 SourceLocation VisLoc = VisTok.getLocation();
887
888 Token Tok;
889 PP.LexUnexpandedToken(Tok);
890
891 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
892
893 const IdentifierInfo *VisType;
894 if (PushPop && PushPop->isStr("pop")) {
895 VisType = nullptr;
896 } else if (PushPop && PushPop->isStr("push")) {
897 PP.LexUnexpandedToken(Tok);
898 if (Tok.isNot(tok::l_paren)) {
899 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
900 << "visibility";
901 return;
902 }
903 PP.LexUnexpandedToken(Tok);
904 VisType = Tok.getIdentifierInfo();
905 if (!VisType) {
906 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
907 << "visibility";
908 return;
909 }
910 PP.LexUnexpandedToken(Tok);
911 if (Tok.isNot(tok::r_paren)) {
912 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
913 << "visibility";
914 return;
915 }
916 } else {
917 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
918 << "visibility";
919 return;
920 }
921 SourceLocation EndLoc = Tok.getLocation();
922 PP.LexUnexpandedToken(Tok);
923 if (Tok.isNot(tok::eod)) {
924 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
925 << "visibility";
926 return;
927 }
928
929 Token *Toks = new Token[1];
930 Toks[0].startToken();
931 Toks[0].setKind(tok::annot_pragma_vis);
932 Toks[0].setLocation(VisLoc);
933 Toks[0].setAnnotationEndLoc(EndLoc);
934 Toks[0].setAnnotationValue(
935 const_cast<void*>(static_cast<const void*>(VisType)));
936 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
937 /*OwnsTokens=*/true);
938 }
939
940 // #pragma pack(...) comes in the following delicious flavors:
941 // pack '(' [integer] ')'
942 // pack '(' 'show' ')'
943 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & PackTok)944 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
945 PragmaIntroducerKind Introducer,
946 Token &PackTok) {
947 SourceLocation PackLoc = PackTok.getLocation();
948
949 Token Tok;
950 PP.Lex(Tok);
951 if (Tok.isNot(tok::l_paren)) {
952 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
953 return;
954 }
955
956 Sema::PragmaPackKind Kind = Sema::PPK_Default;
957 IdentifierInfo *Name = nullptr;
958 Token Alignment;
959 Alignment.startToken();
960 SourceLocation LParenLoc = Tok.getLocation();
961 PP.Lex(Tok);
962 if (Tok.is(tok::numeric_constant)) {
963 Alignment = Tok;
964
965 PP.Lex(Tok);
966
967 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
968 // the push/pop stack.
969 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
970 if (PP.getLangOpts().ApplePragmaPack)
971 Kind = Sema::PPK_Push;
972 } else if (Tok.is(tok::identifier)) {
973 const IdentifierInfo *II = Tok.getIdentifierInfo();
974 if (II->isStr("show")) {
975 Kind = Sema::PPK_Show;
976 PP.Lex(Tok);
977 } else {
978 if (II->isStr("push")) {
979 Kind = Sema::PPK_Push;
980 } else if (II->isStr("pop")) {
981 Kind = Sema::PPK_Pop;
982 } else {
983 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
984 return;
985 }
986 PP.Lex(Tok);
987
988 if (Tok.is(tok::comma)) {
989 PP.Lex(Tok);
990
991 if (Tok.is(tok::numeric_constant)) {
992 Alignment = Tok;
993
994 PP.Lex(Tok);
995 } else if (Tok.is(tok::identifier)) {
996 Name = Tok.getIdentifierInfo();
997 PP.Lex(Tok);
998
999 if (Tok.is(tok::comma)) {
1000 PP.Lex(Tok);
1001
1002 if (Tok.isNot(tok::numeric_constant)) {
1003 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1004 return;
1005 }
1006
1007 Alignment = Tok;
1008
1009 PP.Lex(Tok);
1010 }
1011 } else {
1012 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1013 return;
1014 }
1015 }
1016 }
1017 } else if (PP.getLangOpts().ApplePragmaPack) {
1018 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1019 // the push/pop stack.
1020 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
1021 Kind = Sema::PPK_Pop;
1022 }
1023
1024 if (Tok.isNot(tok::r_paren)) {
1025 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
1026 return;
1027 }
1028
1029 SourceLocation RParenLoc = Tok.getLocation();
1030 PP.Lex(Tok);
1031 if (Tok.isNot(tok::eod)) {
1032 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1033 return;
1034 }
1035
1036 PragmaPackInfo *Info =
1037 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
1038 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
1039 new (Info) PragmaPackInfo();
1040 Info->Kind = Kind;
1041 Info->Name = Name;
1042 Info->Alignment = Alignment;
1043 Info->LParenLoc = LParenLoc;
1044 Info->RParenLoc = RParenLoc;
1045
1046 Token *Toks =
1047 (Token*) PP.getPreprocessorAllocator().Allocate(
1048 sizeof(Token) * 1, llvm::alignOf<Token>());
1049 new (Toks) Token();
1050 Toks[0].startToken();
1051 Toks[0].setKind(tok::annot_pragma_pack);
1052 Toks[0].setLocation(PackLoc);
1053 Toks[0].setAnnotationEndLoc(RParenLoc);
1054 Toks[0].setAnnotationValue(static_cast<void*>(Info));
1055 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1056 /*OwnsTokens=*/false);
1057 }
1058
1059 // #pragma ms_struct on
1060 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & MSStructTok)1061 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1062 PragmaIntroducerKind Introducer,
1063 Token &MSStructTok) {
1064 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
1065
1066 Token Tok;
1067 PP.Lex(Tok);
1068 if (Tok.isNot(tok::identifier)) {
1069 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1070 return;
1071 }
1072 SourceLocation EndLoc = Tok.getLocation();
1073 const IdentifierInfo *II = Tok.getIdentifierInfo();
1074 if (II->isStr("on")) {
1075 Kind = Sema::PMSST_ON;
1076 PP.Lex(Tok);
1077 }
1078 else if (II->isStr("off") || II->isStr("reset"))
1079 PP.Lex(Tok);
1080 else {
1081 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1082 return;
1083 }
1084
1085 if (Tok.isNot(tok::eod)) {
1086 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1087 << "ms_struct";
1088 return;
1089 }
1090
1091 Token *Toks =
1092 (Token*) PP.getPreprocessorAllocator().Allocate(
1093 sizeof(Token) * 1, llvm::alignOf<Token>());
1094 new (Toks) Token();
1095 Toks[0].startToken();
1096 Toks[0].setKind(tok::annot_pragma_msstruct);
1097 Toks[0].setLocation(MSStructTok.getLocation());
1098 Toks[0].setAnnotationEndLoc(EndLoc);
1099 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1100 static_cast<uintptr_t>(Kind)));
1101 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1102 /*OwnsTokens=*/false);
1103 }
1104
1105 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1106 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)1107 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
1108 bool IsOptions) {
1109 Token Tok;
1110
1111 if (IsOptions) {
1112 PP.Lex(Tok);
1113 if (Tok.isNot(tok::identifier) ||
1114 !Tok.getIdentifierInfo()->isStr("align")) {
1115 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1116 return;
1117 }
1118 }
1119
1120 PP.Lex(Tok);
1121 if (Tok.isNot(tok::equal)) {
1122 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1123 << IsOptions;
1124 return;
1125 }
1126
1127 PP.Lex(Tok);
1128 if (Tok.isNot(tok::identifier)) {
1129 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1130 << (IsOptions ? "options" : "align");
1131 return;
1132 }
1133
1134 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
1135 const IdentifierInfo *II = Tok.getIdentifierInfo();
1136 if (II->isStr("native"))
1137 Kind = Sema::POAK_Native;
1138 else if (II->isStr("natural"))
1139 Kind = Sema::POAK_Natural;
1140 else if (II->isStr("packed"))
1141 Kind = Sema::POAK_Packed;
1142 else if (II->isStr("power"))
1143 Kind = Sema::POAK_Power;
1144 else if (II->isStr("mac68k"))
1145 Kind = Sema::POAK_Mac68k;
1146 else if (II->isStr("reset"))
1147 Kind = Sema::POAK_Reset;
1148 else {
1149 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1150 << IsOptions;
1151 return;
1152 }
1153
1154 SourceLocation EndLoc = Tok.getLocation();
1155 PP.Lex(Tok);
1156 if (Tok.isNot(tok::eod)) {
1157 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1158 << (IsOptions ? "options" : "align");
1159 return;
1160 }
1161
1162 Token *Toks =
1163 (Token*) PP.getPreprocessorAllocator().Allocate(
1164 sizeof(Token) * 1, llvm::alignOf<Token>());
1165 new (Toks) Token();
1166 Toks[0].startToken();
1167 Toks[0].setKind(tok::annot_pragma_align);
1168 Toks[0].setLocation(FirstTok.getLocation());
1169 Toks[0].setAnnotationEndLoc(EndLoc);
1170 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1171 static_cast<uintptr_t>(Kind)));
1172 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1173 /*OwnsTokens=*/false);
1174 }
1175
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & AlignTok)1176 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1177 PragmaIntroducerKind Introducer,
1178 Token &AlignTok) {
1179 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
1180 }
1181
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & OptionsTok)1182 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1183 PragmaIntroducerKind Introducer,
1184 Token &OptionsTok) {
1185 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
1186 }
1187
1188 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & UnusedTok)1189 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1190 PragmaIntroducerKind Introducer,
1191 Token &UnusedTok) {
1192 // FIXME: Should we be expanding macros here? My guess is no.
1193 SourceLocation UnusedLoc = UnusedTok.getLocation();
1194
1195 // Lex the left '('.
1196 Token Tok;
1197 PP.Lex(Tok);
1198 if (Tok.isNot(tok::l_paren)) {
1199 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1200 return;
1201 }
1202
1203 // Lex the declaration reference(s).
1204 SmallVector<Token, 5> Identifiers;
1205 SourceLocation RParenLoc;
1206 bool LexID = true;
1207
1208 while (true) {
1209 PP.Lex(Tok);
1210
1211 if (LexID) {
1212 if (Tok.is(tok::identifier)) {
1213 Identifiers.push_back(Tok);
1214 LexID = false;
1215 continue;
1216 }
1217
1218 // Illegal token!
1219 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1220 return;
1221 }
1222
1223 // We are execting a ')' or a ','.
1224 if (Tok.is(tok::comma)) {
1225 LexID = true;
1226 continue;
1227 }
1228
1229 if (Tok.is(tok::r_paren)) {
1230 RParenLoc = Tok.getLocation();
1231 break;
1232 }
1233
1234 // Illegal token!
1235 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
1236 return;
1237 }
1238
1239 PP.Lex(Tok);
1240 if (Tok.isNot(tok::eod)) {
1241 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1242 "unused";
1243 return;
1244 }
1245
1246 // Verify that we have a location for the right parenthesis.
1247 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
1248 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
1249
1250 // For each identifier token, insert into the token stream a
1251 // annot_pragma_unused token followed by the identifier token.
1252 // This allows us to cache a "#pragma unused" that occurs inside an inline
1253 // C++ member function.
1254
1255 Token *Toks =
1256 (Token*) PP.getPreprocessorAllocator().Allocate(
1257 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
1258 for (unsigned i=0; i != Identifiers.size(); i++) {
1259 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1260 pragmaUnusedTok.startToken();
1261 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1262 pragmaUnusedTok.setLocation(UnusedLoc);
1263 idTok = Identifiers[i];
1264 }
1265 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1266 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1267 }
1268
1269 // #pragma weak identifier
1270 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & WeakTok)1271 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1272 PragmaIntroducerKind Introducer,
1273 Token &WeakTok) {
1274 SourceLocation WeakLoc = WeakTok.getLocation();
1275
1276 Token Tok;
1277 PP.Lex(Tok);
1278 if (Tok.isNot(tok::identifier)) {
1279 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1280 return;
1281 }
1282
1283 Token WeakName = Tok;
1284 bool HasAlias = false;
1285 Token AliasName;
1286
1287 PP.Lex(Tok);
1288 if (Tok.is(tok::equal)) {
1289 HasAlias = true;
1290 PP.Lex(Tok);
1291 if (Tok.isNot(tok::identifier)) {
1292 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1293 << "weak";
1294 return;
1295 }
1296 AliasName = Tok;
1297 PP.Lex(Tok);
1298 }
1299
1300 if (Tok.isNot(tok::eod)) {
1301 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1302 return;
1303 }
1304
1305 if (HasAlias) {
1306 Token *Toks =
1307 (Token*) PP.getPreprocessorAllocator().Allocate(
1308 sizeof(Token) * 3, llvm::alignOf<Token>());
1309 Token &pragmaUnusedTok = Toks[0];
1310 pragmaUnusedTok.startToken();
1311 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1312 pragmaUnusedTok.setLocation(WeakLoc);
1313 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
1314 Toks[1] = WeakName;
1315 Toks[2] = AliasName;
1316 PP.EnterTokenStream(Toks, 3,
1317 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1318 } else {
1319 Token *Toks =
1320 (Token*) PP.getPreprocessorAllocator().Allocate(
1321 sizeof(Token) * 2, llvm::alignOf<Token>());
1322 Token &pragmaUnusedTok = Toks[0];
1323 pragmaUnusedTok.startToken();
1324 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1325 pragmaUnusedTok.setLocation(WeakLoc);
1326 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
1327 Toks[1] = WeakName;
1328 PP.EnterTokenStream(Toks, 2,
1329 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1330 }
1331 }
1332
1333 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & RedefToken)1334 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1335 PragmaIntroducerKind Introducer,
1336 Token &RedefToken) {
1337 SourceLocation RedefLoc = RedefToken.getLocation();
1338
1339 Token Tok;
1340 PP.Lex(Tok);
1341 if (Tok.isNot(tok::identifier)) {
1342 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1343 "redefine_extname";
1344 return;
1345 }
1346
1347 Token RedefName = Tok;
1348 PP.Lex(Tok);
1349
1350 if (Tok.isNot(tok::identifier)) {
1351 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1352 << "redefine_extname";
1353 return;
1354 }
1355
1356 Token AliasName = Tok;
1357 PP.Lex(Tok);
1358
1359 if (Tok.isNot(tok::eod)) {
1360 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1361 "redefine_extname";
1362 return;
1363 }
1364
1365 Token *Toks =
1366 (Token*) PP.getPreprocessorAllocator().Allocate(
1367 sizeof(Token) * 3, llvm::alignOf<Token>());
1368 Token &pragmaRedefTok = Toks[0];
1369 pragmaRedefTok.startToken();
1370 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1371 pragmaRedefTok.setLocation(RedefLoc);
1372 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
1373 Toks[1] = RedefName;
1374 Toks[2] = AliasName;
1375 PP.EnterTokenStream(Toks, 3,
1376 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
1377 }
1378
1379
1380 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1381 PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1382 PragmaIntroducerKind Introducer,
1383 Token &Tok) {
1384 tok::OnOffSwitch OOS;
1385 if (PP.LexOnOffSwitch(OOS))
1386 return;
1387
1388 Token *Toks =
1389 (Token*) PP.getPreprocessorAllocator().Allocate(
1390 sizeof(Token) * 1, llvm::alignOf<Token>());
1391 new (Toks) Token();
1392 Toks[0].startToken();
1393 Toks[0].setKind(tok::annot_pragma_fp_contract);
1394 Toks[0].setLocation(Tok.getLocation());
1395 Toks[0].setAnnotationEndLoc(Tok.getLocation());
1396 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1397 static_cast<uintptr_t>(OOS)));
1398 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1399 /*OwnsTokens=*/false);
1400 }
1401
1402 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1403 PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1404 PragmaIntroducerKind Introducer,
1405 Token &Tok) {
1406 PP.LexUnexpandedToken(Tok);
1407 if (Tok.isNot(tok::identifier)) {
1408 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1409 "OPENCL";
1410 return;
1411 }
1412 IdentifierInfo *ename = Tok.getIdentifierInfo();
1413 SourceLocation NameLoc = Tok.getLocation();
1414
1415 PP.Lex(Tok);
1416 if (Tok.isNot(tok::colon)) {
1417 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1418 return;
1419 }
1420
1421 PP.Lex(Tok);
1422 if (Tok.isNot(tok::identifier)) {
1423 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1424 return;
1425 }
1426 IdentifierInfo *op = Tok.getIdentifierInfo();
1427
1428 unsigned state;
1429 if (op->isStr("enable")) {
1430 state = 1;
1431 } else if (op->isStr("disable")) {
1432 state = 0;
1433 } else {
1434 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1435 return;
1436 }
1437 SourceLocation StateLoc = Tok.getLocation();
1438
1439 PP.Lex(Tok);
1440 if (Tok.isNot(tok::eod)) {
1441 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1442 "OPENCL EXTENSION";
1443 return;
1444 }
1445
1446 OpenCLExtData data(ename, state);
1447 Token *Toks =
1448 (Token*) PP.getPreprocessorAllocator().Allocate(
1449 sizeof(Token) * 1, llvm::alignOf<Token>());
1450 new (Toks) Token();
1451 Toks[0].startToken();
1452 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1453 Toks[0].setLocation(NameLoc);
1454 Toks[0].setAnnotationValue(data.getOpaqueValue());
1455 Toks[0].setAnnotationEndLoc(StateLoc);
1456 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1457 /*OwnsTokens=*/false);
1458
1459 if (PP.getPPCallbacks())
1460 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1461 StateLoc, state);
1462 }
1463
1464 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1465 ///
1466 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1467 PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1468 PragmaIntroducerKind Introducer,
1469 Token &FirstTok) {
1470 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1471 FirstTok.getLocation())) {
1472 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1473 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1474 diag::Severity::Ignored, SourceLocation());
1475 }
1476 PP.DiscardUntilEndOfDirective();
1477 }
1478
1479 /// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1480 ///
1481 void
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstTok)1482 PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1483 PragmaIntroducerKind Introducer,
1484 Token &FirstTok) {
1485 SmallVector<Token, 16> Pragma;
1486 Token Tok;
1487 Tok.startToken();
1488 Tok.setKind(tok::annot_pragma_openmp);
1489 Tok.setLocation(FirstTok.getLocation());
1490
1491 while (Tok.isNot(tok::eod)) {
1492 Pragma.push_back(Tok);
1493 PP.Lex(Tok);
1494 }
1495 SourceLocation EodLoc = Tok.getLocation();
1496 Tok.startToken();
1497 Tok.setKind(tok::annot_pragma_openmp_end);
1498 Tok.setLocation(EodLoc);
1499 Pragma.push_back(Tok);
1500
1501 Token *Toks = new Token[Pragma.size()];
1502 std::copy(Pragma.begin(), Pragma.end(), Toks);
1503 PP.EnterTokenStream(Toks, Pragma.size(),
1504 /*DisableMacroExpansion=*/false, /*OwnsTokens=*/true);
1505 }
1506
1507 /// \brief Handle '#pragma pointers_to_members'
1508 // The grammar for this pragma is as follows:
1509 //
1510 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1511 //
1512 // #pragma pointers_to_members '(' 'best_case' ')'
1513 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1514 // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1515 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1516 PragmaIntroducerKind Introducer,
1517 Token &Tok) {
1518 SourceLocation PointersToMembersLoc = Tok.getLocation();
1519 PP.Lex(Tok);
1520 if (Tok.isNot(tok::l_paren)) {
1521 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1522 << "pointers_to_members";
1523 return;
1524 }
1525 PP.Lex(Tok);
1526 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1527 if (!Arg) {
1528 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1529 << "pointers_to_members";
1530 return;
1531 }
1532 PP.Lex(Tok);
1533
1534 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
1535 if (Arg->isStr("best_case")) {
1536 RepresentationMethod = LangOptions::PPTMK_BestCase;
1537 } else {
1538 if (Arg->isStr("full_generality")) {
1539 if (Tok.is(tok::comma)) {
1540 PP.Lex(Tok);
1541
1542 Arg = Tok.getIdentifierInfo();
1543 if (!Arg) {
1544 PP.Diag(Tok.getLocation(),
1545 diag::err_pragma_pointers_to_members_unknown_kind)
1546 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1547 return;
1548 }
1549 PP.Lex(Tok);
1550 } else if (Tok.is(tok::r_paren)) {
1551 // #pragma pointers_to_members(full_generality) implicitly specifies
1552 // virtual_inheritance.
1553 Arg = nullptr;
1554 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1555 } else {
1556 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1557 << "full_generality";
1558 return;
1559 }
1560 }
1561
1562 if (Arg) {
1563 if (Arg->isStr("single_inheritance")) {
1564 RepresentationMethod =
1565 LangOptions::PPTMK_FullGeneralitySingleInheritance;
1566 } else if (Arg->isStr("multiple_inheritance")) {
1567 RepresentationMethod =
1568 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
1569 } else if (Arg->isStr("virtual_inheritance")) {
1570 RepresentationMethod =
1571 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
1572 } else {
1573 PP.Diag(Tok.getLocation(),
1574 diag::err_pragma_pointers_to_members_unknown_kind)
1575 << Arg << /*HasPointerDeclaration*/ 1;
1576 return;
1577 }
1578 }
1579 }
1580
1581 if (Tok.isNot(tok::r_paren)) {
1582 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1583 << (Arg ? Arg->getName() : "full_generality");
1584 return;
1585 }
1586
1587 SourceLocation EndLoc = Tok.getLocation();
1588 PP.Lex(Tok);
1589 if (Tok.isNot(tok::eod)) {
1590 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1591 << "pointers_to_members";
1592 return;
1593 }
1594
1595 Token AnnotTok;
1596 AnnotTok.startToken();
1597 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1598 AnnotTok.setLocation(PointersToMembersLoc);
1599 AnnotTok.setAnnotationEndLoc(EndLoc);
1600 AnnotTok.setAnnotationValue(
1601 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1602 PP.EnterToken(AnnotTok);
1603 }
1604
1605 /// \brief Handle '#pragma vtordisp'
1606 // The grammar for this pragma is as follows:
1607 //
1608 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1609 //
1610 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1611 // #pragma vtordisp '(' 'pop' ')'
1612 // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1613 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1614 PragmaIntroducerKind Introducer,
1615 Token &Tok) {
1616 SourceLocation VtorDispLoc = Tok.getLocation();
1617 PP.Lex(Tok);
1618 if (Tok.isNot(tok::l_paren)) {
1619 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1620 return;
1621 }
1622 PP.Lex(Tok);
1623
1624 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1625 const IdentifierInfo *II = Tok.getIdentifierInfo();
1626 if (II) {
1627 if (II->isStr("push")) {
1628 // #pragma vtordisp(push, mode)
1629 PP.Lex(Tok);
1630 if (Tok.isNot(tok::comma)) {
1631 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1632 return;
1633 }
1634 PP.Lex(Tok);
1635 Kind = Sema::PVDK_Push;
1636 // not push, could be on/off
1637 } else if (II->isStr("pop")) {
1638 // #pragma vtordisp(pop)
1639 PP.Lex(Tok);
1640 Kind = Sema::PVDK_Pop;
1641 }
1642 // not push or pop, could be on/off
1643 } else {
1644 if (Tok.is(tok::r_paren)) {
1645 // #pragma vtordisp()
1646 Kind = Sema::PVDK_Reset;
1647 }
1648 }
1649
1650
1651 uint64_t Value = 0;
1652 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1653 const IdentifierInfo *II = Tok.getIdentifierInfo();
1654 if (II && II->isStr("off")) {
1655 PP.Lex(Tok);
1656 Value = 0;
1657 } else if (II && II->isStr("on")) {
1658 PP.Lex(Tok);
1659 Value = 1;
1660 } else if (Tok.is(tok::numeric_constant) &&
1661 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1662 if (Value > 2) {
1663 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1664 << 0 << 2 << "vtordisp";
1665 return;
1666 }
1667 } else {
1668 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1669 << "vtordisp";
1670 return;
1671 }
1672 }
1673
1674 // Finish the pragma: ')' $
1675 if (Tok.isNot(tok::r_paren)) {
1676 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1677 return;
1678 }
1679 SourceLocation EndLoc = Tok.getLocation();
1680 PP.Lex(Tok);
1681 if (Tok.isNot(tok::eod)) {
1682 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1683 << "vtordisp";
1684 return;
1685 }
1686
1687 // Enter the annotation.
1688 Token AnnotTok;
1689 AnnotTok.startToken();
1690 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1691 AnnotTok.setLocation(VtorDispLoc);
1692 AnnotTok.setAnnotationEndLoc(EndLoc);
1693 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1694 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
1695 PP.EnterToken(AnnotTok);
1696 }
1697
1698 /// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1699 /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1700 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1701 PragmaIntroducerKind Introducer,
1702 Token &Tok) {
1703 Token EoF, AnnotTok;
1704 EoF.startToken();
1705 EoF.setKind(tok::eof);
1706 AnnotTok.startToken();
1707 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1708 AnnotTok.setLocation(Tok.getLocation());
1709 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1710 SmallVector<Token, 8> TokenVector;
1711 // Suck up all of the tokens before the eod.
1712 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
1713 TokenVector.push_back(Tok);
1714 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1715 }
1716 // Add a sentinal EoF token to the end of the list.
1717 TokenVector.push_back(EoF);
1718 // We must allocate this array with new because EnterTokenStream is going to
1719 // delete it later.
1720 Token *TokenArray = new Token[TokenVector.size()];
1721 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1722 auto Value = new (PP.getPreprocessorAllocator())
1723 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1724 AnnotTok.setAnnotationValue(Value);
1725 PP.EnterToken(AnnotTok);
1726 }
1727
1728 /// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1729 ///
1730 /// The syntax is:
1731 /// \code
1732 /// #pragma detect_mismatch("name", "value")
1733 /// \endcode
1734 /// Where 'name' and 'value' are quoted strings. The values are embedded in
1735 /// the object file and passed along to the linker. If the linker detects a
1736 /// mismatch in the object file's values for the given name, a LNK2038 error
1737 /// is emitted. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1738 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1739 PragmaIntroducerKind Introducer,
1740 Token &Tok) {
1741 SourceLocation CommentLoc = Tok.getLocation();
1742 PP.Lex(Tok);
1743 if (Tok.isNot(tok::l_paren)) {
1744 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
1745 return;
1746 }
1747
1748 // Read the name to embed, which must be a string literal.
1749 std::string NameString;
1750 if (!PP.LexStringLiteral(Tok, NameString,
1751 "pragma detect_mismatch",
1752 /*MacroExpansion=*/true))
1753 return;
1754
1755 // Read the comma followed by a second string literal.
1756 std::string ValueString;
1757 if (Tok.isNot(tok::comma)) {
1758 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1759 return;
1760 }
1761
1762 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1763 /*MacroExpansion=*/true))
1764 return;
1765
1766 if (Tok.isNot(tok::r_paren)) {
1767 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1768 return;
1769 }
1770 PP.Lex(Tok); // Eat the r_paren.
1771
1772 if (Tok.isNot(tok::eod)) {
1773 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1774 return;
1775 }
1776
1777 // If the pragma is lexically sound, notify any interested PPCallbacks.
1778 if (PP.getPPCallbacks())
1779 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1780 ValueString);
1781
1782 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1783 }
1784
1785 /// \brief Handle the microsoft \#pragma comment extension.
1786 ///
1787 /// The syntax is:
1788 /// \code
1789 /// #pragma comment(linker, "foo")
1790 /// \endcode
1791 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1792 /// "foo" is a string, which is fully macro expanded, and permits string
1793 /// concatenation, embedded escape characters etc. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1794 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1795 PragmaIntroducerKind Introducer,
1796 Token &Tok) {
1797 SourceLocation CommentLoc = Tok.getLocation();
1798 PP.Lex(Tok);
1799 if (Tok.isNot(tok::l_paren)) {
1800 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1801 return;
1802 }
1803
1804 // Read the identifier.
1805 PP.Lex(Tok);
1806 if (Tok.isNot(tok::identifier)) {
1807 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1808 return;
1809 }
1810
1811 // Verify that this is one of the 5 whitelisted options.
1812 IdentifierInfo *II = Tok.getIdentifierInfo();
1813 Sema::PragmaMSCommentKind Kind =
1814 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1815 .Case("linker", Sema::PCK_Linker)
1816 .Case("lib", Sema::PCK_Lib)
1817 .Case("compiler", Sema::PCK_Compiler)
1818 .Case("exestr", Sema::PCK_ExeStr)
1819 .Case("user", Sema::PCK_User)
1820 .Default(Sema::PCK_Unknown);
1821 if (Kind == Sema::PCK_Unknown) {
1822 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1823 return;
1824 }
1825
1826 // On PS4, issue a warning about any pragma comments other than
1827 // #pragma comment lib.
1828 if (PP.getTargetInfo().getTriple().isPS4() && Kind != Sema::PCK_Lib) {
1829 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
1830 << II->getName();
1831 return;
1832 }
1833
1834 // Read the optional string if present.
1835 PP.Lex(Tok);
1836 std::string ArgumentString;
1837 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1838 "pragma comment",
1839 /*MacroExpansion=*/true))
1840 return;
1841
1842 // FIXME: warn that 'exestr' is deprecated.
1843 // FIXME: If the kind is "compiler" warn if the string is present (it is
1844 // ignored).
1845 // The MSDN docs say that "lib" and "linker" require a string and have a short
1846 // whitelist of linker options they support, but in practice MSVC doesn't
1847 // issue a diagnostic. Therefore neither does clang.
1848
1849 if (Tok.isNot(tok::r_paren)) {
1850 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1851 return;
1852 }
1853 PP.Lex(Tok); // eat the r_paren.
1854
1855 if (Tok.isNot(tok::eod)) {
1856 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1857 return;
1858 }
1859
1860 // If the pragma is lexically sound, notify any interested PPCallbacks.
1861 if (PP.getPPCallbacks())
1862 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1863
1864 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
1865 }
1866
1867 // #pragma clang optimize off
1868 // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & FirstToken)1869 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1870 PragmaIntroducerKind Introducer,
1871 Token &FirstToken) {
1872 Token Tok;
1873 PP.Lex(Tok);
1874 if (Tok.is(tok::eod)) {
1875 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
1876 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
1877 return;
1878 }
1879 if (Tok.isNot(tok::identifier)) {
1880 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1881 << PP.getSpelling(Tok);
1882 return;
1883 }
1884 const IdentifierInfo *II = Tok.getIdentifierInfo();
1885 // The only accepted values are 'on' or 'off'.
1886 bool IsOn = false;
1887 if (II->isStr("on")) {
1888 IsOn = true;
1889 } else if (!II->isStr("off")) {
1890 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1891 << PP.getSpelling(Tok);
1892 return;
1893 }
1894 PP.Lex(Tok);
1895
1896 if (Tok.isNot(tok::eod)) {
1897 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1898 << PP.getSpelling(Tok);
1899 return;
1900 }
1901
1902 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1903 }
1904
1905 /// \brief Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)1906 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1907 Token Option, bool ValueInParens,
1908 PragmaLoopHintInfo &Info) {
1909 SmallVector<Token, 1> ValueList;
1910 int OpenParens = ValueInParens ? 1 : 0;
1911 // Read constant expression.
1912 while (Tok.isNot(tok::eod)) {
1913 if (Tok.is(tok::l_paren))
1914 OpenParens++;
1915 else if (Tok.is(tok::r_paren)) {
1916 OpenParens--;
1917 if (OpenParens == 0 && ValueInParens)
1918 break;
1919 }
1920
1921 ValueList.push_back(Tok);
1922 PP.Lex(Tok);
1923 }
1924
1925 if (ValueInParens) {
1926 // Read ')'
1927 if (Tok.isNot(tok::r_paren)) {
1928 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1929 return true;
1930 }
1931 PP.Lex(Tok);
1932 }
1933
1934 Token EOFTok;
1935 EOFTok.startToken();
1936 EOFTok.setKind(tok::eof);
1937 EOFTok.setLocation(Tok.getLocation());
1938 ValueList.push_back(EOFTok); // Terminates expression for parsing.
1939
1940 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
1941
1942 Info.PragmaName = PragmaName;
1943 Info.Option = Option;
1944 return false;
1945 }
1946
1947 /// \brief Handle the \#pragma clang loop directive.
1948 /// #pragma clang 'loop' loop-hints
1949 ///
1950 /// loop-hints:
1951 /// loop-hint loop-hints[opt]
1952 ///
1953 /// loop-hint:
1954 /// 'vectorize' '(' loop-hint-keyword ')'
1955 /// 'interleave' '(' loop-hint-keyword ')'
1956 /// 'unroll' '(' unroll-hint-keyword ')'
1957 /// 'vectorize_width' '(' loop-hint-value ')'
1958 /// 'interleave_count' '(' loop-hint-value ')'
1959 /// 'unroll_count' '(' loop-hint-value ')'
1960 ///
1961 /// loop-hint-keyword:
1962 /// 'enable'
1963 /// 'disable'
1964 /// 'assume_safety'
1965 ///
1966 /// unroll-hint-keyword:
1967 /// 'enable'
1968 /// 'disable'
1969 /// 'full'
1970 ///
1971 /// loop-hint-value:
1972 /// constant-expression
1973 ///
1974 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1975 /// try vectorizing the instructions of the loop it precedes. Specifying
1976 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
1977 /// interleaving multiple iterations of the loop it precedes. The width of the
1978 /// vector instructions is specified by vectorize_width() and the number of
1979 /// interleaved loop iterations is specified by interleave_count(). Specifying a
1980 /// value of 1 effectively disables vectorization/interleaving, even if it is
1981 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
1982 /// only works on inner loops.
1983 ///
1984 /// The unroll and unroll_count directives control the concatenation
1985 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
1986 /// completely if the trip count is known at compile time and unroll partially
1987 /// if the trip count is not known. Specifying unroll(full) is similar to
1988 /// unroll(enable) but will unroll the loop only if the trip count is known at
1989 /// compile time. Specifying unroll(disable) disables unrolling for the
1990 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
1991 /// loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)1992 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1993 PragmaIntroducerKind Introducer,
1994 Token &Tok) {
1995 // Incoming token is "loop" from "#pragma clang loop".
1996 Token PragmaName = Tok;
1997 SmallVector<Token, 1> TokenList;
1998
1999 // Lex the optimization option and verify it is an identifier.
2000 PP.Lex(Tok);
2001 if (Tok.isNot(tok::identifier)) {
2002 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2003 << /*MissingOption=*/true << "";
2004 return;
2005 }
2006
2007 while (Tok.is(tok::identifier)) {
2008 Token Option = Tok;
2009 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2010
2011 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
2012 .Case("vectorize", true)
2013 .Case("interleave", true)
2014 .Case("unroll", true)
2015 .Case("vectorize_width", true)
2016 .Case("interleave_count", true)
2017 .Case("unroll_count", true)
2018 .Default(false);
2019 if (!OptionValid) {
2020 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2021 << /*MissingOption=*/false << OptionInfo;
2022 return;
2023 }
2024 PP.Lex(Tok);
2025
2026 // Read '('
2027 if (Tok.isNot(tok::l_paren)) {
2028 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2029 return;
2030 }
2031 PP.Lex(Tok);
2032
2033 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2034 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2035 *Info))
2036 return;
2037
2038 // Generate the loop hint token.
2039 Token LoopHintTok;
2040 LoopHintTok.startToken();
2041 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
2042 LoopHintTok.setLocation(PragmaName.getLocation());
2043 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
2044 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2045 TokenList.push_back(LoopHintTok);
2046 }
2047
2048 if (Tok.isNot(tok::eod)) {
2049 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2050 << "clang loop";
2051 return;
2052 }
2053
2054 Token *TokenArray = new Token[TokenList.size()];
2055 std::copy(TokenList.begin(), TokenList.end(), TokenArray);
2056
2057 PP.EnterTokenStream(TokenArray, TokenList.size(),
2058 /*DisableMacroExpansion=*/false,
2059 /*OwnsTokens=*/true);
2060 }
2061
2062 /// \brief Handle the loop unroll optimization pragmas.
2063 /// #pragma unroll
2064 /// #pragma unroll unroll-hint-value
2065 /// #pragma unroll '(' unroll-hint-value ')'
2066 /// #pragma nounroll
2067 ///
2068 /// unroll-hint-value:
2069 /// constant-expression
2070 ///
2071 /// Loop unrolling hints can be specified with '#pragma unroll' or
2072 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2073 /// contained in parentheses. With no argument the directive instructs llvm to
2074 /// try to unroll the loop completely. A positive integer argument can be
2075 /// specified to indicate the number of times the loop should be unrolled. To
2076 /// maximize compatibility with other compilers the unroll count argument can be
2077 /// specified with or without parentheses. Specifying, '#pragma nounroll'
2078 /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducerKind Introducer,Token & Tok)2079 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2080 PragmaIntroducerKind Introducer,
2081 Token &Tok) {
2082 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2083 // "#pragma nounroll".
2084 Token PragmaName = Tok;
2085 PP.Lex(Tok);
2086 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2087 if (Tok.is(tok::eod)) {
2088 // nounroll or unroll pragma without an argument.
2089 Info->PragmaName = PragmaName;
2090 Info->Option.startToken();
2091 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2092 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2093 << "nounroll";
2094 return;
2095 } else {
2096 // Unroll pragma with an argument: "#pragma unroll N" or
2097 // "#pragma unroll(N)".
2098 // Read '(' if it exists.
2099 bool ValueInParens = Tok.is(tok::l_paren);
2100 if (ValueInParens)
2101 PP.Lex(Tok);
2102
2103 Token Option;
2104 Option.startToken();
2105 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
2106 return;
2107
2108 // In CUDA, the argument to '#pragma unroll' should not be contained in
2109 // parentheses.
2110 if (PP.getLangOpts().CUDA && ValueInParens)
2111 PP.Diag(Info->Toks[0].getLocation(),
2112 diag::warn_pragma_unroll_cuda_value_in_parens);
2113
2114 if (Tok.isNot(tok::eod)) {
2115 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2116 << "unroll";
2117 return;
2118 }
2119 }
2120
2121 // Generate the hint token.
2122 Token *TokenArray = new Token[1];
2123 TokenArray[0].startToken();
2124 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2125 TokenArray[0].setLocation(PragmaName.getLocation());
2126 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
2127 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2128 PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
2129 /*OwnsTokens=*/true);
2130 }
2131