1 //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the language specific #pragma handlers.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "clang/AST/ASTContext.h"
14 #include "clang/Basic/PragmaKinds.h"
15 #include "clang/Basic/TargetInfo.h"
16 #include "clang/Lex/Preprocessor.h"
17 #include "clang/Lex/Token.h"
18 #include "clang/Parse/LoopHint.h"
19 #include "clang/Parse/ParseDiagnostic.h"
20 #include "clang/Parse/Parser.h"
21 #include "clang/Parse/RAIIObjectsForParser.h"
22 #include "clang/Sema/Scope.h"
23 #include "llvm/ADT/ArrayRef.h"
24 #include "llvm/ADT/StringSwitch.h"
25 using namespace clang;
26
27 namespace {
28
29 struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon2f4395070111::PragmaAlignHandler30 explicit PragmaAlignHandler() : PragmaHandler("align") {}
31 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
32 Token &FirstToken) override;
33 };
34
35 struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon2f4395070111::PragmaGCCVisibilityHandler36 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
37 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
38 Token &FirstToken) override;
39 };
40
41 struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon2f4395070111::PragmaOptionsHandler42 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
43 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
44 Token &FirstToken) override;
45 };
46
47 struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon2f4395070111::PragmaPackHandler48 explicit PragmaPackHandler() : PragmaHandler("pack") {}
49 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
50 Token &FirstToken) override;
51 };
52
53 struct PragmaClangSectionHandler : public PragmaHandler {
PragmaClangSectionHandler__anon2f4395070111::PragmaClangSectionHandler54 explicit PragmaClangSectionHandler(Sema &S)
55 : PragmaHandler("section"), Actions(S) {}
56 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
57 Token &FirstToken) override;
58
59 private:
60 Sema &Actions;
61 };
62
63 struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon2f4395070111::PragmaMSStructHandler64 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
65 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
66 Token &FirstToken) override;
67 };
68
69 struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon2f4395070111::PragmaUnusedHandler70 PragmaUnusedHandler() : PragmaHandler("unused") {}
71 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
72 Token &FirstToken) override;
73 };
74
75 struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon2f4395070111::PragmaWeakHandler76 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
77 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
78 Token &FirstToken) override;
79 };
80
81 struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon2f4395070111::PragmaRedefineExtnameHandler82 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
83 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
84 Token &FirstToken) override;
85 };
86
87 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon2f4395070111::PragmaOpenCLExtensionHandler88 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
89 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
90 Token &FirstToken) override;
91 };
92
93
94 struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon2f4395070111::PragmaFPContractHandler95 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
96 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
97 Token &FirstToken) override;
98 };
99
100 // Pragma STDC implementations.
101
102 /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
103 struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
PragmaSTDC_FENV_ACCESSHandler__anon2f4395070111::PragmaSTDC_FENV_ACCESSHandler104 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
105
HandlePragma__anon2f4395070111::PragmaSTDC_FENV_ACCESSHandler106 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
107 Token &Tok) override {
108 Token PragmaName = Tok;
109 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
110 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
111 << PragmaName.getIdentifierInfo()->getName();
112 return;
113 }
114 tok::OnOffSwitch OOS;
115 if (PP.LexOnOffSwitch(OOS))
116 return;
117
118 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
119 1);
120 Toks[0].startToken();
121 Toks[0].setKind(tok::annot_pragma_fenv_access);
122 Toks[0].setLocation(Tok.getLocation());
123 Toks[0].setAnnotationEndLoc(Tok.getLocation());
124 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
125 static_cast<uintptr_t>(OOS)));
126 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
127 /*IsReinject=*/false);
128 }
129 };
130
131 /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
132 struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
PragmaSTDC_CX_LIMITED_RANGEHandler__anon2f4395070111::PragmaSTDC_CX_LIMITED_RANGEHandler133 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
134
HandlePragma__anon2f4395070111::PragmaSTDC_CX_LIMITED_RANGEHandler135 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
136 Token &Tok) override {
137 tok::OnOffSwitch OOS;
138 PP.LexOnOffSwitch(OOS);
139 }
140 };
141
142 /// Handler for "\#pragma STDC FENV_ROUND ...".
143 struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
PragmaSTDC_FENV_ROUNDHandler__anon2f4395070111::PragmaSTDC_FENV_ROUNDHandler144 PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
145
146 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
147 Token &Tok) override;
148 };
149
150 /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
151 struct PragmaSTDC_UnknownHandler : public PragmaHandler {
152 PragmaSTDC_UnknownHandler() = default;
153
HandlePragma__anon2f4395070111::PragmaSTDC_UnknownHandler154 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
155 Token &UnknownTok) override {
156 // C99 6.10.6p2, unknown forms are not allowed.
157 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
158 }
159 };
160
161 struct PragmaFPHandler : public PragmaHandler {
PragmaFPHandler__anon2f4395070111::PragmaFPHandler162 PragmaFPHandler() : PragmaHandler("fp") {}
163 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
164 Token &FirstToken) override;
165 };
166
167 struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon2f4395070111::PragmaNoOpenMPHandler168 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
169 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
170 Token &FirstToken) override;
171 };
172
173 struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon2f4395070111::PragmaOpenMPHandler174 PragmaOpenMPHandler() : PragmaHandler("omp") { }
175 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
176 Token &FirstToken) override;
177 };
178
179 /// PragmaCommentHandler - "\#pragma comment ...".
180 struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon2f4395070111::PragmaCommentHandler181 PragmaCommentHandler(Sema &Actions)
182 : PragmaHandler("comment"), Actions(Actions) {}
183 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
184 Token &FirstToken) override;
185
186 private:
187 Sema &Actions;
188 };
189
190 struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon2f4395070111::PragmaDetectMismatchHandler191 PragmaDetectMismatchHandler(Sema &Actions)
192 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
193 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
194 Token &FirstToken) override;
195
196 private:
197 Sema &Actions;
198 };
199
200 struct PragmaFloatControlHandler : public PragmaHandler {
PragmaFloatControlHandler__anon2f4395070111::PragmaFloatControlHandler201 PragmaFloatControlHandler(Sema &Actions)
202 : PragmaHandler("float_control") {}
203 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
204 Token &FirstToken) override;
205 };
206
207 struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon2f4395070111::PragmaMSPointersToMembers208 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
209 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
210 Token &FirstToken) override;
211 };
212
213 struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon2f4395070111::PragmaMSVtorDisp214 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
215 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
216 Token &FirstToken) override;
217 };
218
219 struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon2f4395070111::PragmaMSPragma220 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
221 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
222 Token &FirstToken) override;
223 };
224
225 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
226 struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon2f4395070111::PragmaOptimizeHandler227 PragmaOptimizeHandler(Sema &S)
228 : PragmaHandler("optimize"), Actions(S) {}
229 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
230 Token &FirstToken) override;
231
232 private:
233 Sema &Actions;
234 };
235
236 struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon2f4395070111::PragmaLoopHintHandler237 PragmaLoopHintHandler() : PragmaHandler("loop") {}
238 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
239 Token &FirstToken) override;
240 };
241
242 struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon2f4395070111::PragmaUnrollHintHandler243 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
244 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
245 Token &FirstToken) override;
246 };
247
248 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler__anon2f4395070111::PragmaMSRuntimeChecksHandler249 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
250 };
251
252 struct PragmaMSIntrinsicHandler : public PragmaHandler {
PragmaMSIntrinsicHandler__anon2f4395070111::PragmaMSIntrinsicHandler253 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
254 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
255 Token &FirstToken) override;
256 };
257
258 // "\#pragma fenv_access (on)".
259 struct PragmaMSFenvAccessHandler : public PragmaHandler {
PragmaMSFenvAccessHandler__anon2f4395070111::PragmaMSFenvAccessHandler260 PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
HandlePragma__anon2f4395070111::PragmaMSFenvAccessHandler261 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
262 Token &FirstToken) override {
263 StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
264 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
265 PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
266 << PragmaName;
267 return;
268 }
269
270 Token Tok;
271 PP.Lex(Tok);
272 if (Tok.isNot(tok::l_paren)) {
273 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
274 << PragmaName;
275 return;
276 }
277 PP.Lex(Tok); // Consume the l_paren.
278 if (Tok.isNot(tok::identifier)) {
279 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
280 return;
281 }
282 const IdentifierInfo *II = Tok.getIdentifierInfo();
283 tok::OnOffSwitch OOS;
284 if (II->isStr("on")) {
285 OOS = tok::OOS_ON;
286 PP.Lex(Tok);
287 } else if (II->isStr("off")) {
288 OOS = tok::OOS_OFF;
289 PP.Lex(Tok);
290 } else {
291 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
292 return;
293 }
294 if (Tok.isNot(tok::r_paren)) {
295 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
296 << PragmaName;
297 return;
298 }
299 PP.Lex(Tok); // Consume the r_paren.
300
301 if (Tok.isNot(tok::eod)) {
302 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
303 << PragmaName;
304 return;
305 }
306
307 MutableArrayRef<Token> Toks(
308 PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
309 Toks[0].startToken();
310 Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
311 Toks[0].setLocation(FirstToken.getLocation());
312 Toks[0].setAnnotationEndLoc(Tok.getLocation());
313 Toks[0].setAnnotationValue(
314 reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
315 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
316 /*IsReinject=*/false);
317 }
318 };
319
320 struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler__anon2f4395070111::PragmaForceCUDAHostDeviceHandler321 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
322 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
323 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
324 Token &FirstToken) override;
325
326 private:
327 Sema &Actions;
328 };
329
330 /// PragmaAttributeHandler - "\#pragma clang attribute ...".
331 struct PragmaAttributeHandler : public PragmaHandler {
PragmaAttributeHandler__anon2f4395070111::PragmaAttributeHandler332 PragmaAttributeHandler(AttributeFactory &AttrFactory)
333 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
334 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
335 Token &FirstToken) override;
336
337 /// A pool of attributes that were parsed in \#pragma clang attribute.
338 ParsedAttributes AttributesForPragmaAttribute;
339 };
340
341 struct PragmaMaxTokensHereHandler : public PragmaHandler {
PragmaMaxTokensHereHandler__anon2f4395070111::PragmaMaxTokensHereHandler342 PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
343 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
344 Token &FirstToken) override;
345 };
346
347 struct PragmaMaxTokensTotalHandler : public PragmaHandler {
PragmaMaxTokensTotalHandler__anon2f4395070111::PragmaMaxTokensTotalHandler348 PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
349 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
350 Token &FirstToken) override;
351 };
352
353 struct PragmaRISCVHandler : public PragmaHandler {
PragmaRISCVHandler__anon2f4395070111::PragmaRISCVHandler354 PragmaRISCVHandler(Sema &Actions)
355 : PragmaHandler("riscv"), Actions(Actions) {}
356 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
357 Token &FirstToken) override;
358
359 private:
360 Sema &Actions;
361 };
362
markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks)363 void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
364 for (auto &T : Toks)
365 T.setFlag(clang::Token::IsReinjected);
366 }
367 } // end namespace
368
initializePragmaHandlers()369 void Parser::initializePragmaHandlers() {
370 AlignHandler = std::make_unique<PragmaAlignHandler>();
371 PP.AddPragmaHandler(AlignHandler.get());
372
373 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
374 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
375
376 OptionsHandler = std::make_unique<PragmaOptionsHandler>();
377 PP.AddPragmaHandler(OptionsHandler.get());
378
379 PackHandler = std::make_unique<PragmaPackHandler>();
380 PP.AddPragmaHandler(PackHandler.get());
381
382 MSStructHandler = std::make_unique<PragmaMSStructHandler>();
383 PP.AddPragmaHandler(MSStructHandler.get());
384
385 UnusedHandler = std::make_unique<PragmaUnusedHandler>();
386 PP.AddPragmaHandler(UnusedHandler.get());
387
388 WeakHandler = std::make_unique<PragmaWeakHandler>();
389 PP.AddPragmaHandler(WeakHandler.get());
390
391 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
392 PP.AddPragmaHandler(RedefineExtnameHandler.get());
393
394 FPContractHandler = std::make_unique<PragmaFPContractHandler>();
395 PP.AddPragmaHandler("STDC", FPContractHandler.get());
396
397 STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
398 PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
399
400 STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
401 PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
402
403 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
404 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
405
406 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
407 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
408
409 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
410 PP.AddPragmaHandler("clang", PCSectionHandler.get());
411
412 if (getLangOpts().OpenCL) {
413 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
414 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
415
416 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
417 }
418 if (getLangOpts().OpenMP)
419 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
420 else
421 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
422 PP.AddPragmaHandler(OpenMPHandler.get());
423
424 if (getLangOpts().MicrosoftExt ||
425 getTargetInfo().getTriple().isOSBinFormatELF()) {
426 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
427 PP.AddPragmaHandler(MSCommentHandler.get());
428 }
429
430 FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
431 PP.AddPragmaHandler(FloatControlHandler.get());
432 if (getLangOpts().MicrosoftExt) {
433 MSDetectMismatchHandler =
434 std::make_unique<PragmaDetectMismatchHandler>(Actions);
435 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
436 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
437 PP.AddPragmaHandler(MSPointersToMembers.get());
438 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
439 PP.AddPragmaHandler(MSVtorDisp.get());
440 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
441 PP.AddPragmaHandler(MSInitSeg.get());
442 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
443 PP.AddPragmaHandler(MSDataSeg.get());
444 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
445 PP.AddPragmaHandler(MSBSSSeg.get());
446 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
447 PP.AddPragmaHandler(MSConstSeg.get());
448 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
449 PP.AddPragmaHandler(MSCodeSeg.get());
450 MSSection = std::make_unique<PragmaMSPragma>("section");
451 PP.AddPragmaHandler(MSSection.get());
452 MSFunction = std::make_unique<PragmaMSPragma>("function");
453 PP.AddPragmaHandler(MSFunction.get());
454 MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
455 PP.AddPragmaHandler(MSAllocText.get());
456 MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
457 PP.AddPragmaHandler(MSOptimize.get());
458 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
459 PP.AddPragmaHandler(MSRuntimeChecks.get());
460 MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
461 PP.AddPragmaHandler(MSIntrinsic.get());
462 MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
463 PP.AddPragmaHandler(MSFenvAccess.get());
464 }
465
466 if (getLangOpts().CUDA) {
467 CUDAForceHostDeviceHandler =
468 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
469 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
470 }
471
472 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
473 PP.AddPragmaHandler("clang", OptimizeHandler.get());
474
475 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
476 PP.AddPragmaHandler("clang", LoopHintHandler.get());
477
478 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
479 PP.AddPragmaHandler(UnrollHintHandler.get());
480 PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
481
482 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
483 PP.AddPragmaHandler(NoUnrollHintHandler.get());
484 PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
485
486 UnrollAndJamHintHandler =
487 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
488 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
489
490 NoUnrollAndJamHintHandler =
491 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
492 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
493
494 FPHandler = std::make_unique<PragmaFPHandler>();
495 PP.AddPragmaHandler("clang", FPHandler.get());
496
497 AttributePragmaHandler =
498 std::make_unique<PragmaAttributeHandler>(AttrFactory);
499 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
500
501 MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
502 PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
503
504 MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
505 PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
506
507 if (getTargetInfo().getTriple().isRISCV()) {
508 RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
509 PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
510 }
511 }
512
resetPragmaHandlers()513 void Parser::resetPragmaHandlers() {
514 // Remove the pragma handlers we installed.
515 PP.RemovePragmaHandler(AlignHandler.get());
516 AlignHandler.reset();
517 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
518 GCCVisibilityHandler.reset();
519 PP.RemovePragmaHandler(OptionsHandler.get());
520 OptionsHandler.reset();
521 PP.RemovePragmaHandler(PackHandler.get());
522 PackHandler.reset();
523 PP.RemovePragmaHandler(MSStructHandler.get());
524 MSStructHandler.reset();
525 PP.RemovePragmaHandler(UnusedHandler.get());
526 UnusedHandler.reset();
527 PP.RemovePragmaHandler(WeakHandler.get());
528 WeakHandler.reset();
529 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
530 RedefineExtnameHandler.reset();
531
532 if (getLangOpts().OpenCL) {
533 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
534 OpenCLExtensionHandler.reset();
535 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
536 }
537 PP.RemovePragmaHandler(OpenMPHandler.get());
538 OpenMPHandler.reset();
539
540 if (getLangOpts().MicrosoftExt ||
541 getTargetInfo().getTriple().isOSBinFormatELF()) {
542 PP.RemovePragmaHandler(MSCommentHandler.get());
543 MSCommentHandler.reset();
544 }
545
546 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
547 PCSectionHandler.reset();
548
549 PP.RemovePragmaHandler(FloatControlHandler.get());
550 FloatControlHandler.reset();
551 if (getLangOpts().MicrosoftExt) {
552 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
553 MSDetectMismatchHandler.reset();
554 PP.RemovePragmaHandler(MSPointersToMembers.get());
555 MSPointersToMembers.reset();
556 PP.RemovePragmaHandler(MSVtorDisp.get());
557 MSVtorDisp.reset();
558 PP.RemovePragmaHandler(MSInitSeg.get());
559 MSInitSeg.reset();
560 PP.RemovePragmaHandler(MSDataSeg.get());
561 MSDataSeg.reset();
562 PP.RemovePragmaHandler(MSBSSSeg.get());
563 MSBSSSeg.reset();
564 PP.RemovePragmaHandler(MSConstSeg.get());
565 MSConstSeg.reset();
566 PP.RemovePragmaHandler(MSCodeSeg.get());
567 MSCodeSeg.reset();
568 PP.RemovePragmaHandler(MSSection.get());
569 MSSection.reset();
570 PP.RemovePragmaHandler(MSFunction.get());
571 MSFunction.reset();
572 PP.RemovePragmaHandler(MSAllocText.get());
573 MSAllocText.reset();
574 PP.RemovePragmaHandler(MSRuntimeChecks.get());
575 MSRuntimeChecks.reset();
576 PP.RemovePragmaHandler(MSIntrinsic.get());
577 MSIntrinsic.reset();
578 PP.RemovePragmaHandler(MSOptimize.get());
579 MSOptimize.reset();
580 PP.RemovePragmaHandler(MSFenvAccess.get());
581 MSFenvAccess.reset();
582 }
583
584 if (getLangOpts().CUDA) {
585 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
586 CUDAForceHostDeviceHandler.reset();
587 }
588
589 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
590 FPContractHandler.reset();
591
592 PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
593 STDCFenvAccessHandler.reset();
594
595 PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
596 STDCFenvRoundHandler.reset();
597
598 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
599 STDCCXLIMITHandler.reset();
600
601 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
602 STDCUnknownHandler.reset();
603
604 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
605 OptimizeHandler.reset();
606
607 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
608 LoopHintHandler.reset();
609
610 PP.RemovePragmaHandler(UnrollHintHandler.get());
611 PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
612 UnrollHintHandler.reset();
613
614 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
615 PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
616 NoUnrollHintHandler.reset();
617
618 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
619 UnrollAndJamHintHandler.reset();
620
621 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
622 NoUnrollAndJamHintHandler.reset();
623
624 PP.RemovePragmaHandler("clang", FPHandler.get());
625 FPHandler.reset();
626
627 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
628 AttributePragmaHandler.reset();
629
630 PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
631 MaxTokensHerePragmaHandler.reset();
632
633 PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
634 MaxTokensTotalPragmaHandler.reset();
635
636 if (getTargetInfo().getTriple().isRISCV()) {
637 PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
638 RISCVPragmaHandler.reset();
639 }
640 }
641
642 /// Handle the annotation token produced for #pragma unused(...)
643 ///
644 /// Each annot_pragma_unused is followed by the argument token so e.g.
645 /// "#pragma unused(x,y)" becomes:
646 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()647 void Parser::HandlePragmaUnused() {
648 assert(Tok.is(tok::annot_pragma_unused));
649 SourceLocation UnusedLoc = ConsumeAnnotationToken();
650 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
651 ConsumeToken(); // The argument token.
652 }
653
HandlePragmaVisibility()654 void Parser::HandlePragmaVisibility() {
655 assert(Tok.is(tok::annot_pragma_vis));
656 const IdentifierInfo *VisType =
657 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
658 SourceLocation VisLoc = ConsumeAnnotationToken();
659 Actions.ActOnPragmaVisibility(VisType, VisLoc);
660 }
661
662 namespace {
663 struct PragmaPackInfo {
664 Sema::PragmaMsStackAction Action;
665 StringRef SlotLabel;
666 Token Alignment;
667 };
668 } // end anonymous namespace
669
HandlePragmaPack()670 void Parser::HandlePragmaPack() {
671 assert(Tok.is(tok::annot_pragma_pack));
672 PragmaPackInfo *Info =
673 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
674 SourceLocation PragmaLoc = Tok.getLocation();
675 ExprResult Alignment;
676 if (Info->Alignment.is(tok::numeric_constant)) {
677 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
678 if (Alignment.isInvalid()) {
679 ConsumeAnnotationToken();
680 return;
681 }
682 }
683 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
684 Alignment.get());
685 // Consume the token after processing the pragma to enable pragma-specific
686 // #include warnings.
687 ConsumeAnnotationToken();
688 }
689
HandlePragmaMSStruct()690 void Parser::HandlePragmaMSStruct() {
691 assert(Tok.is(tok::annot_pragma_msstruct));
692 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
693 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
694 Actions.ActOnPragmaMSStruct(Kind);
695 ConsumeAnnotationToken();
696 }
697
HandlePragmaAlign()698 void Parser::HandlePragmaAlign() {
699 assert(Tok.is(tok::annot_pragma_align));
700 Sema::PragmaOptionsAlignKind Kind =
701 static_cast<Sema::PragmaOptionsAlignKind>(
702 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
703 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
704 // Consume the token after processing the pragma to enable pragma-specific
705 // #include warnings.
706 ConsumeAnnotationToken();
707 }
708
HandlePragmaDump()709 void Parser::HandlePragmaDump() {
710 assert(Tok.is(tok::annot_pragma_dump));
711 IdentifierInfo *II =
712 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
713 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
714 ConsumeAnnotationToken();
715 }
716
HandlePragmaWeak()717 void Parser::HandlePragmaWeak() {
718 assert(Tok.is(tok::annot_pragma_weak));
719 SourceLocation PragmaLoc = ConsumeAnnotationToken();
720 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
721 Tok.getLocation());
722 ConsumeToken(); // The weak name.
723 }
724
HandlePragmaWeakAlias()725 void Parser::HandlePragmaWeakAlias() {
726 assert(Tok.is(tok::annot_pragma_weakalias));
727 SourceLocation PragmaLoc = ConsumeAnnotationToken();
728 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
729 SourceLocation WeakNameLoc = Tok.getLocation();
730 ConsumeToken();
731 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
732 SourceLocation AliasNameLoc = Tok.getLocation();
733 ConsumeToken();
734 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
735 WeakNameLoc, AliasNameLoc);
736
737 }
738
HandlePragmaRedefineExtname()739 void Parser::HandlePragmaRedefineExtname() {
740 assert(Tok.is(tok::annot_pragma_redefine_extname));
741 SourceLocation RedefLoc = ConsumeAnnotationToken();
742 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
743 SourceLocation RedefNameLoc = Tok.getLocation();
744 ConsumeToken();
745 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
746 SourceLocation AliasNameLoc = Tok.getLocation();
747 ConsumeToken();
748 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
749 RedefNameLoc, AliasNameLoc);
750 }
751
HandlePragmaFPContract()752 void Parser::HandlePragmaFPContract() {
753 assert(Tok.is(tok::annot_pragma_fp_contract));
754 tok::OnOffSwitch OOS =
755 static_cast<tok::OnOffSwitch>(
756 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
757
758 LangOptions::FPModeKind FPC;
759 switch (OOS) {
760 case tok::OOS_ON:
761 FPC = LangOptions::FPM_On;
762 break;
763 case tok::OOS_OFF:
764 FPC = LangOptions::FPM_Off;
765 break;
766 case tok::OOS_DEFAULT:
767 FPC = getLangOpts().getDefaultFPContractMode();
768 break;
769 }
770
771 SourceLocation PragmaLoc = ConsumeAnnotationToken();
772 Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
773 }
774
HandlePragmaFloatControl()775 void Parser::HandlePragmaFloatControl() {
776 assert(Tok.is(tok::annot_pragma_float_control));
777
778 // The value that is held on the PragmaFloatControlStack encodes
779 // the PragmaFloatControl kind and the MSStackAction kind
780 // into a single 32-bit word. The MsStackAction is the high 16 bits
781 // and the FloatControl is the lower 16 bits. Use shift and bit-and
782 // to decode the parts.
783 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
784 Sema::PragmaMsStackAction Action =
785 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
786 PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
787 SourceLocation PragmaLoc = ConsumeAnnotationToken();
788 Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
789 }
790
HandlePragmaFEnvAccess()791 void Parser::HandlePragmaFEnvAccess() {
792 assert(Tok.is(tok::annot_pragma_fenv_access) ||
793 Tok.is(tok::annot_pragma_fenv_access_ms));
794 tok::OnOffSwitch OOS =
795 static_cast<tok::OnOffSwitch>(
796 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
797
798 bool IsEnabled;
799 switch (OOS) {
800 case tok::OOS_ON:
801 IsEnabled = true;
802 break;
803 case tok::OOS_OFF:
804 IsEnabled = false;
805 break;
806 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
807 IsEnabled = false;
808 break;
809 }
810
811 SourceLocation PragmaLoc = ConsumeAnnotationToken();
812 Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
813 }
814
HandlePragmaFEnvRound()815 void Parser::HandlePragmaFEnvRound() {
816 assert(Tok.is(tok::annot_pragma_fenv_round));
817 auto RM = static_cast<llvm::RoundingMode>(
818 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
819
820 SourceLocation PragmaLoc = ConsumeAnnotationToken();
821 Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
822 }
823
HandlePragmaCaptured()824 StmtResult Parser::HandlePragmaCaptured()
825 {
826 assert(Tok.is(tok::annot_pragma_captured));
827 ConsumeAnnotationToken();
828
829 if (Tok.isNot(tok::l_brace)) {
830 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
831 return StmtError();
832 }
833
834 SourceLocation Loc = Tok.getLocation();
835
836 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
837 Scope::CompoundStmtScope);
838 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
839 /*NumParams=*/1);
840
841 StmtResult R = ParseCompoundStatement();
842 CapturedRegionScope.Exit();
843
844 if (R.isInvalid()) {
845 Actions.ActOnCapturedRegionError();
846 return StmtError();
847 }
848
849 return Actions.ActOnCapturedRegionEnd(R.get());
850 }
851
852 namespace {
853 enum OpenCLExtState : char {
854 Disable, Enable, Begin, End
855 };
856 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
857 }
858
HandlePragmaOpenCLExtension()859 void Parser::HandlePragmaOpenCLExtension() {
860 assert(Tok.is(tok::annot_pragma_opencl_extension));
861 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
862 auto State = Data->second;
863 auto Ident = Data->first;
864 SourceLocation NameLoc = Tok.getLocation();
865 ConsumeAnnotationToken();
866
867 auto &Opt = Actions.getOpenCLOptions();
868 auto Name = Ident->getName();
869 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
870 // overriding all previously issued extension directives, but only if the
871 // behavior is set to disable."
872 if (Name == "all") {
873 if (State == Disable)
874 Opt.disableAll();
875 else
876 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
877 } else if (State == Begin) {
878 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
879 Opt.support(Name);
880 // FIXME: Default behavior of the extension pragma is not defined.
881 // Therefore, it should never be added by default.
882 Opt.acceptsPragma(Name);
883 }
884 } else if (State == End) {
885 // There is no behavior for this directive. We only accept this for
886 // backward compatibility.
887 } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
888 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
889 else if (Opt.isSupportedExtension(Name, getLangOpts()))
890 Opt.enable(Name, State == Enable);
891 else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
892 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
893 else
894 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
895 }
896
HandlePragmaMSPointersToMembers()897 void Parser::HandlePragmaMSPointersToMembers() {
898 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
899 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
900 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
901 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
902 SourceLocation PragmaLoc = ConsumeAnnotationToken();
903 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
904 }
905
HandlePragmaMSVtorDisp()906 void Parser::HandlePragmaMSVtorDisp() {
907 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
908 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
909 Sema::PragmaMsStackAction Action =
910 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
911 MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
912 SourceLocation PragmaLoc = ConsumeAnnotationToken();
913 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
914 }
915
HandlePragmaMSPragma()916 void Parser::HandlePragmaMSPragma() {
917 assert(Tok.is(tok::annot_pragma_ms_pragma));
918 // Grab the tokens out of the annotation and enter them into the stream.
919 auto TheTokens =
920 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
921 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
922 /*IsReinject=*/true);
923 SourceLocation PragmaLocation = ConsumeAnnotationToken();
924 assert(Tok.isAnyIdentifier());
925 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
926 PP.Lex(Tok); // pragma kind
927
928 // Figure out which #pragma we're dealing with. The switch has no default
929 // because lex shouldn't emit the annotation token for unrecognized pragmas.
930 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
931 PragmaHandler Handler =
932 llvm::StringSwitch<PragmaHandler>(PragmaName)
933 .Case("data_seg", &Parser::HandlePragmaMSSegment)
934 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
935 .Case("const_seg", &Parser::HandlePragmaMSSegment)
936 .Case("code_seg", &Parser::HandlePragmaMSSegment)
937 .Case("section", &Parser::HandlePragmaMSSection)
938 .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
939 .Case("function", &Parser::HandlePragmaMSFunction)
940 .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
941 .Case("optimize", &Parser::HandlePragmaMSOptimize);
942
943 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
944 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
945 // until eof (really end of line) to prevent follow-on errors.
946 while (Tok.isNot(tok::eof))
947 PP.Lex(Tok);
948 PP.Lex(Tok);
949 }
950 }
951
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)952 bool Parser::HandlePragmaMSSection(StringRef PragmaName,
953 SourceLocation PragmaLocation) {
954 if (Tok.isNot(tok::l_paren)) {
955 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
956 return false;
957 }
958 PP.Lex(Tok); // (
959 // Parsing code for pragma section
960 if (Tok.isNot(tok::string_literal)) {
961 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
962 << PragmaName;
963 return false;
964 }
965 ExprResult StringResult = ParseStringLiteralExpression();
966 if (StringResult.isInvalid())
967 return false; // Already diagnosed.
968 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
969 if (SegmentName->getCharByteWidth() != 1) {
970 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
971 << PragmaName;
972 return false;
973 }
974 int SectionFlags = ASTContext::PSF_Read;
975 bool SectionFlagsAreDefault = true;
976 while (Tok.is(tok::comma)) {
977 PP.Lex(Tok); // ,
978 // Ignore "long" and "short".
979 // They are undocumented, but widely used, section attributes which appear
980 // to do nothing.
981 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
982 PP.Lex(Tok); // long/short
983 continue;
984 }
985
986 if (!Tok.isAnyIdentifier()) {
987 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
988 << PragmaName;
989 return false;
990 }
991 ASTContext::PragmaSectionFlag Flag =
992 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
993 Tok.getIdentifierInfo()->getName())
994 .Case("read", ASTContext::PSF_Read)
995 .Case("write", ASTContext::PSF_Write)
996 .Case("execute", ASTContext::PSF_Execute)
997 .Case("shared", ASTContext::PSF_Invalid)
998 .Case("nopage", ASTContext::PSF_Invalid)
999 .Case("nocache", ASTContext::PSF_Invalid)
1000 .Case("discard", ASTContext::PSF_Invalid)
1001 .Case("remove", ASTContext::PSF_Invalid)
1002 .Default(ASTContext::PSF_None);
1003 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
1004 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
1005 ? diag::warn_pragma_invalid_specific_action
1006 : diag::warn_pragma_unsupported_action)
1007 << PragmaName << Tok.getIdentifierInfo()->getName();
1008 return false;
1009 }
1010 SectionFlags |= Flag;
1011 SectionFlagsAreDefault = false;
1012 PP.Lex(Tok); // Identifier
1013 }
1014 // If no section attributes are specified, the section will be marked as
1015 // read/write.
1016 if (SectionFlagsAreDefault)
1017 SectionFlags |= ASTContext::PSF_Write;
1018 if (Tok.isNot(tok::r_paren)) {
1019 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1020 return false;
1021 }
1022 PP.Lex(Tok); // )
1023 if (Tok.isNot(tok::eof)) {
1024 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1025 << PragmaName;
1026 return false;
1027 }
1028 PP.Lex(Tok); // eof
1029 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
1030 return true;
1031 }
1032
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)1033 bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
1034 SourceLocation PragmaLocation) {
1035 if (Tok.isNot(tok::l_paren)) {
1036 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1037 return false;
1038 }
1039 PP.Lex(Tok); // (
1040 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1041 StringRef SlotLabel;
1042 if (Tok.isAnyIdentifier()) {
1043 StringRef PushPop = Tok.getIdentifierInfo()->getName();
1044 if (PushPop == "push")
1045 Action = Sema::PSK_Push;
1046 else if (PushPop == "pop")
1047 Action = Sema::PSK_Pop;
1048 else {
1049 PP.Diag(PragmaLocation,
1050 diag::warn_pragma_expected_section_push_pop_or_name)
1051 << PragmaName;
1052 return false;
1053 }
1054 if (Action != Sema::PSK_Reset) {
1055 PP.Lex(Tok); // push | pop
1056 if (Tok.is(tok::comma)) {
1057 PP.Lex(Tok); // ,
1058 // If we've got a comma, we either need a label or a string.
1059 if (Tok.isAnyIdentifier()) {
1060 SlotLabel = Tok.getIdentifierInfo()->getName();
1061 PP.Lex(Tok); // identifier
1062 if (Tok.is(tok::comma))
1063 PP.Lex(Tok);
1064 else if (Tok.isNot(tok::r_paren)) {
1065 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
1066 << PragmaName;
1067 return false;
1068 }
1069 }
1070 } else if (Tok.isNot(tok::r_paren)) {
1071 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
1072 return false;
1073 }
1074 }
1075 }
1076 // Grab the string literal for our section name.
1077 StringLiteral *SegmentName = nullptr;
1078 if (Tok.isNot(tok::r_paren)) {
1079 if (Tok.isNot(tok::string_literal)) {
1080 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
1081 diag::warn_pragma_expected_section_name :
1082 diag::warn_pragma_expected_section_label_or_name :
1083 diag::warn_pragma_expected_section_push_pop_or_name;
1084 PP.Diag(PragmaLocation, DiagID) << PragmaName;
1085 return false;
1086 }
1087 ExprResult StringResult = ParseStringLiteralExpression();
1088 if (StringResult.isInvalid())
1089 return false; // Already diagnosed.
1090 SegmentName = cast<StringLiteral>(StringResult.get());
1091 if (SegmentName->getCharByteWidth() != 1) {
1092 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1093 << PragmaName;
1094 return false;
1095 }
1096 // Setting section "" has no effect
1097 if (SegmentName->getLength())
1098 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1099 }
1100 if (Tok.isNot(tok::r_paren)) {
1101 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1102 return false;
1103 }
1104 PP.Lex(Tok); // )
1105 if (Tok.isNot(tok::eof)) {
1106 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1107 << PragmaName;
1108 return false;
1109 }
1110 PP.Lex(Tok); // eof
1111 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
1112 SegmentName, PragmaName);
1113 return true;
1114 }
1115
1116 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)1117 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
1118 SourceLocation PragmaLocation) {
1119 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
1120 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
1121 return false;
1122 }
1123
1124 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1125 PragmaName))
1126 return false;
1127
1128 // Parse either the known section names or the string section name.
1129 StringLiteral *SegmentName = nullptr;
1130 if (Tok.isAnyIdentifier()) {
1131 auto *II = Tok.getIdentifierInfo();
1132 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1133 .Case("compiler", "\".CRT$XCC\"")
1134 .Case("lib", "\".CRT$XCL\"")
1135 .Case("user", "\".CRT$XCU\"")
1136 .Default("");
1137
1138 if (!Section.empty()) {
1139 // Pretend the user wrote the appropriate string literal here.
1140 Token Toks[1];
1141 Toks[0].startToken();
1142 Toks[0].setKind(tok::string_literal);
1143 Toks[0].setLocation(Tok.getLocation());
1144 Toks[0].setLiteralData(Section.data());
1145 Toks[0].setLength(Section.size());
1146 SegmentName =
1147 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1148 PP.Lex(Tok);
1149 }
1150 } else if (Tok.is(tok::string_literal)) {
1151 ExprResult StringResult = ParseStringLiteralExpression();
1152 if (StringResult.isInvalid())
1153 return false;
1154 SegmentName = cast<StringLiteral>(StringResult.get());
1155 if (SegmentName->getCharByteWidth() != 1) {
1156 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1157 << PragmaName;
1158 return false;
1159 }
1160 // FIXME: Add support for the '[, func-name]' part of the pragma.
1161 }
1162
1163 if (!SegmentName) {
1164 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1165 return false;
1166 }
1167
1168 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1169 PragmaName) ||
1170 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1171 PragmaName))
1172 return false;
1173
1174 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1175 return true;
1176 }
1177
HandlePragmaMSAllocText(StringRef PragmaName,SourceLocation PragmaLocation)1178 bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
1179 SourceLocation PragmaLocation) {
1180 Token FirstTok = Tok;
1181 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1182 PragmaName))
1183 return false;
1184
1185 StringRef Section;
1186 if (Tok.is(tok::string_literal)) {
1187 ExprResult StringResult = ParseStringLiteralExpression();
1188 if (StringResult.isInvalid())
1189 return false; // Already diagnosed.
1190 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1191 if (SegmentName->getCharByteWidth() != 1) {
1192 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1193 << PragmaName;
1194 return false;
1195 }
1196 Section = SegmentName->getString();
1197 } else if (Tok.is(tok::identifier)) {
1198 Section = Tok.getIdentifierInfo()->getName();
1199 PP.Lex(Tok);
1200 } else {
1201 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1202 << PragmaName;
1203 return false;
1204 }
1205
1206 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
1207 PragmaName))
1208 return false;
1209
1210 SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
1211 while (true) {
1212 if (Tok.isNot(tok::identifier)) {
1213 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1214 << PragmaName;
1215 return false;
1216 }
1217
1218 IdentifierInfo *II = Tok.getIdentifierInfo();
1219 Functions.emplace_back(II, Tok.getLocation());
1220
1221 PP.Lex(Tok);
1222 if (Tok.isNot(tok::comma))
1223 break;
1224 PP.Lex(Tok);
1225 }
1226
1227 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1228 PragmaName) ||
1229 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1230 PragmaName))
1231 return false;
1232
1233 Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
1234 return true;
1235 }
1236
1237 namespace {
1238 struct PragmaLoopHintInfo {
1239 Token PragmaName;
1240 Token Option;
1241 ArrayRef<Token> Toks;
1242 };
1243 } // end anonymous namespace
1244
PragmaLoopHintString(Token PragmaName,Token Option)1245 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1246 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1247 std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
1248 return std::string(llvm::StringSwitch<StringRef>(Str)
1249 .Case("loop", ClangLoopStr)
1250 .Case("unroll_and_jam", Str)
1251 .Case("unroll", Str)
1252 .Default(""));
1253 }
1254
HandlePragmaLoopHint(LoopHint & Hint)1255 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1256 assert(Tok.is(tok::annot_pragma_loop_hint));
1257 PragmaLoopHintInfo *Info =
1258 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1259
1260 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1261 Hint.PragmaNameLoc = IdentifierLoc::create(
1262 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
1263
1264 // It is possible that the loop hint has no option identifier, such as
1265 // #pragma unroll(4).
1266 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1267 ? Info->Option.getIdentifierInfo()
1268 : nullptr;
1269 Hint.OptionLoc = IdentifierLoc::create(
1270 Actions.Context, Info->Option.getLocation(), OptionInfo);
1271
1272 llvm::ArrayRef<Token> Toks = Info->Toks;
1273
1274 // Return a valid hint if pragma unroll or nounroll were specified
1275 // without an argument.
1276 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1277 .Cases("unroll", "nounroll", "unroll_and_jam",
1278 "nounroll_and_jam", true)
1279 .Default(false);
1280
1281 if (Toks.empty() && IsLoopHint) {
1282 ConsumeAnnotationToken();
1283 Hint.Range = Info->PragmaName.getLocation();
1284 return true;
1285 }
1286
1287 // The constant expression is always followed by an eof token, which increases
1288 // the TokSize by 1.
1289 assert(!Toks.empty() &&
1290 "PragmaLoopHintInfo::Toks must contain at least one token.");
1291
1292 // If no option is specified the argument is assumed to be a constant expr.
1293 bool OptionUnroll = false;
1294 bool OptionUnrollAndJam = false;
1295 bool OptionDistribute = false;
1296 bool OptionPipelineDisabled = false;
1297 bool StateOption = false;
1298 if (OptionInfo) { // Pragma Unroll does not specify an option.
1299 OptionUnroll = OptionInfo->isStr("unroll");
1300 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1301 OptionDistribute = OptionInfo->isStr("distribute");
1302 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1303 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1304 .Case("vectorize", true)
1305 .Case("interleave", true)
1306 .Case("vectorize_predicate", true)
1307 .Default(false) ||
1308 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1309 OptionPipelineDisabled;
1310 }
1311
1312 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1313 !OptionDistribute && !OptionPipelineDisabled;
1314 // Verify loop hint has an argument.
1315 if (Toks[0].is(tok::eof)) {
1316 ConsumeAnnotationToken();
1317 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1318 << /*StateArgument=*/StateOption
1319 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1320 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1321 return false;
1322 }
1323
1324 // Validate the argument.
1325 if (StateOption) {
1326 ConsumeAnnotationToken();
1327 SourceLocation StateLoc = Toks[0].getLocation();
1328 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1329
1330 bool Valid = StateInfo &&
1331 llvm::StringSwitch<bool>(StateInfo->getName())
1332 .Case("disable", true)
1333 .Case("enable", !OptionPipelineDisabled)
1334 .Case("full", OptionUnroll || OptionUnrollAndJam)
1335 .Case("assume_safety", AssumeSafetyArg)
1336 .Default(false);
1337 if (!Valid) {
1338 if (OptionPipelineDisabled) {
1339 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1340 } else {
1341 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1342 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1343 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1344 }
1345 return false;
1346 }
1347 if (Toks.size() > 2)
1348 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1349 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1350 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1351 } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
1352 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1353 /*IsReinject=*/false);
1354 ConsumeAnnotationToken();
1355
1356 SourceLocation StateLoc = Toks[0].getLocation();
1357 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1358 StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
1359
1360 // Look for vectorize_width(fixed|scalable)
1361 if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
1362 PP.Lex(Tok); // Identifier
1363
1364 if (Toks.size() > 2) {
1365 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1366 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1367 while (Tok.isNot(tok::eof))
1368 ConsumeAnyToken();
1369 }
1370
1371 Hint.StateLoc =
1372 IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1373
1374 ConsumeToken(); // Consume the constant expression eof terminator.
1375 } else {
1376 // Enter constant expression including eof terminator into token stream.
1377 ExprResult R = ParseConstantExpression();
1378
1379 if (R.isInvalid() && !Tok.is(tok::comma))
1380 Diag(Toks[0].getLocation(),
1381 diag::note_pragma_loop_invalid_vectorize_option);
1382
1383 bool Arg2Error = false;
1384 if (Tok.is(tok::comma)) {
1385 PP.Lex(Tok); // ,
1386
1387 StateInfo = Tok.getIdentifierInfo();
1388 IsScalableStr = StateInfo->getName();
1389
1390 if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
1391 Diag(Tok.getLocation(),
1392 diag::err_pragma_loop_invalid_vectorize_option);
1393 Arg2Error = true;
1394 } else
1395 Hint.StateLoc =
1396 IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1397
1398 PP.Lex(Tok); // Identifier
1399 }
1400
1401 // Tokens following an error in an ill-formed constant expression will
1402 // remain in the token stream and must be removed.
1403 if (Tok.isNot(tok::eof)) {
1404 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1405 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1406 while (Tok.isNot(tok::eof))
1407 ConsumeAnyToken();
1408 }
1409
1410 ConsumeToken(); // Consume the constant expression eof terminator.
1411
1412 if (Arg2Error || R.isInvalid() ||
1413 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1414 return false;
1415
1416 // Argument is a constant expression with an integer type.
1417 Hint.ValueExpr = R.get();
1418 }
1419 } else {
1420 // Enter constant expression including eof terminator into token stream.
1421 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1422 /*IsReinject=*/false);
1423 ConsumeAnnotationToken();
1424 ExprResult R = ParseConstantExpression();
1425
1426 // Tokens following an error in an ill-formed constant expression will
1427 // remain in the token stream and must be removed.
1428 if (Tok.isNot(tok::eof)) {
1429 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1430 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1431 while (Tok.isNot(tok::eof))
1432 ConsumeAnyToken();
1433 }
1434
1435 ConsumeToken(); // Consume the constant expression eof terminator.
1436
1437 if (R.isInvalid() ||
1438 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1439 return false;
1440
1441 // Argument is a constant expression with an integer type.
1442 Hint.ValueExpr = R.get();
1443 }
1444
1445 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1446 Info->Toks.back().getLocation());
1447 return true;
1448 }
1449
1450 namespace {
1451 struct PragmaAttributeInfo {
1452 enum ActionType { Push, Pop, Attribute };
1453 ParsedAttributes &Attributes;
1454 ActionType Action;
1455 const IdentifierInfo *Namespace = nullptr;
1456 ArrayRef<Token> Tokens;
1457
PragmaAttributeInfo__anon2f4395070511::PragmaAttributeInfo1458 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1459 };
1460
1461 #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1462
1463 } // end anonymous namespace
1464
getIdentifier(const Token & Tok)1465 static StringRef getIdentifier(const Token &Tok) {
1466 if (Tok.is(tok::identifier))
1467 return Tok.getIdentifierInfo()->getName();
1468 const char *S = tok::getKeywordSpelling(Tok.getKind());
1469 if (!S)
1470 return "";
1471 return S;
1472 }
1473
isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule)1474 static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1475 using namespace attr;
1476 switch (Rule) {
1477 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1478 case Value: \
1479 return IsAbstract;
1480 #include "clang/Basic/AttrSubMatchRulesList.inc"
1481 }
1482 llvm_unreachable("Invalid attribute subject match rule");
1483 return false;
1484 }
1485
diagnoseExpectedAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,SourceLocation SubRuleLoc)1486 static void diagnoseExpectedAttributeSubjectSubRule(
1487 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1488 SourceLocation SubRuleLoc) {
1489 auto Diagnostic =
1490 PRef.Diag(SubRuleLoc,
1491 diag::err_pragma_attribute_expected_subject_sub_identifier)
1492 << PrimaryRuleName;
1493 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1494 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1495 else
1496 Diagnostic << /*SubRulesSupported=*/0;
1497 }
1498
diagnoseUnknownAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,StringRef SubRuleName,SourceLocation SubRuleLoc)1499 static void diagnoseUnknownAttributeSubjectSubRule(
1500 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1501 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1502
1503 auto Diagnostic =
1504 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1505 << SubRuleName << PrimaryRuleName;
1506 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1507 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1508 else
1509 Diagnostic << /*SubRulesSupported=*/0;
1510 }
1511
ParsePragmaAttributeSubjectMatchRuleSet(attr::ParsedSubjectMatchRuleSet & SubjectMatchRules,SourceLocation & AnyLoc,SourceLocation & LastMatchRuleEndLoc)1512 bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1513 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1514 SourceLocation &LastMatchRuleEndLoc) {
1515 bool IsAny = false;
1516 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1517 if (getIdentifier(Tok) == "any") {
1518 AnyLoc = ConsumeToken();
1519 IsAny = true;
1520 if (AnyParens.expectAndConsume())
1521 return true;
1522 }
1523
1524 do {
1525 // Parse the subject matcher rule.
1526 StringRef Name = getIdentifier(Tok);
1527 if (Name.empty()) {
1528 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1529 return true;
1530 }
1531 std::pair<Optional<attr::SubjectMatchRule>,
1532 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1533 Rule = isAttributeSubjectMatchRule(Name);
1534 if (!Rule.first) {
1535 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1536 return true;
1537 }
1538 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1539 SourceLocation RuleLoc = ConsumeToken();
1540
1541 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1542 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1543 if (Parens.expectAndConsume())
1544 return true;
1545 } else if (Parens.consumeOpen()) {
1546 if (!SubjectMatchRules
1547 .insert(
1548 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1549 .second)
1550 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1551 << Name
1552 << FixItHint::CreateRemoval(SourceRange(
1553 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1554 LastMatchRuleEndLoc = RuleLoc;
1555 continue;
1556 }
1557
1558 // Parse the sub-rules.
1559 StringRef SubRuleName = getIdentifier(Tok);
1560 if (SubRuleName.empty()) {
1561 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1562 Tok.getLocation());
1563 return true;
1564 }
1565 attr::SubjectMatchRule SubRule;
1566 if (SubRuleName == "unless") {
1567 SourceLocation SubRuleLoc = ConsumeToken();
1568 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1569 if (Parens.expectAndConsume())
1570 return true;
1571 SubRuleName = getIdentifier(Tok);
1572 if (SubRuleName.empty()) {
1573 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1574 SubRuleLoc);
1575 return true;
1576 }
1577 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1578 if (!SubRuleOrNone) {
1579 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1580 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1581 SubRuleUnlessName, SubRuleLoc);
1582 return true;
1583 }
1584 SubRule = *SubRuleOrNone;
1585 ConsumeToken();
1586 if (Parens.consumeClose())
1587 return true;
1588 } else {
1589 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1590 if (!SubRuleOrNone) {
1591 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1592 SubRuleName, Tok.getLocation());
1593 return true;
1594 }
1595 SubRule = *SubRuleOrNone;
1596 ConsumeToken();
1597 }
1598 SourceLocation RuleEndLoc = Tok.getLocation();
1599 LastMatchRuleEndLoc = RuleEndLoc;
1600 if (Parens.consumeClose())
1601 return true;
1602 if (!SubjectMatchRules
1603 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1604 .second) {
1605 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1606 << attr::getSubjectMatchRuleSpelling(SubRule)
1607 << FixItHint::CreateRemoval(SourceRange(
1608 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1609 continue;
1610 }
1611 } while (IsAny && TryConsumeToken(tok::comma));
1612
1613 if (IsAny)
1614 if (AnyParens.consumeClose())
1615 return true;
1616
1617 return false;
1618 }
1619
1620 namespace {
1621
1622 /// Describes the stage at which attribute subject rule parsing was interrupted.
1623 enum class MissingAttributeSubjectRulesRecoveryPoint {
1624 Comma,
1625 ApplyTo,
1626 Equals,
1627 Any,
1628 None,
1629 };
1630
1631 MissingAttributeSubjectRulesRecoveryPoint
getAttributeSubjectRulesRecoveryPointForToken(const Token & Tok)1632 getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1633 if (const auto *II = Tok.getIdentifierInfo()) {
1634 if (II->isStr("apply_to"))
1635 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1636 if (II->isStr("any"))
1637 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1638 }
1639 if (Tok.is(tok::equal))
1640 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1641 return MissingAttributeSubjectRulesRecoveryPoint::None;
1642 }
1643
1644 /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1645 /// suggests the possible attribute subject rules in a fix-it together with
1646 /// any other missing tokens.
createExpectedAttributeSubjectRulesTokenDiagnostic(unsigned DiagID,ParsedAttributes & Attrs,MissingAttributeSubjectRulesRecoveryPoint Point,Parser & PRef)1647 DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1648 unsigned DiagID, ParsedAttributes &Attrs,
1649 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1650 SourceLocation Loc = PRef.getEndOfPreviousToken();
1651 if (Loc.isInvalid())
1652 Loc = PRef.getCurToken().getLocation();
1653 auto Diagnostic = PRef.Diag(Loc, DiagID);
1654 std::string FixIt;
1655 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1656 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1657 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1658 FixIt = ", ";
1659 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1660 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1661 FixIt += "apply_to";
1662 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1663 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1664 FixIt += " = ";
1665 SourceRange FixItRange(Loc);
1666 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1667 // Gather the subject match rules that are supported by the attribute.
1668 // Add all the possible rules initially.
1669 llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
1670 // Remove the ones that are not supported by any of the attributes.
1671 for (const ParsedAttr &Attribute : Attrs) {
1672 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
1673 Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
1674 llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
1675 for (const auto &Rule : MatchRules) {
1676 // Ensure that the missing rule is reported in the fix-it only when it's
1677 // supported in the current language mode.
1678 if (!Rule.second)
1679 continue;
1680 IsSupported[Rule.first] = true;
1681 }
1682 IsMatchRuleAvailable &= IsSupported;
1683 }
1684 if (IsMatchRuleAvailable.count() == 0) {
1685 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1686 // placeholders will be supported by the fix-its.
1687 return Diagnostic;
1688 }
1689 FixIt += "any(";
1690 bool NeedsComma = false;
1691 for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
1692 if (!IsMatchRuleAvailable[I])
1693 continue;
1694 if (NeedsComma)
1695 FixIt += ", ";
1696 else
1697 NeedsComma = true;
1698 FixIt += attr::getSubjectMatchRuleSpelling(
1699 static_cast<attr::SubjectMatchRule>(I));
1700 }
1701 FixIt += ")";
1702 // Check if we need to remove the range
1703 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1704 FixItRange.setEnd(PRef.getCurToken().getLocation());
1705 }
1706 if (FixItRange.getBegin() == FixItRange.getEnd())
1707 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1708 else
1709 Diagnostic << FixItHint::CreateReplacement(
1710 CharSourceRange::getCharRange(FixItRange), FixIt);
1711 return Diagnostic;
1712 }
1713
1714 } // end anonymous namespace
1715
HandlePragmaAttribute()1716 void Parser::HandlePragmaAttribute() {
1717 assert(Tok.is(tok::annot_pragma_attribute) &&
1718 "Expected #pragma attribute annotation token");
1719 SourceLocation PragmaLoc = Tok.getLocation();
1720 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1721 if (Info->Action == PragmaAttributeInfo::Pop) {
1722 ConsumeAnnotationToken();
1723 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1724 return;
1725 }
1726 // Parse the actual attribute with its arguments.
1727 assert((Info->Action == PragmaAttributeInfo::Push ||
1728 Info->Action == PragmaAttributeInfo::Attribute) &&
1729 "Unexpected #pragma attribute command");
1730
1731 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1732 ConsumeAnnotationToken();
1733 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1734 return;
1735 }
1736
1737 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1738 /*IsReinject=*/false);
1739 ConsumeAnnotationToken();
1740
1741 ParsedAttributes &Attrs = Info->Attributes;
1742 Attrs.clearListOnly();
1743
1744 auto SkipToEnd = [this]() {
1745 SkipUntil(tok::eof, StopBeforeMatch);
1746 ConsumeToken();
1747 };
1748
1749 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1750 // Parse the CXX11 style attribute.
1751 ParseCXX11AttributeSpecifier(Attrs);
1752 } else if (Tok.is(tok::kw___attribute)) {
1753 ConsumeToken();
1754 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1755 "attribute"))
1756 return SkipToEnd();
1757 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1758 return SkipToEnd();
1759
1760 // FIXME: The practical usefulness of completion here is limited because
1761 // we only get here if the line has balanced parens.
1762 if (Tok.is(tok::code_completion)) {
1763 cutOffParsing();
1764 // FIXME: suppress completion of unsupported attributes?
1765 Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
1766 return SkipToEnd();
1767 }
1768
1769 // Parse the comma-separated list of attributes.
1770 do {
1771 if (Tok.isNot(tok::identifier)) {
1772 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1773 SkipToEnd();
1774 return;
1775 }
1776 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1777 SourceLocation AttrNameLoc = ConsumeToken();
1778
1779 if (Tok.isNot(tok::l_paren))
1780 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1781 ParsedAttr::AS_GNU);
1782 else
1783 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1784 /*ScopeName=*/nullptr,
1785 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
1786 /*Declarator=*/nullptr);
1787 } while (TryConsumeToken(tok::comma));
1788
1789 if (ExpectAndConsume(tok::r_paren))
1790 return SkipToEnd();
1791 if (ExpectAndConsume(tok::r_paren))
1792 return SkipToEnd();
1793 } else if (Tok.is(tok::kw___declspec)) {
1794 ParseMicrosoftDeclSpecs(Attrs);
1795 } else {
1796 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1797 if (Tok.getIdentifierInfo()) {
1798 // If we suspect that this is an attribute suggest the use of
1799 // '__attribute__'.
1800 if (ParsedAttr::getParsedKind(
1801 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1802 ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
1803 SourceLocation InsertStartLoc = Tok.getLocation();
1804 ConsumeToken();
1805 if (Tok.is(tok::l_paren)) {
1806 ConsumeAnyToken();
1807 SkipUntil(tok::r_paren, StopBeforeMatch);
1808 if (Tok.isNot(tok::r_paren))
1809 return SkipToEnd();
1810 }
1811 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1812 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1813 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1814 }
1815 }
1816 SkipToEnd();
1817 return;
1818 }
1819
1820 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
1821 SkipToEnd();
1822 return;
1823 }
1824
1825 for (const ParsedAttr &Attribute : Attrs) {
1826 if (!Attribute.isSupportedByPragmaAttribute()) {
1827 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1828 << Attribute;
1829 SkipToEnd();
1830 return;
1831 }
1832 }
1833
1834 // Parse the subject-list.
1835 if (!TryConsumeToken(tok::comma)) {
1836 createExpectedAttributeSubjectRulesTokenDiagnostic(
1837 diag::err_expected, Attrs,
1838 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1839 << tok::comma;
1840 SkipToEnd();
1841 return;
1842 }
1843
1844 if (Tok.isNot(tok::identifier)) {
1845 createExpectedAttributeSubjectRulesTokenDiagnostic(
1846 diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1847 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1848 SkipToEnd();
1849 return;
1850 }
1851 const IdentifierInfo *II = Tok.getIdentifierInfo();
1852 if (!II->isStr("apply_to")) {
1853 createExpectedAttributeSubjectRulesTokenDiagnostic(
1854 diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1855 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1856 SkipToEnd();
1857 return;
1858 }
1859 ConsumeToken();
1860
1861 if (!TryConsumeToken(tok::equal)) {
1862 createExpectedAttributeSubjectRulesTokenDiagnostic(
1863 diag::err_expected, Attrs,
1864 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1865 << tok::equal;
1866 SkipToEnd();
1867 return;
1868 }
1869
1870 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1871 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1872 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1873 LastMatchRuleEndLoc)) {
1874 SkipToEnd();
1875 return;
1876 }
1877
1878 // Tokens following an ill-formed attribute will remain in the token stream
1879 // and must be removed.
1880 if (Tok.isNot(tok::eof)) {
1881 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1882 SkipToEnd();
1883 return;
1884 }
1885
1886 // Consume the eof terminator token.
1887 ConsumeToken();
1888
1889 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1890 if (Info->Action == PragmaAttributeInfo::Push)
1891 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1892
1893 for (ParsedAttr &Attribute : Attrs) {
1894 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1895 SubjectMatchRules);
1896 }
1897 }
1898
1899 // #pragma GCC visibility comes in two variants:
1900 // 'push' '(' [visibility] ')'
1901 // 'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & VisTok)1902 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1903 PragmaIntroducer Introducer,
1904 Token &VisTok) {
1905 SourceLocation VisLoc = VisTok.getLocation();
1906
1907 Token Tok;
1908 PP.LexUnexpandedToken(Tok);
1909
1910 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1911
1912 const IdentifierInfo *VisType;
1913 if (PushPop && PushPop->isStr("pop")) {
1914 VisType = nullptr;
1915 } else if (PushPop && PushPop->isStr("push")) {
1916 PP.LexUnexpandedToken(Tok);
1917 if (Tok.isNot(tok::l_paren)) {
1918 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1919 << "visibility";
1920 return;
1921 }
1922 PP.LexUnexpandedToken(Tok);
1923 VisType = Tok.getIdentifierInfo();
1924 if (!VisType) {
1925 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1926 << "visibility";
1927 return;
1928 }
1929 PP.LexUnexpandedToken(Tok);
1930 if (Tok.isNot(tok::r_paren)) {
1931 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1932 << "visibility";
1933 return;
1934 }
1935 } else {
1936 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1937 << "visibility";
1938 return;
1939 }
1940 SourceLocation EndLoc = Tok.getLocation();
1941 PP.LexUnexpandedToken(Tok);
1942 if (Tok.isNot(tok::eod)) {
1943 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1944 << "visibility";
1945 return;
1946 }
1947
1948 auto Toks = std::make_unique<Token[]>(1);
1949 Toks[0].startToken();
1950 Toks[0].setKind(tok::annot_pragma_vis);
1951 Toks[0].setLocation(VisLoc);
1952 Toks[0].setAnnotationEndLoc(EndLoc);
1953 Toks[0].setAnnotationValue(
1954 const_cast<void *>(static_cast<const void *>(VisType)));
1955 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1956 /*IsReinject=*/false);
1957 }
1958
1959 // #pragma pack(...) comes in the following delicious flavors:
1960 // pack '(' [integer] ')'
1961 // pack '(' 'show' ')'
1962 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & PackTok)1963 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1964 PragmaIntroducer Introducer,
1965 Token &PackTok) {
1966 SourceLocation PackLoc = PackTok.getLocation();
1967
1968 Token Tok;
1969 PP.Lex(Tok);
1970 if (Tok.isNot(tok::l_paren)) {
1971 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
1972 return;
1973 }
1974
1975 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1976 StringRef SlotLabel;
1977 Token Alignment;
1978 Alignment.startToken();
1979 PP.Lex(Tok);
1980 if (Tok.is(tok::numeric_constant)) {
1981 Alignment = Tok;
1982
1983 PP.Lex(Tok);
1984
1985 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1986 // the push/pop stack.
1987 // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
1988 Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
1989 ? Sema::PSK_Push_Set
1990 : Sema::PSK_Set;
1991 } else if (Tok.is(tok::identifier)) {
1992 const IdentifierInfo *II = Tok.getIdentifierInfo();
1993 if (II->isStr("show")) {
1994 Action = Sema::PSK_Show;
1995 PP.Lex(Tok);
1996 } else {
1997 if (II->isStr("push")) {
1998 Action = Sema::PSK_Push;
1999 } else if (II->isStr("pop")) {
2000 Action = Sema::PSK_Pop;
2001 } else {
2002 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
2003 return;
2004 }
2005 PP.Lex(Tok);
2006
2007 if (Tok.is(tok::comma)) {
2008 PP.Lex(Tok);
2009
2010 if (Tok.is(tok::numeric_constant)) {
2011 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2012 Alignment = Tok;
2013
2014 PP.Lex(Tok);
2015 } else if (Tok.is(tok::identifier)) {
2016 SlotLabel = Tok.getIdentifierInfo()->getName();
2017 PP.Lex(Tok);
2018
2019 if (Tok.is(tok::comma)) {
2020 PP.Lex(Tok);
2021
2022 if (Tok.isNot(tok::numeric_constant)) {
2023 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2024 return;
2025 }
2026
2027 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2028 Alignment = Tok;
2029
2030 PP.Lex(Tok);
2031 }
2032 } else {
2033 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2034 return;
2035 }
2036 }
2037 }
2038 } else if (PP.getLangOpts().ApplePragmaPack ||
2039 PP.getLangOpts().XLPragmaPack) {
2040 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2041 // the push/pop stack.
2042 // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2043 // pack(pop).
2044 Action = Sema::PSK_Pop;
2045 }
2046
2047 if (Tok.isNot(tok::r_paren)) {
2048 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
2049 return;
2050 }
2051
2052 SourceLocation RParenLoc = Tok.getLocation();
2053 PP.Lex(Tok);
2054 if (Tok.isNot(tok::eod)) {
2055 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
2056 return;
2057 }
2058
2059 PragmaPackInfo *Info =
2060 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
2061 Info->Action = Action;
2062 Info->SlotLabel = SlotLabel;
2063 Info->Alignment = Alignment;
2064
2065 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2066 1);
2067 Toks[0].startToken();
2068 Toks[0].setKind(tok::annot_pragma_pack);
2069 Toks[0].setLocation(PackLoc);
2070 Toks[0].setAnnotationEndLoc(RParenLoc);
2071 Toks[0].setAnnotationValue(static_cast<void*>(Info));
2072 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2073 /*IsReinject=*/false);
2074 }
2075
2076 // #pragma ms_struct on
2077 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & MSStructTok)2078 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
2079 PragmaIntroducer Introducer,
2080 Token &MSStructTok) {
2081 PragmaMSStructKind Kind = PMSST_OFF;
2082
2083 Token Tok;
2084 PP.Lex(Tok);
2085 if (Tok.isNot(tok::identifier)) {
2086 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2087 return;
2088 }
2089 SourceLocation EndLoc = Tok.getLocation();
2090 const IdentifierInfo *II = Tok.getIdentifierInfo();
2091 if (II->isStr("on")) {
2092 Kind = PMSST_ON;
2093 PP.Lex(Tok);
2094 }
2095 else if (II->isStr("off") || II->isStr("reset"))
2096 PP.Lex(Tok);
2097 else {
2098 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2099 return;
2100 }
2101
2102 if (Tok.isNot(tok::eod)) {
2103 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2104 << "ms_struct";
2105 return;
2106 }
2107
2108 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2109 1);
2110 Toks[0].startToken();
2111 Toks[0].setKind(tok::annot_pragma_msstruct);
2112 Toks[0].setLocation(MSStructTok.getLocation());
2113 Toks[0].setAnnotationEndLoc(EndLoc);
2114 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2115 static_cast<uintptr_t>(Kind)));
2116 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2117 /*IsReinject=*/false);
2118 }
2119
2120 // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)2121 void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
2122 PragmaIntroducer Introducer,
2123 Token &FirstToken) {
2124
2125 Token Tok;
2126 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
2127
2128 PP.Lex(Tok); // eat 'section'
2129 while (Tok.isNot(tok::eod)) {
2130 if (Tok.isNot(tok::identifier)) {
2131 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2132 return;
2133 }
2134
2135 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
2136 if (SecType->isStr("bss"))
2137 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
2138 else if (SecType->isStr("data"))
2139 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
2140 else if (SecType->isStr("rodata"))
2141 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
2142 else if (SecType->isStr("relro"))
2143 SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
2144 else if (SecType->isStr("text"))
2145 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
2146 else {
2147 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2148 return;
2149 }
2150
2151 SourceLocation PragmaLocation = Tok.getLocation();
2152 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
2153 if (Tok.isNot(tok::equal)) {
2154 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
2155 return;
2156 }
2157
2158 std::string SecName;
2159 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
2160 return;
2161
2162 Actions.ActOnPragmaClangSection(
2163 PragmaLocation,
2164 (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
2165 : Sema::PragmaClangSectionAction::PCSA_Clear),
2166 SecKind, SecName);
2167 }
2168 }
2169
2170 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2171 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2172 // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)2173 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
2174 bool IsOptions) {
2175 Token Tok;
2176
2177 if (IsOptions) {
2178 PP.Lex(Tok);
2179 if (Tok.isNot(tok::identifier) ||
2180 !Tok.getIdentifierInfo()->isStr("align")) {
2181 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2182 return;
2183 }
2184 }
2185
2186 PP.Lex(Tok);
2187 if (PP.getLangOpts().XLPragmaPack) {
2188 if (Tok.isNot(tok::l_paren)) {
2189 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2190 return;
2191 }
2192 } else if (Tok.isNot(tok::equal)) {
2193 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2194 << IsOptions;
2195 return;
2196 }
2197
2198 PP.Lex(Tok);
2199 if (Tok.isNot(tok::identifier)) {
2200 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2201 << (IsOptions ? "options" : "align");
2202 return;
2203 }
2204
2205 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
2206 const IdentifierInfo *II = Tok.getIdentifierInfo();
2207 if (II->isStr("native"))
2208 Kind = Sema::POAK_Native;
2209 else if (II->isStr("natural"))
2210 Kind = Sema::POAK_Natural;
2211 else if (II->isStr("packed"))
2212 Kind = Sema::POAK_Packed;
2213 else if (II->isStr("power"))
2214 Kind = Sema::POAK_Power;
2215 else if (II->isStr("mac68k"))
2216 Kind = Sema::POAK_Mac68k;
2217 else if (II->isStr("reset"))
2218 Kind = Sema::POAK_Reset;
2219 else {
2220 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2221 << IsOptions;
2222 return;
2223 }
2224
2225 if (PP.getLangOpts().XLPragmaPack) {
2226 PP.Lex(Tok);
2227 if (Tok.isNot(tok::r_paren)) {
2228 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2229 return;
2230 }
2231 }
2232
2233 SourceLocation EndLoc = Tok.getLocation();
2234 PP.Lex(Tok);
2235 if (Tok.isNot(tok::eod)) {
2236 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2237 << (IsOptions ? "options" : "align");
2238 return;
2239 }
2240
2241 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2242 1);
2243 Toks[0].startToken();
2244 Toks[0].setKind(tok::annot_pragma_align);
2245 Toks[0].setLocation(FirstTok.getLocation());
2246 Toks[0].setAnnotationEndLoc(EndLoc);
2247 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2248 static_cast<uintptr_t>(Kind)));
2249 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2250 /*IsReinject=*/false);
2251 }
2252
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & AlignTok)2253 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2254 PragmaIntroducer Introducer,
2255 Token &AlignTok) {
2256 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2257 }
2258
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & OptionsTok)2259 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2260 PragmaIntroducer Introducer,
2261 Token &OptionsTok) {
2262 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2263 }
2264
2265 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & UnusedTok)2266 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2267 PragmaIntroducer Introducer,
2268 Token &UnusedTok) {
2269 // FIXME: Should we be expanding macros here? My guess is no.
2270 SourceLocation UnusedLoc = UnusedTok.getLocation();
2271
2272 // Lex the left '('.
2273 Token Tok;
2274 PP.Lex(Tok);
2275 if (Tok.isNot(tok::l_paren)) {
2276 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2277 return;
2278 }
2279
2280 // Lex the declaration reference(s).
2281 SmallVector<Token, 5> Identifiers;
2282 SourceLocation RParenLoc;
2283 bool LexID = true;
2284
2285 while (true) {
2286 PP.Lex(Tok);
2287
2288 if (LexID) {
2289 if (Tok.is(tok::identifier)) {
2290 Identifiers.push_back(Tok);
2291 LexID = false;
2292 continue;
2293 }
2294
2295 // Illegal token!
2296 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2297 return;
2298 }
2299
2300 // We are execting a ')' or a ','.
2301 if (Tok.is(tok::comma)) {
2302 LexID = true;
2303 continue;
2304 }
2305
2306 if (Tok.is(tok::r_paren)) {
2307 RParenLoc = Tok.getLocation();
2308 break;
2309 }
2310
2311 // Illegal token!
2312 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2313 return;
2314 }
2315
2316 PP.Lex(Tok);
2317 if (Tok.isNot(tok::eod)) {
2318 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2319 "unused";
2320 return;
2321 }
2322
2323 // Verify that we have a location for the right parenthesis.
2324 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2325 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2326
2327 // For each identifier token, insert into the token stream a
2328 // annot_pragma_unused token followed by the identifier token.
2329 // This allows us to cache a "#pragma unused" that occurs inside an inline
2330 // C++ member function.
2331
2332 MutableArrayRef<Token> Toks(
2333 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2334 2 * Identifiers.size());
2335 for (unsigned i=0; i != Identifiers.size(); i++) {
2336 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2337 pragmaUnusedTok.startToken();
2338 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2339 pragmaUnusedTok.setLocation(UnusedLoc);
2340 idTok = Identifiers[i];
2341 }
2342 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2343 /*IsReinject=*/false);
2344 }
2345
2346 // #pragma weak identifier
2347 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & WeakTok)2348 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2349 PragmaIntroducer Introducer,
2350 Token &WeakTok) {
2351 SourceLocation WeakLoc = WeakTok.getLocation();
2352
2353 Token Tok;
2354 PP.Lex(Tok);
2355 if (Tok.isNot(tok::identifier)) {
2356 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2357 return;
2358 }
2359
2360 Token WeakName = Tok;
2361 bool HasAlias = false;
2362 Token AliasName;
2363
2364 PP.Lex(Tok);
2365 if (Tok.is(tok::equal)) {
2366 HasAlias = true;
2367 PP.Lex(Tok);
2368 if (Tok.isNot(tok::identifier)) {
2369 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2370 << "weak";
2371 return;
2372 }
2373 AliasName = Tok;
2374 PP.Lex(Tok);
2375 }
2376
2377 if (Tok.isNot(tok::eod)) {
2378 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2379 return;
2380 }
2381
2382 if (HasAlias) {
2383 MutableArrayRef<Token> Toks(
2384 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2385 Token &pragmaUnusedTok = Toks[0];
2386 pragmaUnusedTok.startToken();
2387 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2388 pragmaUnusedTok.setLocation(WeakLoc);
2389 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2390 Toks[1] = WeakName;
2391 Toks[2] = AliasName;
2392 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2393 /*IsReinject=*/false);
2394 } else {
2395 MutableArrayRef<Token> Toks(
2396 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2397 Token &pragmaUnusedTok = Toks[0];
2398 pragmaUnusedTok.startToken();
2399 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2400 pragmaUnusedTok.setLocation(WeakLoc);
2401 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2402 Toks[1] = WeakName;
2403 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2404 /*IsReinject=*/false);
2405 }
2406 }
2407
2408 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & RedefToken)2409 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2410 PragmaIntroducer Introducer,
2411 Token &RedefToken) {
2412 SourceLocation RedefLoc = RedefToken.getLocation();
2413
2414 Token Tok;
2415 PP.Lex(Tok);
2416 if (Tok.isNot(tok::identifier)) {
2417 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2418 "redefine_extname";
2419 return;
2420 }
2421
2422 Token RedefName = Tok;
2423 PP.Lex(Tok);
2424
2425 if (Tok.isNot(tok::identifier)) {
2426 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2427 << "redefine_extname";
2428 return;
2429 }
2430
2431 Token AliasName = Tok;
2432 PP.Lex(Tok);
2433
2434 if (Tok.isNot(tok::eod)) {
2435 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2436 "redefine_extname";
2437 return;
2438 }
2439
2440 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2441 3);
2442 Token &pragmaRedefTok = Toks[0];
2443 pragmaRedefTok.startToken();
2444 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2445 pragmaRedefTok.setLocation(RedefLoc);
2446 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2447 Toks[1] = RedefName;
2448 Toks[2] = AliasName;
2449 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2450 /*IsReinject=*/false);
2451 }
2452
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2453 void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2454 PragmaIntroducer Introducer,
2455 Token &Tok) {
2456 tok::OnOffSwitch OOS;
2457 if (PP.LexOnOffSwitch(OOS))
2458 return;
2459
2460 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2461 1);
2462 Toks[0].startToken();
2463 Toks[0].setKind(tok::annot_pragma_fp_contract);
2464 Toks[0].setLocation(Tok.getLocation());
2465 Toks[0].setAnnotationEndLoc(Tok.getLocation());
2466 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2467 static_cast<uintptr_t>(OOS)));
2468 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2469 /*IsReinject=*/false);
2470 }
2471
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2472 void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2473 PragmaIntroducer Introducer,
2474 Token &Tok) {
2475 PP.LexUnexpandedToken(Tok);
2476 if (Tok.isNot(tok::identifier)) {
2477 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2478 "OPENCL";
2479 return;
2480 }
2481 IdentifierInfo *Ext = Tok.getIdentifierInfo();
2482 SourceLocation NameLoc = Tok.getLocation();
2483
2484 PP.Lex(Tok);
2485 if (Tok.isNot(tok::colon)) {
2486 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2487 return;
2488 }
2489
2490 PP.Lex(Tok);
2491 if (Tok.isNot(tok::identifier)) {
2492 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2493 return;
2494 }
2495 IdentifierInfo *Pred = Tok.getIdentifierInfo();
2496
2497 OpenCLExtState State;
2498 if (Pred->isStr("enable")) {
2499 State = Enable;
2500 } else if (Pred->isStr("disable")) {
2501 State = Disable;
2502 } else if (Pred->isStr("begin"))
2503 State = Begin;
2504 else if (Pred->isStr("end"))
2505 State = End;
2506 else {
2507 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2508 << Ext->isStr("all");
2509 return;
2510 }
2511 SourceLocation StateLoc = Tok.getLocation();
2512
2513 PP.Lex(Tok);
2514 if (Tok.isNot(tok::eod)) {
2515 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2516 "OPENCL EXTENSION";
2517 return;
2518 }
2519
2520 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2521 Info->first = Ext;
2522 Info->second = State;
2523 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2524 1);
2525 Toks[0].startToken();
2526 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2527 Toks[0].setLocation(NameLoc);
2528 Toks[0].setAnnotationValue(static_cast<void*>(Info));
2529 Toks[0].setAnnotationEndLoc(StateLoc);
2530 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2531 /*IsReinject=*/false);
2532
2533 if (PP.getPPCallbacks())
2534 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2535 StateLoc, State);
2536 }
2537
2538 /// Handle '#pragma omp ...' when OpenMP is disabled.
2539 ///
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2540 void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2541 PragmaIntroducer Introducer,
2542 Token &FirstTok) {
2543 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2544 FirstTok.getLocation())) {
2545 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
2546 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2547 diag::Severity::Ignored, SourceLocation());
2548 }
2549 PP.DiscardUntilEndOfDirective();
2550 }
2551
2552 /// Handle '#pragma omp ...' when OpenMP is enabled.
2553 ///
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2554 void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2555 PragmaIntroducer Introducer,
2556 Token &FirstTok) {
2557 SmallVector<Token, 16> Pragma;
2558 Token Tok;
2559 Tok.startToken();
2560 Tok.setKind(tok::annot_pragma_openmp);
2561 Tok.setLocation(Introducer.Loc);
2562
2563 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
2564 Pragma.push_back(Tok);
2565 PP.Lex(Tok);
2566 if (Tok.is(tok::annot_pragma_openmp)) {
2567 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2568 unsigned InnerPragmaCnt = 1;
2569 while (InnerPragmaCnt != 0) {
2570 PP.Lex(Tok);
2571 if (Tok.is(tok::annot_pragma_openmp))
2572 ++InnerPragmaCnt;
2573 else if (Tok.is(tok::annot_pragma_openmp_end))
2574 --InnerPragmaCnt;
2575 }
2576 PP.Lex(Tok);
2577 }
2578 }
2579 SourceLocation EodLoc = Tok.getLocation();
2580 Tok.startToken();
2581 Tok.setKind(tok::annot_pragma_openmp_end);
2582 Tok.setLocation(EodLoc);
2583 Pragma.push_back(Tok);
2584
2585 auto Toks = std::make_unique<Token[]>(Pragma.size());
2586 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2587 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2588 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2589 }
2590
2591 /// Handle '#pragma pointers_to_members'
2592 // The grammar for this pragma is as follows:
2593 //
2594 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2595 //
2596 // #pragma pointers_to_members '(' 'best_case' ')'
2597 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2598 // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2599 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2600 PragmaIntroducer Introducer,
2601 Token &Tok) {
2602 SourceLocation PointersToMembersLoc = Tok.getLocation();
2603 PP.Lex(Tok);
2604 if (Tok.isNot(tok::l_paren)) {
2605 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2606 << "pointers_to_members";
2607 return;
2608 }
2609 PP.Lex(Tok);
2610 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2611 if (!Arg) {
2612 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2613 << "pointers_to_members";
2614 return;
2615 }
2616 PP.Lex(Tok);
2617
2618 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2619 if (Arg->isStr("best_case")) {
2620 RepresentationMethod = LangOptions::PPTMK_BestCase;
2621 } else {
2622 if (Arg->isStr("full_generality")) {
2623 if (Tok.is(tok::comma)) {
2624 PP.Lex(Tok);
2625
2626 Arg = Tok.getIdentifierInfo();
2627 if (!Arg) {
2628 PP.Diag(Tok.getLocation(),
2629 diag::err_pragma_pointers_to_members_unknown_kind)
2630 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2631 return;
2632 }
2633 PP.Lex(Tok);
2634 } else if (Tok.is(tok::r_paren)) {
2635 // #pragma pointers_to_members(full_generality) implicitly specifies
2636 // virtual_inheritance.
2637 Arg = nullptr;
2638 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2639 } else {
2640 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2641 << "full_generality";
2642 return;
2643 }
2644 }
2645
2646 if (Arg) {
2647 if (Arg->isStr("single_inheritance")) {
2648 RepresentationMethod =
2649 LangOptions::PPTMK_FullGeneralitySingleInheritance;
2650 } else if (Arg->isStr("multiple_inheritance")) {
2651 RepresentationMethod =
2652 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
2653 } else if (Arg->isStr("virtual_inheritance")) {
2654 RepresentationMethod =
2655 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2656 } else {
2657 PP.Diag(Tok.getLocation(),
2658 diag::err_pragma_pointers_to_members_unknown_kind)
2659 << Arg << /*HasPointerDeclaration*/ 1;
2660 return;
2661 }
2662 }
2663 }
2664
2665 if (Tok.isNot(tok::r_paren)) {
2666 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2667 << (Arg ? Arg->getName() : "full_generality");
2668 return;
2669 }
2670
2671 SourceLocation EndLoc = Tok.getLocation();
2672 PP.Lex(Tok);
2673 if (Tok.isNot(tok::eod)) {
2674 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2675 << "pointers_to_members";
2676 return;
2677 }
2678
2679 Token AnnotTok;
2680 AnnotTok.startToken();
2681 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2682 AnnotTok.setLocation(PointersToMembersLoc);
2683 AnnotTok.setAnnotationEndLoc(EndLoc);
2684 AnnotTok.setAnnotationValue(
2685 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2686 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2687 }
2688
2689 /// Handle '#pragma vtordisp'
2690 // The grammar for this pragma is as follows:
2691 //
2692 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2693 //
2694 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2695 // #pragma vtordisp '(' 'pop' ')'
2696 // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2697 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2698 PragmaIntroducer Introducer, Token &Tok) {
2699 SourceLocation VtorDispLoc = Tok.getLocation();
2700 PP.Lex(Tok);
2701 if (Tok.isNot(tok::l_paren)) {
2702 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2703 return;
2704 }
2705 PP.Lex(Tok);
2706
2707 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2708 const IdentifierInfo *II = Tok.getIdentifierInfo();
2709 if (II) {
2710 if (II->isStr("push")) {
2711 // #pragma vtordisp(push, mode)
2712 PP.Lex(Tok);
2713 if (Tok.isNot(tok::comma)) {
2714 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2715 return;
2716 }
2717 PP.Lex(Tok);
2718 Action = Sema::PSK_Push_Set;
2719 // not push, could be on/off
2720 } else if (II->isStr("pop")) {
2721 // #pragma vtordisp(pop)
2722 PP.Lex(Tok);
2723 Action = Sema::PSK_Pop;
2724 }
2725 // not push or pop, could be on/off
2726 } else {
2727 if (Tok.is(tok::r_paren)) {
2728 // #pragma vtordisp()
2729 Action = Sema::PSK_Reset;
2730 }
2731 }
2732
2733
2734 uint64_t Value = 0;
2735 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
2736 const IdentifierInfo *II = Tok.getIdentifierInfo();
2737 if (II && II->isStr("off")) {
2738 PP.Lex(Tok);
2739 Value = 0;
2740 } else if (II && II->isStr("on")) {
2741 PP.Lex(Tok);
2742 Value = 1;
2743 } else if (Tok.is(tok::numeric_constant) &&
2744 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2745 if (Value > 2) {
2746 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2747 << 0 << 2 << "vtordisp";
2748 return;
2749 }
2750 } else {
2751 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2752 << "vtordisp";
2753 return;
2754 }
2755 }
2756
2757 // Finish the pragma: ')' $
2758 if (Tok.isNot(tok::r_paren)) {
2759 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2760 return;
2761 }
2762 SourceLocation EndLoc = Tok.getLocation();
2763 PP.Lex(Tok);
2764 if (Tok.isNot(tok::eod)) {
2765 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2766 << "vtordisp";
2767 return;
2768 }
2769
2770 // Enter the annotation.
2771 Token AnnotTok;
2772 AnnotTok.startToken();
2773 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2774 AnnotTok.setLocation(VtorDispLoc);
2775 AnnotTok.setAnnotationEndLoc(EndLoc);
2776 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2777 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2778 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2779 }
2780
2781 /// Handle all MS pragmas. Simply forwards the tokens after inserting
2782 /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2783 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2784 PragmaIntroducer Introducer, Token &Tok) {
2785 Token EoF, AnnotTok;
2786 EoF.startToken();
2787 EoF.setKind(tok::eof);
2788 AnnotTok.startToken();
2789 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2790 AnnotTok.setLocation(Tok.getLocation());
2791 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2792 SmallVector<Token, 8> TokenVector;
2793 // Suck up all of the tokens before the eod.
2794 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
2795 TokenVector.push_back(Tok);
2796 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2797 }
2798 // Add a sentinel EoF token to the end of the list.
2799 TokenVector.push_back(EoF);
2800 // We must allocate this array with new because EnterTokenStream is going to
2801 // delete it later.
2802 markAsReinjectedForRelexing(TokenVector);
2803 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2804 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2805 auto Value = new (PP.getPreprocessorAllocator())
2806 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2807 TokenVector.size());
2808 AnnotTok.setAnnotationValue(Value);
2809 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2810 }
2811
2812 /// Handle the \#pragma float_control extension.
2813 ///
2814 /// The syntax is:
2815 /// \code
2816 /// #pragma float_control(keyword[, setting] [,push])
2817 /// \endcode
2818 /// Where 'keyword' and 'setting' are identifiers.
2819 // 'keyword' can be: precise, except, push, pop
2820 // 'setting' can be: on, off
2821 /// The optional arguments 'setting' and 'push' are supported only
2822 /// when the keyword is 'precise' or 'except'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2823 void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
2824 PragmaIntroducer Introducer,
2825 Token &Tok) {
2826 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2827 SourceLocation FloatControlLoc = Tok.getLocation();
2828 Token PragmaName = Tok;
2829 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
2830 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
2831 << PragmaName.getIdentifierInfo()->getName();
2832 return;
2833 }
2834 PP.Lex(Tok);
2835 if (Tok.isNot(tok::l_paren)) {
2836 PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
2837 return;
2838 }
2839
2840 // Read the identifier.
2841 PP.Lex(Tok);
2842 if (Tok.isNot(tok::identifier)) {
2843 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2844 return;
2845 }
2846
2847 // Verify that this is one of the float control options.
2848 IdentifierInfo *II = Tok.getIdentifierInfo();
2849 PragmaFloatControlKind Kind =
2850 llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
2851 .Case("precise", PFC_Precise)
2852 .Case("except", PFC_Except)
2853 .Case("push", PFC_Push)
2854 .Case("pop", PFC_Pop)
2855 .Default(PFC_Unknown);
2856 PP.Lex(Tok); // the identifier
2857 if (Kind == PFC_Unknown) {
2858 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2859 return;
2860 } else if (Kind == PFC_Push || Kind == PFC_Pop) {
2861 if (Tok.isNot(tok::r_paren)) {
2862 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2863 return;
2864 }
2865 PP.Lex(Tok); // Eat the r_paren
2866 Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
2867 } else {
2868 if (Tok.is(tok::r_paren))
2869 // Selecting Precise or Except
2870 PP.Lex(Tok); // the r_paren
2871 else if (Tok.isNot(tok::comma)) {
2872 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2873 return;
2874 } else {
2875 PP.Lex(Tok); // ,
2876 if (!Tok.isAnyIdentifier()) {
2877 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2878 return;
2879 }
2880 StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
2881 if (PushOnOff == "on")
2882 // Kind is set correctly
2883 ;
2884 else if (PushOnOff == "off") {
2885 if (Kind == PFC_Precise)
2886 Kind = PFC_NoPrecise;
2887 if (Kind == PFC_Except)
2888 Kind = PFC_NoExcept;
2889 } else if (PushOnOff == "push") {
2890 Action = Sema::PSK_Push_Set;
2891 } else {
2892 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2893 return;
2894 }
2895 PP.Lex(Tok); // the identifier
2896 if (Tok.is(tok::comma)) {
2897 PP.Lex(Tok); // ,
2898 if (!Tok.isAnyIdentifier()) {
2899 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2900 return;
2901 }
2902 StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
2903 if (ExpectedPush == "push") {
2904 Action = Sema::PSK_Push_Set;
2905 } else {
2906 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2907 return;
2908 }
2909 PP.Lex(Tok); // the push identifier
2910 }
2911 if (Tok.isNot(tok::r_paren)) {
2912 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2913 return;
2914 }
2915 PP.Lex(Tok); // the r_paren
2916 }
2917 }
2918 SourceLocation EndLoc = Tok.getLocation();
2919 if (Tok.isNot(tok::eod)) {
2920 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2921 << "float_control";
2922 return;
2923 }
2924
2925 // Note: there is no accomodation for PP callback for this pragma.
2926
2927 // Enter the annotation.
2928 auto TokenArray = std::make_unique<Token[]>(1);
2929 TokenArray[0].startToken();
2930 TokenArray[0].setKind(tok::annot_pragma_float_control);
2931 TokenArray[0].setLocation(FloatControlLoc);
2932 TokenArray[0].setAnnotationEndLoc(EndLoc);
2933 // Create an encoding of Action and Value by shifting the Action into
2934 // the high 16 bits then union with the Kind.
2935 TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
2936 static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
2937 PP.EnterTokenStream(std::move(TokenArray), 1,
2938 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2939 }
2940
2941 /// Handle the Microsoft \#pragma detect_mismatch extension.
2942 ///
2943 /// The syntax is:
2944 /// \code
2945 /// #pragma detect_mismatch("name", "value")
2946 /// \endcode
2947 /// Where 'name' and 'value' are quoted strings. The values are embedded in
2948 /// the object file and passed along to the linker. If the linker detects a
2949 /// mismatch in the object file's values for the given name, a LNK2038 error
2950 /// is emitted. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2951 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2952 PragmaIntroducer Introducer,
2953 Token &Tok) {
2954 SourceLocation DetectMismatchLoc = Tok.getLocation();
2955 PP.Lex(Tok);
2956 if (Tok.isNot(tok::l_paren)) {
2957 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
2958 return;
2959 }
2960
2961 // Read the name to embed, which must be a string literal.
2962 std::string NameString;
2963 if (!PP.LexStringLiteral(Tok, NameString,
2964 "pragma detect_mismatch",
2965 /*AllowMacroExpansion=*/true))
2966 return;
2967
2968 // Read the comma followed by a second string literal.
2969 std::string ValueString;
2970 if (Tok.isNot(tok::comma)) {
2971 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2972 return;
2973 }
2974
2975 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2976 /*AllowMacroExpansion=*/true))
2977 return;
2978
2979 if (Tok.isNot(tok::r_paren)) {
2980 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2981 return;
2982 }
2983 PP.Lex(Tok); // Eat the r_paren.
2984
2985 if (Tok.isNot(tok::eod)) {
2986 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2987 return;
2988 }
2989
2990 // If the pragma is lexically sound, notify any interested PPCallbacks.
2991 if (PP.getPPCallbacks())
2992 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
2993 ValueString);
2994
2995 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
2996 }
2997
2998 /// Handle the microsoft \#pragma comment extension.
2999 ///
3000 /// The syntax is:
3001 /// \code
3002 /// #pragma comment(linker, "foo")
3003 /// \endcode
3004 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
3005 /// "foo" is a string, which is fully macro expanded, and permits string
3006 /// concatenation, embedded escape characters etc. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3007 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
3008 PragmaIntroducer Introducer,
3009 Token &Tok) {
3010 SourceLocation CommentLoc = Tok.getLocation();
3011 PP.Lex(Tok);
3012 if (Tok.isNot(tok::l_paren)) {
3013 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3014 return;
3015 }
3016
3017 // Read the identifier.
3018 PP.Lex(Tok);
3019 if (Tok.isNot(tok::identifier)) {
3020 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3021 return;
3022 }
3023
3024 // Verify that this is one of the 5 explicitly listed options.
3025 IdentifierInfo *II = Tok.getIdentifierInfo();
3026 PragmaMSCommentKind Kind =
3027 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
3028 .Case("linker", PCK_Linker)
3029 .Case("lib", PCK_Lib)
3030 .Case("compiler", PCK_Compiler)
3031 .Case("exestr", PCK_ExeStr)
3032 .Case("user", PCK_User)
3033 .Default(PCK_Unknown);
3034 if (Kind == PCK_Unknown) {
3035 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
3036 return;
3037 }
3038
3039 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
3040 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3041 << II->getName();
3042 return;
3043 }
3044
3045 // Read the optional string if present.
3046 PP.Lex(Tok);
3047 std::string ArgumentString;
3048 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
3049 "pragma comment",
3050 /*AllowMacroExpansion=*/true))
3051 return;
3052
3053 // FIXME: warn that 'exestr' is deprecated.
3054 // FIXME: If the kind is "compiler" warn if the string is present (it is
3055 // ignored).
3056 // The MSDN docs say that "lib" and "linker" require a string and have a short
3057 // list of linker options they support, but in practice MSVC doesn't
3058 // issue a diagnostic. Therefore neither does clang.
3059
3060 if (Tok.isNot(tok::r_paren)) {
3061 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3062 return;
3063 }
3064 PP.Lex(Tok); // eat the r_paren.
3065
3066 if (Tok.isNot(tok::eod)) {
3067 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3068 return;
3069 }
3070
3071 // If the pragma is lexically sound, notify any interested PPCallbacks.
3072 if (PP.getPPCallbacks())
3073 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
3074
3075 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
3076 }
3077
3078 // #pragma clang optimize off
3079 // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3080 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
3081 PragmaIntroducer Introducer,
3082 Token &FirstToken) {
3083 Token Tok;
3084 PP.Lex(Tok);
3085 if (Tok.is(tok::eod)) {
3086 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3087 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3088 return;
3089 }
3090 if (Tok.isNot(tok::identifier)) {
3091 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3092 << PP.getSpelling(Tok);
3093 return;
3094 }
3095 const IdentifierInfo *II = Tok.getIdentifierInfo();
3096 // The only accepted values are 'on' or 'off'.
3097 bool IsOn = false;
3098 if (II->isStr("on")) {
3099 IsOn = true;
3100 } else if (!II->isStr("off")) {
3101 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3102 << PP.getSpelling(Tok);
3103 return;
3104 }
3105 PP.Lex(Tok);
3106
3107 if (Tok.isNot(tok::eod)) {
3108 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
3109 << PP.getSpelling(Tok);
3110 return;
3111 }
3112
3113 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
3114 }
3115
3116 namespace {
3117 /// Used as the annotation value for tok::annot_pragma_fp.
3118 struct TokFPAnnotValue {
3119 enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod };
3120 enum FlagValues { On, Off, Fast };
3121
3122 llvm::Optional<LangOptions::FPModeKind> ContractValue;
3123 llvm::Optional<LangOptions::FPModeKind> ReassociateValue;
3124 llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3125 llvm::Optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
3126 };
3127 } // end anonymous namespace
3128
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3129 void PragmaFPHandler::HandlePragma(Preprocessor &PP,
3130 PragmaIntroducer Introducer, Token &Tok) {
3131 // fp
3132 Token PragmaName = Tok;
3133 SmallVector<Token, 1> TokenList;
3134
3135 PP.Lex(Tok);
3136 if (Tok.isNot(tok::identifier)) {
3137 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3138 << /*MissingOption=*/true << "";
3139 return;
3140 }
3141
3142 auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
3143 while (Tok.is(tok::identifier)) {
3144 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3145
3146 auto FlagKind =
3147 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
3148 OptionInfo->getName())
3149 .Case("contract", TokFPAnnotValue::Contract)
3150 .Case("reassociate", TokFPAnnotValue::Reassociate)
3151 .Case("exceptions", TokFPAnnotValue::Exceptions)
3152 .Case("eval_method", TokFPAnnotValue::EvalMethod)
3153 .Default(None);
3154 if (!FlagKind) {
3155 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3156 << /*MissingOption=*/false << OptionInfo;
3157 return;
3158 }
3159 PP.Lex(Tok);
3160
3161 // Read '('
3162 if (Tok.isNot(tok::l_paren)) {
3163 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3164 return;
3165 }
3166 PP.Lex(Tok);
3167 bool isEvalMethodDouble =
3168 Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod;
3169
3170 // Don't diagnose if we have an eval_metod pragma with "double" kind.
3171 if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
3172 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3173 << PP.getSpelling(Tok) << OptionInfo->getName()
3174 << static_cast<int>(*FlagKind);
3175 return;
3176 }
3177 const IdentifierInfo *II = Tok.getIdentifierInfo();
3178
3179 if (FlagKind == TokFPAnnotValue::Contract) {
3180 AnnotValue->ContractValue =
3181 llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
3182 II->getName())
3183 .Case("on", LangOptions::FPModeKind::FPM_On)
3184 .Case("off", LangOptions::FPModeKind::FPM_Off)
3185 .Case("fast", LangOptions::FPModeKind::FPM_Fast)
3186 .Default(llvm::None);
3187 if (!AnnotValue->ContractValue) {
3188 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3189 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3190 return;
3191 }
3192 } else if (FlagKind == TokFPAnnotValue::Reassociate) {
3193 AnnotValue->ReassociateValue =
3194 llvm::StringSwitch<llvm::Optional<LangOptions::FPModeKind>>(
3195 II->getName())
3196 .Case("on", LangOptions::FPModeKind::FPM_On)
3197 .Case("off", LangOptions::FPModeKind::FPM_Off)
3198 .Default(llvm::None);
3199 if (!AnnotValue->ReassociateValue) {
3200 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3201 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3202 return;
3203 }
3204 } else if (FlagKind == TokFPAnnotValue::Exceptions) {
3205 AnnotValue->ExceptionsValue =
3206 llvm::StringSwitch<llvm::Optional<LangOptions::FPExceptionModeKind>>(
3207 II->getName())
3208 .Case("ignore", LangOptions::FPE_Ignore)
3209 .Case("maytrap", LangOptions::FPE_MayTrap)
3210 .Case("strict", LangOptions::FPE_Strict)
3211 .Default(llvm::None);
3212 if (!AnnotValue->ExceptionsValue) {
3213 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3214 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3215 return;
3216 }
3217 } else if (FlagKind == TokFPAnnotValue::EvalMethod) {
3218 AnnotValue->EvalMethodValue =
3219 llvm::StringSwitch<llvm::Optional<LangOptions::FPEvalMethodKind>>(
3220 II->getName())
3221 .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
3222 .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
3223 .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
3224 .Default(llvm::None);
3225 if (!AnnotValue->EvalMethodValue) {
3226 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3227 << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3228 return;
3229 }
3230 }
3231 PP.Lex(Tok);
3232
3233 // Read ')'
3234 if (Tok.isNot(tok::r_paren)) {
3235 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3236 return;
3237 }
3238 PP.Lex(Tok);
3239 }
3240
3241 if (Tok.isNot(tok::eod)) {
3242 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3243 << "clang fp";
3244 return;
3245 }
3246
3247 Token FPTok;
3248 FPTok.startToken();
3249 FPTok.setKind(tok::annot_pragma_fp);
3250 FPTok.setLocation(PragmaName.getLocation());
3251 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3252 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3253 TokenList.push_back(FPTok);
3254
3255 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3256 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3257
3258 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3259 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3260 }
3261
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3262 void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3263 PragmaIntroducer Introducer,
3264 Token &Tok) {
3265 Token PragmaName = Tok;
3266 SmallVector<Token, 1> TokenList;
3267 if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3268 PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3269 << PragmaName.getIdentifierInfo()->getName();
3270 return;
3271 }
3272
3273 PP.Lex(Tok);
3274 if (Tok.isNot(tok::identifier)) {
3275 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3276 << PragmaName.getIdentifierInfo()->getName();
3277 return;
3278 }
3279 IdentifierInfo *II = Tok.getIdentifierInfo();
3280
3281 auto RM =
3282 llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3283 .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3284 .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3285 .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3286 .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3287 .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3288 .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3289 .Default(llvm::RoundingMode::Invalid);
3290 if (RM == llvm::RoundingMode::Invalid) {
3291 PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3292 return;
3293 }
3294 PP.Lex(Tok);
3295
3296 if (Tok.isNot(tok::eod)) {
3297 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3298 << "STDC FENV_ROUND";
3299 return;
3300 }
3301
3302 // Until the pragma is fully implemented, issue a warning.
3303 PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3304
3305 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
3306 1);
3307 Toks[0].startToken();
3308 Toks[0].setKind(tok::annot_pragma_fenv_round);
3309 Toks[0].setLocation(Tok.getLocation());
3310 Toks[0].setAnnotationEndLoc(Tok.getLocation());
3311 Toks[0].setAnnotationValue(
3312 reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3313 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3314 /*IsReinject=*/false);
3315 }
3316
HandlePragmaFP()3317 void Parser::HandlePragmaFP() {
3318 assert(Tok.is(tok::annot_pragma_fp));
3319 auto *AnnotValue =
3320 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3321
3322 if (AnnotValue->ReassociateValue)
3323 Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
3324 *AnnotValue->ReassociateValue ==
3325 LangOptions::FPModeKind::FPM_On);
3326 if (AnnotValue->ContractValue)
3327 Actions.ActOnPragmaFPContract(Tok.getLocation(),
3328 *AnnotValue->ContractValue);
3329 if (AnnotValue->ExceptionsValue)
3330 Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3331 *AnnotValue->ExceptionsValue);
3332 if (AnnotValue->EvalMethodValue)
3333 Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
3334 *AnnotValue->EvalMethodValue);
3335 ConsumeAnnotationToken();
3336 }
3337
3338 /// Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)3339 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3340 Token Option, bool ValueInParens,
3341 PragmaLoopHintInfo &Info) {
3342 SmallVector<Token, 1> ValueList;
3343 int OpenParens = ValueInParens ? 1 : 0;
3344 // Read constant expression.
3345 while (Tok.isNot(tok::eod)) {
3346 if (Tok.is(tok::l_paren))
3347 OpenParens++;
3348 else if (Tok.is(tok::r_paren)) {
3349 OpenParens--;
3350 if (OpenParens == 0 && ValueInParens)
3351 break;
3352 }
3353
3354 ValueList.push_back(Tok);
3355 PP.Lex(Tok);
3356 }
3357
3358 if (ValueInParens) {
3359 // Read ')'
3360 if (Tok.isNot(tok::r_paren)) {
3361 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3362 return true;
3363 }
3364 PP.Lex(Tok);
3365 }
3366
3367 Token EOFTok;
3368 EOFTok.startToken();
3369 EOFTok.setKind(tok::eof);
3370 EOFTok.setLocation(Tok.getLocation());
3371 ValueList.push_back(EOFTok); // Terminates expression for parsing.
3372
3373 markAsReinjectedForRelexing(ValueList);
3374 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
3375
3376 Info.PragmaName = PragmaName;
3377 Info.Option = Option;
3378 return false;
3379 }
3380
3381 /// Handle the \#pragma clang loop directive.
3382 /// #pragma clang 'loop' loop-hints
3383 ///
3384 /// loop-hints:
3385 /// loop-hint loop-hints[opt]
3386 ///
3387 /// loop-hint:
3388 /// 'vectorize' '(' loop-hint-keyword ')'
3389 /// 'interleave' '(' loop-hint-keyword ')'
3390 /// 'unroll' '(' unroll-hint-keyword ')'
3391 /// 'vectorize_predicate' '(' loop-hint-keyword ')'
3392 /// 'vectorize_width' '(' loop-hint-value ')'
3393 /// 'interleave_count' '(' loop-hint-value ')'
3394 /// 'unroll_count' '(' loop-hint-value ')'
3395 /// 'pipeline' '(' disable ')'
3396 /// 'pipeline_initiation_interval' '(' loop-hint-value ')'
3397 ///
3398 /// loop-hint-keyword:
3399 /// 'enable'
3400 /// 'disable'
3401 /// 'assume_safety'
3402 ///
3403 /// unroll-hint-keyword:
3404 /// 'enable'
3405 /// 'disable'
3406 /// 'full'
3407 ///
3408 /// loop-hint-value:
3409 /// constant-expression
3410 ///
3411 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3412 /// try vectorizing the instructions of the loop it precedes. Specifying
3413 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
3414 /// interleaving multiple iterations of the loop it precedes. The width of the
3415 /// vector instructions is specified by vectorize_width() and the number of
3416 /// interleaved loop iterations is specified by interleave_count(). Specifying a
3417 /// value of 1 effectively disables vectorization/interleaving, even if it is
3418 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
3419 /// only works on inner loops.
3420 ///
3421 /// The unroll and unroll_count directives control the concatenation
3422 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3423 /// completely if the trip count is known at compile time and unroll partially
3424 /// if the trip count is not known. Specifying unroll(full) is similar to
3425 /// unroll(enable) but will unroll the loop only if the trip count is known at
3426 /// compile time. Specifying unroll(disable) disables unrolling for the
3427 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3428 /// loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3429 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3430 PragmaIntroducer Introducer,
3431 Token &Tok) {
3432 // Incoming token is "loop" from "#pragma clang loop".
3433 Token PragmaName = Tok;
3434 SmallVector<Token, 1> TokenList;
3435
3436 // Lex the optimization option and verify it is an identifier.
3437 PP.Lex(Tok);
3438 if (Tok.isNot(tok::identifier)) {
3439 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3440 << /*MissingOption=*/true << "";
3441 return;
3442 }
3443
3444 while (Tok.is(tok::identifier)) {
3445 Token Option = Tok;
3446 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3447
3448 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3449 .Case("vectorize", true)
3450 .Case("interleave", true)
3451 .Case("unroll", true)
3452 .Case("distribute", true)
3453 .Case("vectorize_predicate", true)
3454 .Case("vectorize_width", true)
3455 .Case("interleave_count", true)
3456 .Case("unroll_count", true)
3457 .Case("pipeline", true)
3458 .Case("pipeline_initiation_interval", true)
3459 .Default(false);
3460 if (!OptionValid) {
3461 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3462 << /*MissingOption=*/false << OptionInfo;
3463 return;
3464 }
3465 PP.Lex(Tok);
3466
3467 // Read '('
3468 if (Tok.isNot(tok::l_paren)) {
3469 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3470 return;
3471 }
3472 PP.Lex(Tok);
3473
3474 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3475 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3476 *Info))
3477 return;
3478
3479 // Generate the loop hint token.
3480 Token LoopHintTok;
3481 LoopHintTok.startToken();
3482 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
3483 LoopHintTok.setLocation(Introducer.Loc);
3484 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
3485 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3486 TokenList.push_back(LoopHintTok);
3487 }
3488
3489 if (Tok.isNot(tok::eod)) {
3490 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3491 << "clang loop";
3492 return;
3493 }
3494
3495 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3496 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3497
3498 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3499 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3500 }
3501
3502 /// Handle the loop unroll optimization pragmas.
3503 /// #pragma unroll
3504 /// #pragma unroll unroll-hint-value
3505 /// #pragma unroll '(' unroll-hint-value ')'
3506 /// #pragma nounroll
3507 /// #pragma unroll_and_jam
3508 /// #pragma unroll_and_jam unroll-hint-value
3509 /// #pragma unroll_and_jam '(' unroll-hint-value ')'
3510 /// #pragma nounroll_and_jam
3511 ///
3512 /// unroll-hint-value:
3513 /// constant-expression
3514 ///
3515 /// Loop unrolling hints can be specified with '#pragma unroll' or
3516 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3517 /// contained in parentheses. With no argument the directive instructs llvm to
3518 /// try to unroll the loop completely. A positive integer argument can be
3519 /// specified to indicate the number of times the loop should be unrolled. To
3520 /// maximize compatibility with other compilers the unroll count argument can be
3521 /// specified with or without parentheses. Specifying, '#pragma nounroll'
3522 /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3523 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3524 PragmaIntroducer Introducer,
3525 Token &Tok) {
3526 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3527 // "#pragma nounroll".
3528 Token PragmaName = Tok;
3529 PP.Lex(Tok);
3530 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3531 if (Tok.is(tok::eod)) {
3532 // nounroll or unroll pragma without an argument.
3533 Info->PragmaName = PragmaName;
3534 Info->Option.startToken();
3535 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3536 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3537 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3538 << PragmaName.getIdentifierInfo()->getName();
3539 return;
3540 } else {
3541 // Unroll pragma with an argument: "#pragma unroll N" or
3542 // "#pragma unroll(N)".
3543 // Read '(' if it exists.
3544 bool ValueInParens = Tok.is(tok::l_paren);
3545 if (ValueInParens)
3546 PP.Lex(Tok);
3547
3548 Token Option;
3549 Option.startToken();
3550 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3551 return;
3552
3553 // In CUDA, the argument to '#pragma unroll' should not be contained in
3554 // parentheses.
3555 if (PP.getLangOpts().CUDA && ValueInParens)
3556 PP.Diag(Info->Toks[0].getLocation(),
3557 diag::warn_pragma_unroll_cuda_value_in_parens);
3558
3559 if (Tok.isNot(tok::eod)) {
3560 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3561 << "unroll";
3562 return;
3563 }
3564 }
3565
3566 // Generate the hint token.
3567 auto TokenArray = std::make_unique<Token[]>(1);
3568 TokenArray[0].startToken();
3569 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3570 TokenArray[0].setLocation(Introducer.Loc);
3571 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3572 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3573 PP.EnterTokenStream(std::move(TokenArray), 1,
3574 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3575 }
3576
3577 /// Handle the Microsoft \#pragma intrinsic extension.
3578 ///
3579 /// The syntax is:
3580 /// \code
3581 /// #pragma intrinsic(memset)
3582 /// #pragma intrinsic(strlen, memcpy)
3583 /// \endcode
3584 ///
3585 /// Pragma intrisic tells the compiler to use a builtin version of the
3586 /// function. Clang does it anyway, so the pragma doesn't really do anything.
3587 /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3588 /// isn't an intrinsic in clang and suggest to include intrin.h.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3589 void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3590 PragmaIntroducer Introducer,
3591 Token &Tok) {
3592 PP.Lex(Tok);
3593
3594 if (Tok.isNot(tok::l_paren)) {
3595 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3596 << "intrinsic";
3597 return;
3598 }
3599 PP.Lex(Tok);
3600
3601 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3602
3603 while (Tok.is(tok::identifier)) {
3604 IdentifierInfo *II = Tok.getIdentifierInfo();
3605 if (!II->getBuiltinID())
3606 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3607 << II << SuggestIntrinH;
3608
3609 PP.Lex(Tok);
3610 if (Tok.isNot(tok::comma))
3611 break;
3612 PP.Lex(Tok);
3613 }
3614
3615 if (Tok.isNot(tok::r_paren)) {
3616 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3617 << "intrinsic";
3618 return;
3619 }
3620 PP.Lex(Tok);
3621
3622 if (Tok.isNot(tok::eod))
3623 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3624 << "intrinsic";
3625 }
3626
HandlePragmaMSFunction(StringRef PragmaName,SourceLocation PragmaLocation)3627 bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
3628 SourceLocation PragmaLocation) {
3629 Token FirstTok = Tok;
3630
3631 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3632 PragmaName))
3633 return false;
3634
3635 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3636
3637 llvm::SmallVector<StringRef> NoBuiltins;
3638 while (Tok.is(tok::identifier)) {
3639 IdentifierInfo *II = Tok.getIdentifierInfo();
3640 if (!II->getBuiltinID())
3641 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3642 << II << SuggestIntrinH;
3643 else
3644 NoBuiltins.emplace_back(II->getName());
3645
3646 PP.Lex(Tok);
3647 if (Tok.isNot(tok::comma))
3648 break;
3649 PP.Lex(Tok); // ,
3650 }
3651
3652 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3653 PragmaName) ||
3654 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3655 PragmaName))
3656 return false;
3657
3658 Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
3659 return true;
3660 }
3661
3662 // #pragma optimize("gsty", on|off)
HandlePragmaMSOptimize(StringRef PragmaName,SourceLocation PragmaLocation)3663 bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
3664 SourceLocation PragmaLocation) {
3665 Token FirstTok = Tok;
3666 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3667 PragmaName))
3668 return false;
3669
3670 if (Tok.isNot(tok::string_literal)) {
3671 PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
3672 return false;
3673 }
3674 ExprResult StringResult = ParseStringLiteralExpression();
3675 if (StringResult.isInvalid())
3676 return false; // Already diagnosed.
3677 StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
3678 if (OptimizationList->getCharByteWidth() != 1) {
3679 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
3680 << PragmaName;
3681 return false;
3682 }
3683
3684 if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
3685 PragmaName))
3686 return false;
3687
3688 if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
3689 PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
3690 << PragmaName << /*Expected=*/true << "'on' or 'off'";
3691 return false;
3692 }
3693 IdentifierInfo *II = Tok.getIdentifierInfo();
3694 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3695 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3696 << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
3697 << "'on' or 'off'";
3698 return false;
3699 }
3700 bool IsOn = II->isStr("on");
3701 PP.Lex(Tok);
3702
3703 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3704 PragmaName))
3705 return false;
3706
3707 // TODO: Add support for "sgty"
3708 if (!OptimizationList->getString().empty()) {
3709 PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3710 << OptimizationList->getString() << PragmaName << /*Expected=*/true
3711 << "\"\"";
3712 return false;
3713 }
3714
3715 if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3716 PragmaName))
3717 return false;
3718
3719 Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
3720 return true;
3721 }
3722
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3723 void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3724 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3725 Token FirstTok = Tok;
3726
3727 PP.Lex(Tok);
3728 IdentifierInfo *Info = Tok.getIdentifierInfo();
3729 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3730 PP.Diag(FirstTok.getLocation(),
3731 diag::warn_pragma_force_cuda_host_device_bad_arg);
3732 return;
3733 }
3734
3735 if (Info->isStr("begin"))
3736 Actions.PushForceCUDAHostDevice();
3737 else if (!Actions.PopForceCUDAHostDevice())
3738 PP.Diag(FirstTok.getLocation(),
3739 diag::err_pragma_cannot_end_force_cuda_host_device);
3740
3741 PP.Lex(Tok);
3742 if (!Tok.is(tok::eod))
3743 PP.Diag(FirstTok.getLocation(),
3744 diag::warn_pragma_force_cuda_host_device_bad_arg);
3745 }
3746
3747 /// Handle the #pragma clang attribute directive.
3748 ///
3749 /// The syntax is:
3750 /// \code
3751 /// #pragma clang attribute push (attribute, subject-set)
3752 /// #pragma clang attribute push
3753 /// #pragma clang attribute (attribute, subject-set)
3754 /// #pragma clang attribute pop
3755 /// \endcode
3756 ///
3757 /// There are also 'namespace' variants of push and pop directives. The bare
3758 /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3759 /// namespace, since it always applies attributes to the most recently pushed
3760 /// group, regardless of namespace.
3761 /// \code
3762 /// #pragma clang attribute namespace.push (attribute, subject-set)
3763 /// #pragma clang attribute namespace.push
3764 /// #pragma clang attribute namespace.pop
3765 /// \endcode
3766 ///
3767 /// The subject-set clause defines the set of declarations which receive the
3768 /// attribute. Its exact syntax is described in the LanguageExtensions document
3769 /// in Clang's documentation.
3770 ///
3771 /// This directive instructs the compiler to begin/finish applying the specified
3772 /// attribute to the set of attribute-specific declarations in the active range
3773 /// of the pragma.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3774 void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3775 PragmaIntroducer Introducer,
3776 Token &FirstToken) {
3777 Token Tok;
3778 PP.Lex(Tok);
3779 auto *Info = new (PP.getPreprocessorAllocator())
3780 PragmaAttributeInfo(AttributesForPragmaAttribute);
3781
3782 // Parse the optional namespace followed by a period.
3783 if (Tok.is(tok::identifier)) {
3784 IdentifierInfo *II = Tok.getIdentifierInfo();
3785 if (!II->isStr("push") && !II->isStr("pop")) {
3786 Info->Namespace = II;
3787 PP.Lex(Tok);
3788
3789 if (!Tok.is(tok::period)) {
3790 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3791 << II;
3792 return;
3793 }
3794 PP.Lex(Tok);
3795 }
3796 }
3797
3798 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3799 PP.Diag(Tok.getLocation(),
3800 diag::err_pragma_attribute_expected_push_pop_paren);
3801 return;
3802 }
3803
3804 // Determine what action this pragma clang attribute represents.
3805 if (Tok.is(tok::l_paren)) {
3806 if (Info->Namespace) {
3807 PP.Diag(Tok.getLocation(),
3808 diag::err_pragma_attribute_namespace_on_attribute);
3809 PP.Diag(Tok.getLocation(),
3810 diag::note_pragma_attribute_namespace_on_attribute);
3811 return;
3812 }
3813 Info->Action = PragmaAttributeInfo::Attribute;
3814 } else {
3815 const IdentifierInfo *II = Tok.getIdentifierInfo();
3816 if (II->isStr("push"))
3817 Info->Action = PragmaAttributeInfo::Push;
3818 else if (II->isStr("pop"))
3819 Info->Action = PragmaAttributeInfo::Pop;
3820 else {
3821 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3822 << PP.getSpelling(Tok);
3823 return;
3824 }
3825
3826 PP.Lex(Tok);
3827 }
3828
3829 // Parse the actual attribute.
3830 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3831 Info->Action == PragmaAttributeInfo::Attribute) {
3832 if (Tok.isNot(tok::l_paren)) {
3833 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3834 return;
3835 }
3836 PP.Lex(Tok);
3837
3838 // Lex the attribute tokens.
3839 SmallVector<Token, 16> AttributeTokens;
3840 int OpenParens = 1;
3841 while (Tok.isNot(tok::eod)) {
3842 if (Tok.is(tok::l_paren))
3843 OpenParens++;
3844 else if (Tok.is(tok::r_paren)) {
3845 OpenParens--;
3846 if (OpenParens == 0)
3847 break;
3848 }
3849
3850 AttributeTokens.push_back(Tok);
3851 PP.Lex(Tok);
3852 }
3853
3854 if (AttributeTokens.empty()) {
3855 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3856 return;
3857 }
3858 if (Tok.isNot(tok::r_paren)) {
3859 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3860 return;
3861 }
3862 SourceLocation EndLoc = Tok.getLocation();
3863 PP.Lex(Tok);
3864
3865 // Terminate the attribute for parsing.
3866 Token EOFTok;
3867 EOFTok.startToken();
3868 EOFTok.setKind(tok::eof);
3869 EOFTok.setLocation(EndLoc);
3870 AttributeTokens.push_back(EOFTok);
3871
3872 markAsReinjectedForRelexing(AttributeTokens);
3873 Info->Tokens =
3874 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3875 }
3876
3877 if (Tok.isNot(tok::eod))
3878 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3879 << "clang attribute";
3880
3881 // Generate the annotated pragma token.
3882 auto TokenArray = std::make_unique<Token[]>(1);
3883 TokenArray[0].startToken();
3884 TokenArray[0].setKind(tok::annot_pragma_attribute);
3885 TokenArray[0].setLocation(FirstToken.getLocation());
3886 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3887 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3888 PP.EnterTokenStream(std::move(TokenArray), 1,
3889 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3890 }
3891
3892 // Handle '#pragma clang max_tokens 12345'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3893 void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
3894 PragmaIntroducer Introducer,
3895 Token &Tok) {
3896 PP.Lex(Tok);
3897 if (Tok.is(tok::eod)) {
3898 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3899 << "clang max_tokens_here" << /*Expected=*/true << "integer";
3900 return;
3901 }
3902
3903 SourceLocation Loc = Tok.getLocation();
3904 uint64_t MaxTokens;
3905 if (Tok.isNot(tok::numeric_constant) ||
3906 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3907 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3908 << "clang max_tokens_here";
3909 return;
3910 }
3911
3912 if (Tok.isNot(tok::eod)) {
3913 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3914 << "clang max_tokens_here";
3915 return;
3916 }
3917
3918 if (PP.getTokenCount() > MaxTokens) {
3919 PP.Diag(Loc, diag::warn_max_tokens)
3920 << PP.getTokenCount() << (unsigned)MaxTokens;
3921 }
3922 }
3923
3924 // Handle '#pragma clang max_tokens_total 12345'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3925 void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
3926 PragmaIntroducer Introducer,
3927 Token &Tok) {
3928 PP.Lex(Tok);
3929 if (Tok.is(tok::eod)) {
3930 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3931 << "clang max_tokens_total" << /*Expected=*/true << "integer";
3932 return;
3933 }
3934
3935 SourceLocation Loc = Tok.getLocation();
3936 uint64_t MaxTokens;
3937 if (Tok.isNot(tok::numeric_constant) ||
3938 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3939 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3940 << "clang max_tokens_total";
3941 return;
3942 }
3943
3944 if (Tok.isNot(tok::eod)) {
3945 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3946 << "clang max_tokens_total";
3947 return;
3948 }
3949
3950 PP.overrideMaxTokens(MaxTokens, Loc);
3951 }
3952
3953 // Handle '#pragma clang riscv intrinsic vector'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3954 void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
3955 PragmaIntroducer Introducer,
3956 Token &FirstToken) {
3957 Token Tok;
3958 PP.Lex(Tok);
3959 IdentifierInfo *II = Tok.getIdentifierInfo();
3960
3961 if (!II || !II->isStr("intrinsic")) {
3962 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3963 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
3964 return;
3965 }
3966
3967 PP.Lex(Tok);
3968 II = Tok.getIdentifierInfo();
3969 if (!II || !II->isStr("vector")) {
3970 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3971 << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'vector'";
3972 return;
3973 }
3974
3975 PP.Lex(Tok);
3976 if (Tok.isNot(tok::eod)) {
3977 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3978 << "clang riscv intrinsic";
3979 return;
3980 }
3981
3982 Actions.DeclareRISCVVBuiltins = true;
3983 }
3984