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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Parse/ParsePragma.cpp