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

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