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/Parse/LoopHint.h"
18 #include "clang/Parse/ParseDiagnostic.h"
19 #include "clang/Parse/Parser.h"
20 #include "clang/Parse/RAIIObjectsForParser.h"
21 #include "clang/Sema/Scope.h"
22 #include "llvm/ADT/StringSwitch.h"
23 using namespace clang;
24
25 namespace {
26
27 struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon9522386e0111::PragmaAlignHandler28 explicit PragmaAlignHandler() : PragmaHandler("align") {}
29 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
30 Token &FirstToken) override;
31 };
32
33 struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon9522386e0111::PragmaGCCVisibilityHandler34 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
35 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
36 Token &FirstToken) override;
37 };
38
39 struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon9522386e0111::PragmaOptionsHandler40 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
41 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
42 Token &FirstToken) override;
43 };
44
45 struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon9522386e0111::PragmaPackHandler46 explicit PragmaPackHandler() : PragmaHandler("pack") {}
47 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
48 Token &FirstToken) override;
49 };
50
51 struct PragmaClangSectionHandler : public PragmaHandler {
PragmaClangSectionHandler__anon9522386e0111::PragmaClangSectionHandler52 explicit PragmaClangSectionHandler(Sema &S)
53 : PragmaHandler("section"), Actions(S) {}
54 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
55 Token &FirstToken) override;
56
57 private:
58 Sema &Actions;
59 };
60
61 struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon9522386e0111::PragmaMSStructHandler62 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
63 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
64 Token &FirstToken) override;
65 };
66
67 struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon9522386e0111::PragmaUnusedHandler68 PragmaUnusedHandler() : PragmaHandler("unused") {}
69 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
70 Token &FirstToken) override;
71 };
72
73 struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon9522386e0111::PragmaWeakHandler74 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
75 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
76 Token &FirstToken) override;
77 };
78
79 struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon9522386e0111::PragmaRedefineExtnameHandler80 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
81 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
82 Token &FirstToken) override;
83 };
84
85 struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon9522386e0111::PragmaOpenCLExtensionHandler86 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
87 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
88 Token &FirstToken) override;
89 };
90
91
92 struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon9522386e0111::PragmaFPContractHandler93 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
94 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
95 Token &FirstToken) override;
96 };
97
98 // Pragma STDC implementations.
99
100 /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
101 struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
PragmaSTDC_FENV_ACCESSHandler__anon9522386e0111::PragmaSTDC_FENV_ACCESSHandler102 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
103
HandlePragma__anon9522386e0111::PragmaSTDC_FENV_ACCESSHandler104 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
105 Token &Tok) override {
106 tok::OnOffSwitch OOS;
107 if (PP.LexOnOffSwitch(OOS))
108 return;
109 if (OOS == tok::OOS_ON) {
110 PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
111 }
112
113 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
114 1);
115 Toks[0].startToken();
116 Toks[0].setKind(tok::annot_pragma_fenv_access);
117 Toks[0].setLocation(Tok.getLocation());
118 Toks[0].setAnnotationEndLoc(Tok.getLocation());
119 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
120 static_cast<uintptr_t>(OOS)));
121 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
122 /*IsReinject=*/false);
123 }
124 };
125
126 /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
127 struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
PragmaSTDC_CX_LIMITED_RANGEHandler__anon9522386e0111::PragmaSTDC_CX_LIMITED_RANGEHandler128 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
129
HandlePragma__anon9522386e0111::PragmaSTDC_CX_LIMITED_RANGEHandler130 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
131 Token &Tok) override {
132 tok::OnOffSwitch OOS;
133 PP.LexOnOffSwitch(OOS);
134 }
135 };
136
137 /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
138 struct PragmaSTDC_UnknownHandler : public PragmaHandler {
139 PragmaSTDC_UnknownHandler() = default;
140
HandlePragma__anon9522386e0111::PragmaSTDC_UnknownHandler141 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
142 Token &UnknownTok) override {
143 // C99 6.10.6p2, unknown forms are not allowed.
144 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
145 }
146 };
147
148 struct PragmaFPHandler : public PragmaHandler {
PragmaFPHandler__anon9522386e0111::PragmaFPHandler149 PragmaFPHandler() : PragmaHandler("fp") {}
150 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
151 Token &FirstToken) override;
152 };
153
154 struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon9522386e0111::PragmaNoOpenMPHandler155 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
156 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
157 Token &FirstToken) override;
158 };
159
160 struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon9522386e0111::PragmaOpenMPHandler161 PragmaOpenMPHandler() : PragmaHandler("omp") { }
162 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
163 Token &FirstToken) override;
164 };
165
166 /// PragmaCommentHandler - "\#pragma comment ...".
167 struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon9522386e0111::PragmaCommentHandler168 PragmaCommentHandler(Sema &Actions)
169 : PragmaHandler("comment"), Actions(Actions) {}
170 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
171 Token &FirstToken) override;
172
173 private:
174 Sema &Actions;
175 };
176
177 struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon9522386e0111::PragmaDetectMismatchHandler178 PragmaDetectMismatchHandler(Sema &Actions)
179 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
180 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
181 Token &FirstToken) override;
182
183 private:
184 Sema &Actions;
185 };
186
187 struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon9522386e0111::PragmaMSPointersToMembers188 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
189 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
190 Token &FirstToken) override;
191 };
192
193 struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon9522386e0111::PragmaMSVtorDisp194 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
195 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
196 Token &FirstToken) override;
197 };
198
199 struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon9522386e0111::PragmaMSPragma200 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
201 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
202 Token &FirstToken) override;
203 };
204
205 /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
206 struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon9522386e0111::PragmaOptimizeHandler207 PragmaOptimizeHandler(Sema &S)
208 : PragmaHandler("optimize"), Actions(S) {}
209 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
210 Token &FirstToken) override;
211
212 private:
213 Sema &Actions;
214 };
215
216 struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon9522386e0111::PragmaLoopHintHandler217 PragmaLoopHintHandler() : PragmaHandler("loop") {}
218 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
219 Token &FirstToken) override;
220 };
221
222 struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon9522386e0111::PragmaUnrollHintHandler223 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
224 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
225 Token &FirstToken) override;
226 };
227
228 struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler__anon9522386e0111::PragmaMSRuntimeChecksHandler229 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
230 };
231
232 struct PragmaMSIntrinsicHandler : public PragmaHandler {
PragmaMSIntrinsicHandler__anon9522386e0111::PragmaMSIntrinsicHandler233 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
234 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
235 Token &FirstToken) override;
236 };
237
238 struct PragmaMSOptimizeHandler : public PragmaHandler {
PragmaMSOptimizeHandler__anon9522386e0111::PragmaMSOptimizeHandler239 PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
240 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
241 Token &FirstToken) override;
242 };
243
244 struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler__anon9522386e0111::PragmaForceCUDAHostDeviceHandler245 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
246 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
247 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
248 Token &FirstToken) override;
249
250 private:
251 Sema &Actions;
252 };
253
254 /// PragmaAttributeHandler - "\#pragma clang attribute ...".
255 struct PragmaAttributeHandler : public PragmaHandler {
PragmaAttributeHandler__anon9522386e0111::PragmaAttributeHandler256 PragmaAttributeHandler(AttributeFactory &AttrFactory)
257 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
258 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
259 Token &FirstToken) override;
260
261 /// A pool of attributes that were parsed in \#pragma clang attribute.
262 ParsedAttributes AttributesForPragmaAttribute;
263 };
264
265 } // end namespace
266
initializePragmaHandlers()267 void Parser::initializePragmaHandlers() {
268 AlignHandler = std::make_unique<PragmaAlignHandler>();
269 PP.AddPragmaHandler(AlignHandler.get());
270
271 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
272 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
273
274 OptionsHandler = std::make_unique<PragmaOptionsHandler>();
275 PP.AddPragmaHandler(OptionsHandler.get());
276
277 PackHandler = std::make_unique<PragmaPackHandler>();
278 PP.AddPragmaHandler(PackHandler.get());
279
280 MSStructHandler = std::make_unique<PragmaMSStructHandler>();
281 PP.AddPragmaHandler(MSStructHandler.get());
282
283 UnusedHandler = std::make_unique<PragmaUnusedHandler>();
284 PP.AddPragmaHandler(UnusedHandler.get());
285
286 WeakHandler = std::make_unique<PragmaWeakHandler>();
287 PP.AddPragmaHandler(WeakHandler.get());
288
289 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
290 PP.AddPragmaHandler(RedefineExtnameHandler.get());
291
292 FPContractHandler = std::make_unique<PragmaFPContractHandler>();
293 PP.AddPragmaHandler("STDC", FPContractHandler.get());
294
295 STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
296 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
297
298 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
299 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
300
301 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
302 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
303
304 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
305 PP.AddPragmaHandler("clang", PCSectionHandler.get());
306
307 if (getLangOpts().OpenCL) {
308 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
309 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
310
311 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
312 }
313 if (getLangOpts().OpenMP)
314 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
315 else
316 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
317 PP.AddPragmaHandler(OpenMPHandler.get());
318
319 if (getLangOpts().MicrosoftExt ||
320 getTargetInfo().getTriple().isOSBinFormatELF()) {
321 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
322 PP.AddPragmaHandler(MSCommentHandler.get());
323 }
324
325 if (getLangOpts().MicrosoftExt) {
326 MSDetectMismatchHandler =
327 std::make_unique<PragmaDetectMismatchHandler>(Actions);
328 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
329 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
330 PP.AddPragmaHandler(MSPointersToMembers.get());
331 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
332 PP.AddPragmaHandler(MSVtorDisp.get());
333 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
334 PP.AddPragmaHandler(MSInitSeg.get());
335 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
336 PP.AddPragmaHandler(MSDataSeg.get());
337 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
338 PP.AddPragmaHandler(MSBSSSeg.get());
339 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
340 PP.AddPragmaHandler(MSConstSeg.get());
341 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
342 PP.AddPragmaHandler(MSCodeSeg.get());
343 MSSection = std::make_unique<PragmaMSPragma>("section");
344 PP.AddPragmaHandler(MSSection.get());
345 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
346 PP.AddPragmaHandler(MSRuntimeChecks.get());
347 MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
348 PP.AddPragmaHandler(MSIntrinsic.get());
349 MSOptimize = std::make_unique<PragmaMSOptimizeHandler>();
350 PP.AddPragmaHandler(MSOptimize.get());
351 }
352
353 if (getLangOpts().CUDA) {
354 CUDAForceHostDeviceHandler =
355 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
356 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
357 }
358
359 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
360 PP.AddPragmaHandler("clang", OptimizeHandler.get());
361
362 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
363 PP.AddPragmaHandler("clang", LoopHintHandler.get());
364
365 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
366 PP.AddPragmaHandler(UnrollHintHandler.get());
367
368 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
369 PP.AddPragmaHandler(NoUnrollHintHandler.get());
370
371 UnrollAndJamHintHandler =
372 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
373 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
374
375 NoUnrollAndJamHintHandler =
376 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
377 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
378
379 FPHandler = std::make_unique<PragmaFPHandler>();
380 PP.AddPragmaHandler("clang", FPHandler.get());
381
382 AttributePragmaHandler =
383 std::make_unique<PragmaAttributeHandler>(AttrFactory);
384 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
385 }
386
resetPragmaHandlers()387 void Parser::resetPragmaHandlers() {
388 // Remove the pragma handlers we installed.
389 PP.RemovePragmaHandler(AlignHandler.get());
390 AlignHandler.reset();
391 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
392 GCCVisibilityHandler.reset();
393 PP.RemovePragmaHandler(OptionsHandler.get());
394 OptionsHandler.reset();
395 PP.RemovePragmaHandler(PackHandler.get());
396 PackHandler.reset();
397 PP.RemovePragmaHandler(MSStructHandler.get());
398 MSStructHandler.reset();
399 PP.RemovePragmaHandler(UnusedHandler.get());
400 UnusedHandler.reset();
401 PP.RemovePragmaHandler(WeakHandler.get());
402 WeakHandler.reset();
403 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
404 RedefineExtnameHandler.reset();
405
406 if (getLangOpts().OpenCL) {
407 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
408 OpenCLExtensionHandler.reset();
409 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
410 }
411 PP.RemovePragmaHandler(OpenMPHandler.get());
412 OpenMPHandler.reset();
413
414 if (getLangOpts().MicrosoftExt ||
415 getTargetInfo().getTriple().isOSBinFormatELF()) {
416 PP.RemovePragmaHandler(MSCommentHandler.get());
417 MSCommentHandler.reset();
418 }
419
420 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
421 PCSectionHandler.reset();
422
423 if (getLangOpts().MicrosoftExt) {
424 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
425 MSDetectMismatchHandler.reset();
426 PP.RemovePragmaHandler(MSPointersToMembers.get());
427 MSPointersToMembers.reset();
428 PP.RemovePragmaHandler(MSVtorDisp.get());
429 MSVtorDisp.reset();
430 PP.RemovePragmaHandler(MSInitSeg.get());
431 MSInitSeg.reset();
432 PP.RemovePragmaHandler(MSDataSeg.get());
433 MSDataSeg.reset();
434 PP.RemovePragmaHandler(MSBSSSeg.get());
435 MSBSSSeg.reset();
436 PP.RemovePragmaHandler(MSConstSeg.get());
437 MSConstSeg.reset();
438 PP.RemovePragmaHandler(MSCodeSeg.get());
439 MSCodeSeg.reset();
440 PP.RemovePragmaHandler(MSSection.get());
441 MSSection.reset();
442 PP.RemovePragmaHandler(MSRuntimeChecks.get());
443 MSRuntimeChecks.reset();
444 PP.RemovePragmaHandler(MSIntrinsic.get());
445 MSIntrinsic.reset();
446 PP.RemovePragmaHandler(MSOptimize.get());
447 MSOptimize.reset();
448 }
449
450 if (getLangOpts().CUDA) {
451 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
452 CUDAForceHostDeviceHandler.reset();
453 }
454
455 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
456 FPContractHandler.reset();
457
458 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
459 STDCFENVHandler.reset();
460
461 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
462 STDCCXLIMITHandler.reset();
463
464 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
465 STDCUnknownHandler.reset();
466
467 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
468 OptimizeHandler.reset();
469
470 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
471 LoopHintHandler.reset();
472
473 PP.RemovePragmaHandler(UnrollHintHandler.get());
474 UnrollHintHandler.reset();
475
476 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
477 NoUnrollHintHandler.reset();
478
479 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
480 UnrollAndJamHintHandler.reset();
481
482 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
483 NoUnrollAndJamHintHandler.reset();
484
485 PP.RemovePragmaHandler("clang", FPHandler.get());
486 FPHandler.reset();
487
488 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
489 AttributePragmaHandler.reset();
490 }
491
492 /// Handle the annotation token produced for #pragma unused(...)
493 ///
494 /// Each annot_pragma_unused is followed by the argument token so e.g.
495 /// "#pragma unused(x,y)" becomes:
496 /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()497 void Parser::HandlePragmaUnused() {
498 assert(Tok.is(tok::annot_pragma_unused));
499 SourceLocation UnusedLoc = ConsumeAnnotationToken();
500 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
501 ConsumeToken(); // The argument token.
502 }
503
HandlePragmaVisibility()504 void Parser::HandlePragmaVisibility() {
505 assert(Tok.is(tok::annot_pragma_vis));
506 const IdentifierInfo *VisType =
507 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
508 SourceLocation VisLoc = ConsumeAnnotationToken();
509 Actions.ActOnPragmaVisibility(VisType, VisLoc);
510 }
511
512 namespace {
513 struct PragmaPackInfo {
514 Sema::PragmaMsStackAction Action;
515 StringRef SlotLabel;
516 Token Alignment;
517 };
518 } // end anonymous namespace
519
HandlePragmaPack()520 void Parser::HandlePragmaPack() {
521 assert(Tok.is(tok::annot_pragma_pack));
522 PragmaPackInfo *Info =
523 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
524 SourceLocation PragmaLoc = Tok.getLocation();
525 ExprResult Alignment;
526 if (Info->Alignment.is(tok::numeric_constant)) {
527 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
528 if (Alignment.isInvalid()) {
529 ConsumeAnnotationToken();
530 return;
531 }
532 }
533 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
534 Alignment.get());
535 // Consume the token after processing the pragma to enable pragma-specific
536 // #include warnings.
537 ConsumeAnnotationToken();
538 }
539
HandlePragmaMSStruct()540 void Parser::HandlePragmaMSStruct() {
541 assert(Tok.is(tok::annot_pragma_msstruct));
542 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
543 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
544 Actions.ActOnPragmaMSStruct(Kind);
545 ConsumeAnnotationToken();
546 }
547
HandlePragmaAlign()548 void Parser::HandlePragmaAlign() {
549 assert(Tok.is(tok::annot_pragma_align));
550 Sema::PragmaOptionsAlignKind Kind =
551 static_cast<Sema::PragmaOptionsAlignKind>(
552 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
553 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
554 // Consume the token after processing the pragma to enable pragma-specific
555 // #include warnings.
556 ConsumeAnnotationToken();
557 }
558
HandlePragmaDump()559 void Parser::HandlePragmaDump() {
560 assert(Tok.is(tok::annot_pragma_dump));
561 IdentifierInfo *II =
562 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
563 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
564 ConsumeAnnotationToken();
565 }
566
HandlePragmaWeak()567 void Parser::HandlePragmaWeak() {
568 assert(Tok.is(tok::annot_pragma_weak));
569 SourceLocation PragmaLoc = ConsumeAnnotationToken();
570 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
571 Tok.getLocation());
572 ConsumeToken(); // The weak name.
573 }
574
HandlePragmaWeakAlias()575 void Parser::HandlePragmaWeakAlias() {
576 assert(Tok.is(tok::annot_pragma_weakalias));
577 SourceLocation PragmaLoc = ConsumeAnnotationToken();
578 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
579 SourceLocation WeakNameLoc = Tok.getLocation();
580 ConsumeToken();
581 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
582 SourceLocation AliasNameLoc = Tok.getLocation();
583 ConsumeToken();
584 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
585 WeakNameLoc, AliasNameLoc);
586
587 }
588
HandlePragmaRedefineExtname()589 void Parser::HandlePragmaRedefineExtname() {
590 assert(Tok.is(tok::annot_pragma_redefine_extname));
591 SourceLocation RedefLoc = ConsumeAnnotationToken();
592 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
593 SourceLocation RedefNameLoc = Tok.getLocation();
594 ConsumeToken();
595 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
596 SourceLocation AliasNameLoc = Tok.getLocation();
597 ConsumeToken();
598 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
599 RedefNameLoc, AliasNameLoc);
600 }
601
HandlePragmaFPContract()602 void Parser::HandlePragmaFPContract() {
603 assert(Tok.is(tok::annot_pragma_fp_contract));
604 tok::OnOffSwitch OOS =
605 static_cast<tok::OnOffSwitch>(
606 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
607
608 LangOptions::FPContractModeKind FPC;
609 switch (OOS) {
610 case tok::OOS_ON:
611 FPC = LangOptions::FPC_On;
612 break;
613 case tok::OOS_OFF:
614 FPC = LangOptions::FPC_Off;
615 break;
616 case tok::OOS_DEFAULT:
617 FPC = getLangOpts().getDefaultFPContractMode();
618 break;
619 }
620
621 Actions.ActOnPragmaFPContract(FPC);
622 ConsumeAnnotationToken();
623 }
624
HandlePragmaFEnvAccess()625 void Parser::HandlePragmaFEnvAccess() {
626 assert(Tok.is(tok::annot_pragma_fenv_access));
627 tok::OnOffSwitch OOS =
628 static_cast<tok::OnOffSwitch>(
629 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
630
631 LangOptions::FEnvAccessModeKind FPC;
632 switch (OOS) {
633 case tok::OOS_ON:
634 FPC = LangOptions::FEA_On;
635 break;
636 case tok::OOS_OFF:
637 FPC = LangOptions::FEA_Off;
638 break;
639 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
640 FPC = LangOptions::FEA_Off;
641 break;
642 }
643
644 Actions.ActOnPragmaFEnvAccess(FPC);
645 ConsumeAnnotationToken();
646 }
647
648
HandlePragmaCaptured()649 StmtResult Parser::HandlePragmaCaptured()
650 {
651 assert(Tok.is(tok::annot_pragma_captured));
652 ConsumeAnnotationToken();
653
654 if (Tok.isNot(tok::l_brace)) {
655 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
656 return StmtError();
657 }
658
659 SourceLocation Loc = Tok.getLocation();
660
661 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
662 Scope::CompoundStmtScope);
663 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
664 /*NumParams=*/1);
665
666 StmtResult R = ParseCompoundStatement();
667 CapturedRegionScope.Exit();
668
669 if (R.isInvalid()) {
670 Actions.ActOnCapturedRegionError();
671 return StmtError();
672 }
673
674 return Actions.ActOnCapturedRegionEnd(R.get());
675 }
676
677 namespace {
678 enum OpenCLExtState : char {
679 Disable, Enable, Begin, End
680 };
681 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
682 }
683
HandlePragmaOpenCLExtension()684 void Parser::HandlePragmaOpenCLExtension() {
685 assert(Tok.is(tok::annot_pragma_opencl_extension));
686 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
687 auto State = Data->second;
688 auto Ident = Data->first;
689 SourceLocation NameLoc = Tok.getLocation();
690 ConsumeAnnotationToken();
691
692 auto &Opt = Actions.getOpenCLOptions();
693 auto Name = Ident->getName();
694 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
695 // overriding all previously issued extension directives, but only if the
696 // behavior is set to disable."
697 if (Name == "all") {
698 if (State == Disable) {
699 Opt.disableAll();
700 Opt.enableSupportedCore(getLangOpts());
701 } else {
702 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
703 }
704 } else if (State == Begin) {
705 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
706 Opt.support(Name);
707 }
708 Actions.setCurrentOpenCLExtension(Name);
709 } else if (State == End) {
710 if (Name != Actions.getCurrentOpenCLExtension())
711 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
712 Actions.setCurrentOpenCLExtension("");
713 } else if (!Opt.isKnown(Name))
714 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
715 else if (Opt.isSupportedExtension(Name, getLangOpts()))
716 Opt.enable(Name, State == Enable);
717 else if (Opt.isSupportedCore(Name, getLangOpts()))
718 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
719 else
720 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
721 }
722
HandlePragmaMSPointersToMembers()723 void Parser::HandlePragmaMSPointersToMembers() {
724 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
725 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
726 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
727 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
728 SourceLocation PragmaLoc = ConsumeAnnotationToken();
729 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
730 }
731
HandlePragmaMSVtorDisp()732 void Parser::HandlePragmaMSVtorDisp() {
733 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
734 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
735 Sema::PragmaMsStackAction Action =
736 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
737 MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
738 SourceLocation PragmaLoc = ConsumeAnnotationToken();
739 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
740 }
741
HandlePragmaMSPragma()742 void Parser::HandlePragmaMSPragma() {
743 assert(Tok.is(tok::annot_pragma_ms_pragma));
744 // Grab the tokens out of the annotation and enter them into the stream.
745 auto TheTokens =
746 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
747 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
748 /*IsReinject=*/true);
749 SourceLocation PragmaLocation = ConsumeAnnotationToken();
750 assert(Tok.isAnyIdentifier());
751 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
752 PP.Lex(Tok); // pragma kind
753
754 // Figure out which #pragma we're dealing with. The switch has no default
755 // because lex shouldn't emit the annotation token for unrecognized pragmas.
756 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
757 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
758 .Case("data_seg", &Parser::HandlePragmaMSSegment)
759 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
760 .Case("const_seg", &Parser::HandlePragmaMSSegment)
761 .Case("code_seg", &Parser::HandlePragmaMSSegment)
762 .Case("section", &Parser::HandlePragmaMSSection)
763 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
764
765 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
766 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
767 // until eof (really end of line) to prevent follow-on errors.
768 while (Tok.isNot(tok::eof))
769 PP.Lex(Tok);
770 PP.Lex(Tok);
771 }
772 }
773
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)774 bool Parser::HandlePragmaMSSection(StringRef PragmaName,
775 SourceLocation PragmaLocation) {
776 if (Tok.isNot(tok::l_paren)) {
777 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
778 return false;
779 }
780 PP.Lex(Tok); // (
781 // Parsing code for pragma section
782 if (Tok.isNot(tok::string_literal)) {
783 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
784 << PragmaName;
785 return false;
786 }
787 ExprResult StringResult = ParseStringLiteralExpression();
788 if (StringResult.isInvalid())
789 return false; // Already diagnosed.
790 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
791 if (SegmentName->getCharByteWidth() != 1) {
792 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
793 << PragmaName;
794 return false;
795 }
796 int SectionFlags = ASTContext::PSF_Read;
797 bool SectionFlagsAreDefault = true;
798 while (Tok.is(tok::comma)) {
799 PP.Lex(Tok); // ,
800 // Ignore "long" and "short".
801 // They are undocumented, but widely used, section attributes which appear
802 // to do nothing.
803 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
804 PP.Lex(Tok); // long/short
805 continue;
806 }
807
808 if (!Tok.isAnyIdentifier()) {
809 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
810 << PragmaName;
811 return false;
812 }
813 ASTContext::PragmaSectionFlag Flag =
814 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
815 Tok.getIdentifierInfo()->getName())
816 .Case("read", ASTContext::PSF_Read)
817 .Case("write", ASTContext::PSF_Write)
818 .Case("execute", ASTContext::PSF_Execute)
819 .Case("shared", ASTContext::PSF_Invalid)
820 .Case("nopage", ASTContext::PSF_Invalid)
821 .Case("nocache", ASTContext::PSF_Invalid)
822 .Case("discard", ASTContext::PSF_Invalid)
823 .Case("remove", ASTContext::PSF_Invalid)
824 .Default(ASTContext::PSF_None);
825 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
826 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
827 ? diag::warn_pragma_invalid_specific_action
828 : diag::warn_pragma_unsupported_action)
829 << PragmaName << Tok.getIdentifierInfo()->getName();
830 return false;
831 }
832 SectionFlags |= Flag;
833 SectionFlagsAreDefault = false;
834 PP.Lex(Tok); // Identifier
835 }
836 // If no section attributes are specified, the section will be marked as
837 // read/write.
838 if (SectionFlagsAreDefault)
839 SectionFlags |= ASTContext::PSF_Write;
840 if (Tok.isNot(tok::r_paren)) {
841 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
842 return false;
843 }
844 PP.Lex(Tok); // )
845 if (Tok.isNot(tok::eof)) {
846 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
847 << PragmaName;
848 return false;
849 }
850 PP.Lex(Tok); // eof
851 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
852 return true;
853 }
854
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)855 bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
856 SourceLocation PragmaLocation) {
857 if (Tok.isNot(tok::l_paren)) {
858 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
859 return false;
860 }
861 PP.Lex(Tok); // (
862 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
863 StringRef SlotLabel;
864 if (Tok.isAnyIdentifier()) {
865 StringRef PushPop = Tok.getIdentifierInfo()->getName();
866 if (PushPop == "push")
867 Action = Sema::PSK_Push;
868 else if (PushPop == "pop")
869 Action = Sema::PSK_Pop;
870 else {
871 PP.Diag(PragmaLocation,
872 diag::warn_pragma_expected_section_push_pop_or_name)
873 << PragmaName;
874 return false;
875 }
876 if (Action != Sema::PSK_Reset) {
877 PP.Lex(Tok); // push | pop
878 if (Tok.is(tok::comma)) {
879 PP.Lex(Tok); // ,
880 // If we've got a comma, we either need a label or a string.
881 if (Tok.isAnyIdentifier()) {
882 SlotLabel = Tok.getIdentifierInfo()->getName();
883 PP.Lex(Tok); // identifier
884 if (Tok.is(tok::comma))
885 PP.Lex(Tok);
886 else if (Tok.isNot(tok::r_paren)) {
887 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
888 << PragmaName;
889 return false;
890 }
891 }
892 } else if (Tok.isNot(tok::r_paren)) {
893 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
894 return false;
895 }
896 }
897 }
898 // Grab the string literal for our section name.
899 StringLiteral *SegmentName = nullptr;
900 if (Tok.isNot(tok::r_paren)) {
901 if (Tok.isNot(tok::string_literal)) {
902 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
903 diag::warn_pragma_expected_section_name :
904 diag::warn_pragma_expected_section_label_or_name :
905 diag::warn_pragma_expected_section_push_pop_or_name;
906 PP.Diag(PragmaLocation, DiagID) << PragmaName;
907 return false;
908 }
909 ExprResult StringResult = ParseStringLiteralExpression();
910 if (StringResult.isInvalid())
911 return false; // Already diagnosed.
912 SegmentName = cast<StringLiteral>(StringResult.get());
913 if (SegmentName->getCharByteWidth() != 1) {
914 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
915 << PragmaName;
916 return false;
917 }
918 // Setting section "" has no effect
919 if (SegmentName->getLength())
920 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
921 }
922 if (Tok.isNot(tok::r_paren)) {
923 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
924 return false;
925 }
926 PP.Lex(Tok); // )
927 if (Tok.isNot(tok::eof)) {
928 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
929 << PragmaName;
930 return false;
931 }
932 PP.Lex(Tok); // eof
933 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
934 SegmentName, PragmaName);
935 return true;
936 }
937
938 // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)939 bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
940 SourceLocation PragmaLocation) {
941 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
942 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
943 return false;
944 }
945
946 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
947 PragmaName))
948 return false;
949
950 // Parse either the known section names or the string section name.
951 StringLiteral *SegmentName = nullptr;
952 if (Tok.isAnyIdentifier()) {
953 auto *II = Tok.getIdentifierInfo();
954 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
955 .Case("compiler", "\".CRT$XCC\"")
956 .Case("lib", "\".CRT$XCL\"")
957 .Case("user", "\".CRT$XCU\"")
958 .Default("");
959
960 if (!Section.empty()) {
961 // Pretend the user wrote the appropriate string literal here.
962 Token Toks[1];
963 Toks[0].startToken();
964 Toks[0].setKind(tok::string_literal);
965 Toks[0].setLocation(Tok.getLocation());
966 Toks[0].setLiteralData(Section.data());
967 Toks[0].setLength(Section.size());
968 SegmentName =
969 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
970 PP.Lex(Tok);
971 }
972 } else if (Tok.is(tok::string_literal)) {
973 ExprResult StringResult = ParseStringLiteralExpression();
974 if (StringResult.isInvalid())
975 return false;
976 SegmentName = cast<StringLiteral>(StringResult.get());
977 if (SegmentName->getCharByteWidth() != 1) {
978 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
979 << PragmaName;
980 return false;
981 }
982 // FIXME: Add support for the '[, func-name]' part of the pragma.
983 }
984
985 if (!SegmentName) {
986 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
987 return false;
988 }
989
990 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
991 PragmaName) ||
992 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
993 PragmaName))
994 return false;
995
996 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
997 return true;
998 }
999
1000 namespace {
1001 struct PragmaLoopHintInfo {
1002 Token PragmaName;
1003 Token Option;
1004 ArrayRef<Token> Toks;
1005 };
1006 } // end anonymous namespace
1007
PragmaLoopHintString(Token PragmaName,Token Option)1008 static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1009 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1010 std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
1011 return llvm::StringSwitch<StringRef>(Str)
1012 .Case("loop", ClangLoopStr)
1013 .Case("unroll_and_jam", Str)
1014 .Case("unroll", Str)
1015 .Default("");
1016 }
1017
HandlePragmaLoopHint(LoopHint & Hint)1018 bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1019 assert(Tok.is(tok::annot_pragma_loop_hint));
1020 PragmaLoopHintInfo *Info =
1021 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1022
1023 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1024 Hint.PragmaNameLoc = IdentifierLoc::create(
1025 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
1026
1027 // It is possible that the loop hint has no option identifier, such as
1028 // #pragma unroll(4).
1029 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1030 ? Info->Option.getIdentifierInfo()
1031 : nullptr;
1032 Hint.OptionLoc = IdentifierLoc::create(
1033 Actions.Context, Info->Option.getLocation(), OptionInfo);
1034
1035 llvm::ArrayRef<Token> Toks = Info->Toks;
1036
1037 // Return a valid hint if pragma unroll or nounroll were specified
1038 // without an argument.
1039 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1040 .Cases("unroll", "nounroll", "unroll_and_jam",
1041 "nounroll_and_jam", true)
1042 .Default(false);
1043
1044 if (Toks.empty() && IsLoopHint) {
1045 ConsumeAnnotationToken();
1046 Hint.Range = Info->PragmaName.getLocation();
1047 return true;
1048 }
1049
1050 // The constant expression is always followed by an eof token, which increases
1051 // the TokSize by 1.
1052 assert(!Toks.empty() &&
1053 "PragmaLoopHintInfo::Toks must contain at least one token.");
1054
1055 // If no option is specified the argument is assumed to be a constant expr.
1056 bool OptionUnroll = false;
1057 bool OptionUnrollAndJam = false;
1058 bool OptionDistribute = false;
1059 bool OptionPipelineDisabled = false;
1060 bool StateOption = false;
1061 if (OptionInfo) { // Pragma Unroll does not specify an option.
1062 OptionUnroll = OptionInfo->isStr("unroll");
1063 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1064 OptionDistribute = OptionInfo->isStr("distribute");
1065 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1066 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1067 .Case("vectorize", true)
1068 .Case("interleave", true)
1069 .Case("vectorize_predicate", true)
1070 .Default(false) ||
1071 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1072 OptionPipelineDisabled;
1073 }
1074
1075 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1076 !OptionDistribute && !OptionPipelineDisabled;
1077 // Verify loop hint has an argument.
1078 if (Toks[0].is(tok::eof)) {
1079 ConsumeAnnotationToken();
1080 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1081 << /*StateArgument=*/StateOption
1082 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1083 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1084 return false;
1085 }
1086
1087 // Validate the argument.
1088 if (StateOption) {
1089 ConsumeAnnotationToken();
1090 SourceLocation StateLoc = Toks[0].getLocation();
1091 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1092
1093 bool Valid = StateInfo &&
1094 llvm::StringSwitch<bool>(StateInfo->getName())
1095 .Case("disable", true)
1096 .Case("enable", !OptionPipelineDisabled)
1097 .Case("full", OptionUnroll || OptionUnrollAndJam)
1098 .Case("assume_safety", AssumeSafetyArg)
1099 .Default(false);
1100 if (!Valid) {
1101 if (OptionPipelineDisabled) {
1102 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1103 } else {
1104 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1105 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1106 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1107 }
1108 return false;
1109 }
1110 if (Toks.size() > 2)
1111 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1112 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1113 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1114 } else {
1115 // Enter constant expression including eof terminator into token stream.
1116 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1117 /*IsReinject=*/false);
1118 ConsumeAnnotationToken();
1119
1120 ExprResult R = ParseConstantExpression();
1121
1122 // Tokens following an error in an ill-formed constant expression will
1123 // remain in the token stream and must be removed.
1124 if (Tok.isNot(tok::eof)) {
1125 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1126 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1127 while (Tok.isNot(tok::eof))
1128 ConsumeAnyToken();
1129 }
1130
1131 ConsumeToken(); // Consume the constant expression eof terminator.
1132
1133 if (R.isInvalid() ||
1134 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1135 return false;
1136
1137 // Argument is a constant expression with an integer type.
1138 Hint.ValueExpr = R.get();
1139 }
1140
1141 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1142 Info->Toks.back().getLocation());
1143 return true;
1144 }
1145
1146 namespace {
1147 struct PragmaAttributeInfo {
1148 enum ActionType { Push, Pop, Attribute };
1149 ParsedAttributes &Attributes;
1150 ActionType Action;
1151 const IdentifierInfo *Namespace = nullptr;
1152 ArrayRef<Token> Tokens;
1153
PragmaAttributeInfo__anon9522386e0511::PragmaAttributeInfo1154 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1155 };
1156
1157 #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1158
1159 } // end anonymous namespace
1160
getIdentifier(const Token & Tok)1161 static StringRef getIdentifier(const Token &Tok) {
1162 if (Tok.is(tok::identifier))
1163 return Tok.getIdentifierInfo()->getName();
1164 const char *S = tok::getKeywordSpelling(Tok.getKind());
1165 if (!S)
1166 return "";
1167 return S;
1168 }
1169
isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule)1170 static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1171 using namespace attr;
1172 switch (Rule) {
1173 #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1174 case Value: \
1175 return IsAbstract;
1176 #include "clang/Basic/AttrSubMatchRulesList.inc"
1177 }
1178 llvm_unreachable("Invalid attribute subject match rule");
1179 return false;
1180 }
1181
diagnoseExpectedAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,SourceLocation SubRuleLoc)1182 static void diagnoseExpectedAttributeSubjectSubRule(
1183 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1184 SourceLocation SubRuleLoc) {
1185 auto Diagnostic =
1186 PRef.Diag(SubRuleLoc,
1187 diag::err_pragma_attribute_expected_subject_sub_identifier)
1188 << PrimaryRuleName;
1189 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1190 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1191 else
1192 Diagnostic << /*SubRulesSupported=*/0;
1193 }
1194
diagnoseUnknownAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,StringRef SubRuleName,SourceLocation SubRuleLoc)1195 static void diagnoseUnknownAttributeSubjectSubRule(
1196 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1197 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1198
1199 auto Diagnostic =
1200 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1201 << SubRuleName << PrimaryRuleName;
1202 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1203 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1204 else
1205 Diagnostic << /*SubRulesSupported=*/0;
1206 }
1207
ParsePragmaAttributeSubjectMatchRuleSet(attr::ParsedSubjectMatchRuleSet & SubjectMatchRules,SourceLocation & AnyLoc,SourceLocation & LastMatchRuleEndLoc)1208 bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1209 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1210 SourceLocation &LastMatchRuleEndLoc) {
1211 bool IsAny = false;
1212 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1213 if (getIdentifier(Tok) == "any") {
1214 AnyLoc = ConsumeToken();
1215 IsAny = true;
1216 if (AnyParens.expectAndConsume())
1217 return true;
1218 }
1219
1220 do {
1221 // Parse the subject matcher rule.
1222 StringRef Name = getIdentifier(Tok);
1223 if (Name.empty()) {
1224 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1225 return true;
1226 }
1227 std::pair<Optional<attr::SubjectMatchRule>,
1228 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1229 Rule = isAttributeSubjectMatchRule(Name);
1230 if (!Rule.first) {
1231 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1232 return true;
1233 }
1234 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1235 SourceLocation RuleLoc = ConsumeToken();
1236
1237 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1238 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1239 if (Parens.expectAndConsume())
1240 return true;
1241 } else if (Parens.consumeOpen()) {
1242 if (!SubjectMatchRules
1243 .insert(
1244 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1245 .second)
1246 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1247 << Name
1248 << FixItHint::CreateRemoval(SourceRange(
1249 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1250 LastMatchRuleEndLoc = RuleLoc;
1251 continue;
1252 }
1253
1254 // Parse the sub-rules.
1255 StringRef SubRuleName = getIdentifier(Tok);
1256 if (SubRuleName.empty()) {
1257 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1258 Tok.getLocation());
1259 return true;
1260 }
1261 attr::SubjectMatchRule SubRule;
1262 if (SubRuleName == "unless") {
1263 SourceLocation SubRuleLoc = ConsumeToken();
1264 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1265 if (Parens.expectAndConsume())
1266 return true;
1267 SubRuleName = getIdentifier(Tok);
1268 if (SubRuleName.empty()) {
1269 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1270 SubRuleLoc);
1271 return true;
1272 }
1273 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1274 if (!SubRuleOrNone) {
1275 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1276 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1277 SubRuleUnlessName, SubRuleLoc);
1278 return true;
1279 }
1280 SubRule = *SubRuleOrNone;
1281 ConsumeToken();
1282 if (Parens.consumeClose())
1283 return true;
1284 } else {
1285 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1286 if (!SubRuleOrNone) {
1287 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1288 SubRuleName, Tok.getLocation());
1289 return true;
1290 }
1291 SubRule = *SubRuleOrNone;
1292 ConsumeToken();
1293 }
1294 SourceLocation RuleEndLoc = Tok.getLocation();
1295 LastMatchRuleEndLoc = RuleEndLoc;
1296 if (Parens.consumeClose())
1297 return true;
1298 if (!SubjectMatchRules
1299 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1300 .second) {
1301 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1302 << attr::getSubjectMatchRuleSpelling(SubRule)
1303 << FixItHint::CreateRemoval(SourceRange(
1304 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1305 continue;
1306 }
1307 } while (IsAny && TryConsumeToken(tok::comma));
1308
1309 if (IsAny)
1310 if (AnyParens.consumeClose())
1311 return true;
1312
1313 return false;
1314 }
1315
1316 namespace {
1317
1318 /// Describes the stage at which attribute subject rule parsing was interrupted.
1319 enum class MissingAttributeSubjectRulesRecoveryPoint {
1320 Comma,
1321 ApplyTo,
1322 Equals,
1323 Any,
1324 None,
1325 };
1326
1327 MissingAttributeSubjectRulesRecoveryPoint
getAttributeSubjectRulesRecoveryPointForToken(const Token & Tok)1328 getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1329 if (const auto *II = Tok.getIdentifierInfo()) {
1330 if (II->isStr("apply_to"))
1331 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1332 if (II->isStr("any"))
1333 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1334 }
1335 if (Tok.is(tok::equal))
1336 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1337 return MissingAttributeSubjectRulesRecoveryPoint::None;
1338 }
1339
1340 /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1341 /// suggests the possible attribute subject rules in a fix-it together with
1342 /// any other missing tokens.
createExpectedAttributeSubjectRulesTokenDiagnostic(unsigned DiagID,ParsedAttr & Attribute,MissingAttributeSubjectRulesRecoveryPoint Point,Parser & PRef)1343 DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1344 unsigned DiagID, ParsedAttr &Attribute,
1345 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1346 SourceLocation Loc = PRef.getEndOfPreviousToken();
1347 if (Loc.isInvalid())
1348 Loc = PRef.getCurToken().getLocation();
1349 auto Diagnostic = PRef.Diag(Loc, DiagID);
1350 std::string FixIt;
1351 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1352 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1353 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1354 FixIt = ", ";
1355 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1356 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1357 FixIt += "apply_to";
1358 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1359 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1360 FixIt += " = ";
1361 SourceRange FixItRange(Loc);
1362 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1363 // Gather the subject match rules that are supported by the attribute.
1364 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1365 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1366 if (SubjectMatchRuleSet.empty()) {
1367 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1368 // placeholders will be supported by the fix-its.
1369 return Diagnostic;
1370 }
1371 FixIt += "any(";
1372 bool NeedsComma = false;
1373 for (const auto &I : SubjectMatchRuleSet) {
1374 // Ensure that the missing rule is reported in the fix-it only when it's
1375 // supported in the current language mode.
1376 if (!I.second)
1377 continue;
1378 if (NeedsComma)
1379 FixIt += ", ";
1380 else
1381 NeedsComma = true;
1382 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1383 }
1384 FixIt += ")";
1385 // Check if we need to remove the range
1386 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1387 FixItRange.setEnd(PRef.getCurToken().getLocation());
1388 }
1389 if (FixItRange.getBegin() == FixItRange.getEnd())
1390 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1391 else
1392 Diagnostic << FixItHint::CreateReplacement(
1393 CharSourceRange::getCharRange(FixItRange), FixIt);
1394 return Diagnostic;
1395 }
1396
1397 } // end anonymous namespace
1398
HandlePragmaAttribute()1399 void Parser::HandlePragmaAttribute() {
1400 assert(Tok.is(tok::annot_pragma_attribute) &&
1401 "Expected #pragma attribute annotation token");
1402 SourceLocation PragmaLoc = Tok.getLocation();
1403 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1404 if (Info->Action == PragmaAttributeInfo::Pop) {
1405 ConsumeAnnotationToken();
1406 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1407 return;
1408 }
1409 // Parse the actual attribute with its arguments.
1410 assert((Info->Action == PragmaAttributeInfo::Push ||
1411 Info->Action == PragmaAttributeInfo::Attribute) &&
1412 "Unexpected #pragma attribute command");
1413
1414 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1415 ConsumeAnnotationToken();
1416 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1417 return;
1418 }
1419
1420 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1421 /*IsReinject=*/false);
1422 ConsumeAnnotationToken();
1423
1424 ParsedAttributes &Attrs = Info->Attributes;
1425 Attrs.clearListOnly();
1426
1427 auto SkipToEnd = [this]() {
1428 SkipUntil(tok::eof, StopBeforeMatch);
1429 ConsumeToken();
1430 };
1431
1432 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1433 // Parse the CXX11 style attribute.
1434 ParseCXX11AttributeSpecifier(Attrs);
1435 } else if (Tok.is(tok::kw___attribute)) {
1436 ConsumeToken();
1437 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1438 "attribute"))
1439 return SkipToEnd();
1440 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1441 return SkipToEnd();
1442
1443 if (Tok.isNot(tok::identifier)) {
1444 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1445 SkipToEnd();
1446 return;
1447 }
1448 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1449 SourceLocation AttrNameLoc = ConsumeToken();
1450
1451 if (Tok.isNot(tok::l_paren))
1452 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1453 ParsedAttr::AS_GNU);
1454 else
1455 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1456 /*ScopeName=*/nullptr,
1457 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
1458 /*Declarator=*/nullptr);
1459
1460 if (ExpectAndConsume(tok::r_paren))
1461 return SkipToEnd();
1462 if (ExpectAndConsume(tok::r_paren))
1463 return SkipToEnd();
1464 } else if (Tok.is(tok::kw___declspec)) {
1465 ParseMicrosoftDeclSpecs(Attrs);
1466 } else {
1467 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1468 if (Tok.getIdentifierInfo()) {
1469 // If we suspect that this is an attribute suggest the use of
1470 // '__attribute__'.
1471 if (ParsedAttr::getParsedKind(
1472 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1473 ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
1474 SourceLocation InsertStartLoc = Tok.getLocation();
1475 ConsumeToken();
1476 if (Tok.is(tok::l_paren)) {
1477 ConsumeAnyToken();
1478 SkipUntil(tok::r_paren, StopBeforeMatch);
1479 if (Tok.isNot(tok::r_paren))
1480 return SkipToEnd();
1481 }
1482 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1483 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1484 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1485 }
1486 }
1487 SkipToEnd();
1488 return;
1489 }
1490
1491 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
1492 SkipToEnd();
1493 return;
1494 }
1495
1496 // Ensure that we don't have more than one attribute.
1497 if (Attrs.size() > 1) {
1498 SourceLocation Loc = Attrs[1].getLoc();
1499 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1500 SkipToEnd();
1501 return;
1502 }
1503
1504 ParsedAttr &Attribute = *Attrs.begin();
1505 if (!Attribute.isSupportedByPragmaAttribute()) {
1506 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1507 << Attribute;
1508 SkipToEnd();
1509 return;
1510 }
1511
1512 // Parse the subject-list.
1513 if (!TryConsumeToken(tok::comma)) {
1514 createExpectedAttributeSubjectRulesTokenDiagnostic(
1515 diag::err_expected, Attribute,
1516 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1517 << tok::comma;
1518 SkipToEnd();
1519 return;
1520 }
1521
1522 if (Tok.isNot(tok::identifier)) {
1523 createExpectedAttributeSubjectRulesTokenDiagnostic(
1524 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1525 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1526 SkipToEnd();
1527 return;
1528 }
1529 const IdentifierInfo *II = Tok.getIdentifierInfo();
1530 if (!II->isStr("apply_to")) {
1531 createExpectedAttributeSubjectRulesTokenDiagnostic(
1532 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1533 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1534 SkipToEnd();
1535 return;
1536 }
1537 ConsumeToken();
1538
1539 if (!TryConsumeToken(tok::equal)) {
1540 createExpectedAttributeSubjectRulesTokenDiagnostic(
1541 diag::err_expected, Attribute,
1542 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1543 << tok::equal;
1544 SkipToEnd();
1545 return;
1546 }
1547
1548 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1549 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1550 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1551 LastMatchRuleEndLoc)) {
1552 SkipToEnd();
1553 return;
1554 }
1555
1556 // Tokens following an ill-formed attribute will remain in the token stream
1557 // and must be removed.
1558 if (Tok.isNot(tok::eof)) {
1559 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1560 SkipToEnd();
1561 return;
1562 }
1563
1564 // Consume the eof terminator token.
1565 ConsumeToken();
1566
1567 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1568 if (Info->Action == PragmaAttributeInfo::Push)
1569 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1570
1571 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1572 std::move(SubjectMatchRules));
1573 }
1574
1575 // #pragma GCC visibility comes in two variants:
1576 // 'push' '(' [visibility] ')'
1577 // 'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & VisTok)1578 void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1579 PragmaIntroducer Introducer,
1580 Token &VisTok) {
1581 SourceLocation VisLoc = VisTok.getLocation();
1582
1583 Token Tok;
1584 PP.LexUnexpandedToken(Tok);
1585
1586 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1587
1588 const IdentifierInfo *VisType;
1589 if (PushPop && PushPop->isStr("pop")) {
1590 VisType = nullptr;
1591 } else if (PushPop && PushPop->isStr("push")) {
1592 PP.LexUnexpandedToken(Tok);
1593 if (Tok.isNot(tok::l_paren)) {
1594 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1595 << "visibility";
1596 return;
1597 }
1598 PP.LexUnexpandedToken(Tok);
1599 VisType = Tok.getIdentifierInfo();
1600 if (!VisType) {
1601 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1602 << "visibility";
1603 return;
1604 }
1605 PP.LexUnexpandedToken(Tok);
1606 if (Tok.isNot(tok::r_paren)) {
1607 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1608 << "visibility";
1609 return;
1610 }
1611 } else {
1612 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1613 << "visibility";
1614 return;
1615 }
1616 SourceLocation EndLoc = Tok.getLocation();
1617 PP.LexUnexpandedToken(Tok);
1618 if (Tok.isNot(tok::eod)) {
1619 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1620 << "visibility";
1621 return;
1622 }
1623
1624 auto Toks = std::make_unique<Token[]>(1);
1625 Toks[0].startToken();
1626 Toks[0].setKind(tok::annot_pragma_vis);
1627 Toks[0].setLocation(VisLoc);
1628 Toks[0].setAnnotationEndLoc(EndLoc);
1629 Toks[0].setAnnotationValue(
1630 const_cast<void *>(static_cast<const void *>(VisType)));
1631 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1632 /*IsReinject=*/false);
1633 }
1634
1635 // #pragma pack(...) comes in the following delicious flavors:
1636 // pack '(' [integer] ')'
1637 // pack '(' 'show' ')'
1638 // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & PackTok)1639 void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1640 PragmaIntroducer Introducer,
1641 Token &PackTok) {
1642 SourceLocation PackLoc = PackTok.getLocation();
1643
1644 Token Tok;
1645 PP.Lex(Tok);
1646 if (Tok.isNot(tok::l_paren)) {
1647 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
1648 return;
1649 }
1650
1651 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1652 StringRef SlotLabel;
1653 Token Alignment;
1654 Alignment.startToken();
1655 PP.Lex(Tok);
1656 if (Tok.is(tok::numeric_constant)) {
1657 Alignment = Tok;
1658
1659 PP.Lex(Tok);
1660
1661 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1662 // the push/pop stack.
1663 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
1664 Action =
1665 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
1666 } else if (Tok.is(tok::identifier)) {
1667 const IdentifierInfo *II = Tok.getIdentifierInfo();
1668 if (II->isStr("show")) {
1669 Action = Sema::PSK_Show;
1670 PP.Lex(Tok);
1671 } else {
1672 if (II->isStr("push")) {
1673 Action = Sema::PSK_Push;
1674 } else if (II->isStr("pop")) {
1675 Action = Sema::PSK_Pop;
1676 } else {
1677 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
1678 return;
1679 }
1680 PP.Lex(Tok);
1681
1682 if (Tok.is(tok::comma)) {
1683 PP.Lex(Tok);
1684
1685 if (Tok.is(tok::numeric_constant)) {
1686 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1687 Alignment = Tok;
1688
1689 PP.Lex(Tok);
1690 } else if (Tok.is(tok::identifier)) {
1691 SlotLabel = Tok.getIdentifierInfo()->getName();
1692 PP.Lex(Tok);
1693
1694 if (Tok.is(tok::comma)) {
1695 PP.Lex(Tok);
1696
1697 if (Tok.isNot(tok::numeric_constant)) {
1698 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1699 return;
1700 }
1701
1702 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1703 Alignment = Tok;
1704
1705 PP.Lex(Tok);
1706 }
1707 } else {
1708 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
1709 return;
1710 }
1711 }
1712 }
1713 } else if (PP.getLangOpts().ApplePragmaPack) {
1714 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1715 // the push/pop stack.
1716 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
1717 Action = Sema::PSK_Pop;
1718 }
1719
1720 if (Tok.isNot(tok::r_paren)) {
1721 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
1722 return;
1723 }
1724
1725 SourceLocation RParenLoc = Tok.getLocation();
1726 PP.Lex(Tok);
1727 if (Tok.isNot(tok::eod)) {
1728 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1729 return;
1730 }
1731
1732 PragmaPackInfo *Info =
1733 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
1734 Info->Action = Action;
1735 Info->SlotLabel = SlotLabel;
1736 Info->Alignment = Alignment;
1737
1738 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1739 1);
1740 Toks[0].startToken();
1741 Toks[0].setKind(tok::annot_pragma_pack);
1742 Toks[0].setLocation(PackLoc);
1743 Toks[0].setAnnotationEndLoc(RParenLoc);
1744 Toks[0].setAnnotationValue(static_cast<void*>(Info));
1745 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1746 /*IsReinject=*/false);
1747 }
1748
1749 // #pragma ms_struct on
1750 // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & MSStructTok)1751 void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1752 PragmaIntroducer Introducer,
1753 Token &MSStructTok) {
1754 PragmaMSStructKind Kind = PMSST_OFF;
1755
1756 Token Tok;
1757 PP.Lex(Tok);
1758 if (Tok.isNot(tok::identifier)) {
1759 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1760 return;
1761 }
1762 SourceLocation EndLoc = Tok.getLocation();
1763 const IdentifierInfo *II = Tok.getIdentifierInfo();
1764 if (II->isStr("on")) {
1765 Kind = PMSST_ON;
1766 PP.Lex(Tok);
1767 }
1768 else if (II->isStr("off") || II->isStr("reset"))
1769 PP.Lex(Tok);
1770 else {
1771 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1772 return;
1773 }
1774
1775 if (Tok.isNot(tok::eod)) {
1776 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1777 << "ms_struct";
1778 return;
1779 }
1780
1781 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1782 1);
1783 Toks[0].startToken();
1784 Toks[0].setKind(tok::annot_pragma_msstruct);
1785 Toks[0].setLocation(MSStructTok.getLocation());
1786 Toks[0].setAnnotationEndLoc(EndLoc);
1787 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1788 static_cast<uintptr_t>(Kind)));
1789 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1790 /*IsReinject=*/false);
1791 }
1792
1793 // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)1794 void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1795 PragmaIntroducer Introducer,
1796 Token &FirstToken) {
1797
1798 Token Tok;
1799 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1800
1801 PP.Lex(Tok); // eat 'section'
1802 while (Tok.isNot(tok::eod)) {
1803 if (Tok.isNot(tok::identifier)) {
1804 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1805 return;
1806 }
1807
1808 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1809 if (SecType->isStr("bss"))
1810 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1811 else if (SecType->isStr("data"))
1812 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1813 else if (SecType->isStr("rodata"))
1814 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1815 else if (SecType->isStr("relro"))
1816 SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
1817 else if (SecType->isStr("text"))
1818 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1819 else {
1820 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1821 return;
1822 }
1823
1824 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1825 if (Tok.isNot(tok::equal)) {
1826 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1827 return;
1828 }
1829
1830 std::string SecName;
1831 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1832 return;
1833
1834 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1835 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1836 Sema::PragmaClangSectionAction::PCSA_Clear),
1837 SecKind, SecName);
1838 }
1839 }
1840
1841 // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1842 // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)1843 static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
1844 bool IsOptions) {
1845 Token Tok;
1846
1847 if (IsOptions) {
1848 PP.Lex(Tok);
1849 if (Tok.isNot(tok::identifier) ||
1850 !Tok.getIdentifierInfo()->isStr("align")) {
1851 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1852 return;
1853 }
1854 }
1855
1856 PP.Lex(Tok);
1857 if (Tok.isNot(tok::equal)) {
1858 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1859 << IsOptions;
1860 return;
1861 }
1862
1863 PP.Lex(Tok);
1864 if (Tok.isNot(tok::identifier)) {
1865 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1866 << (IsOptions ? "options" : "align");
1867 return;
1868 }
1869
1870 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
1871 const IdentifierInfo *II = Tok.getIdentifierInfo();
1872 if (II->isStr("native"))
1873 Kind = Sema::POAK_Native;
1874 else if (II->isStr("natural"))
1875 Kind = Sema::POAK_Natural;
1876 else if (II->isStr("packed"))
1877 Kind = Sema::POAK_Packed;
1878 else if (II->isStr("power"))
1879 Kind = Sema::POAK_Power;
1880 else if (II->isStr("mac68k"))
1881 Kind = Sema::POAK_Mac68k;
1882 else if (II->isStr("reset"))
1883 Kind = Sema::POAK_Reset;
1884 else {
1885 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1886 << IsOptions;
1887 return;
1888 }
1889
1890 SourceLocation EndLoc = Tok.getLocation();
1891 PP.Lex(Tok);
1892 if (Tok.isNot(tok::eod)) {
1893 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1894 << (IsOptions ? "options" : "align");
1895 return;
1896 }
1897
1898 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1899 1);
1900 Toks[0].startToken();
1901 Toks[0].setKind(tok::annot_pragma_align);
1902 Toks[0].setLocation(FirstTok.getLocation());
1903 Toks[0].setAnnotationEndLoc(EndLoc);
1904 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1905 static_cast<uintptr_t>(Kind)));
1906 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1907 /*IsReinject=*/false);
1908 }
1909
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & AlignTok)1910 void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1911 PragmaIntroducer Introducer,
1912 Token &AlignTok) {
1913 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
1914 }
1915
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & OptionsTok)1916 void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1917 PragmaIntroducer Introducer,
1918 Token &OptionsTok) {
1919 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
1920 }
1921
1922 // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & UnusedTok)1923 void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1924 PragmaIntroducer Introducer,
1925 Token &UnusedTok) {
1926 // FIXME: Should we be expanding macros here? My guess is no.
1927 SourceLocation UnusedLoc = UnusedTok.getLocation();
1928
1929 // Lex the left '('.
1930 Token Tok;
1931 PP.Lex(Tok);
1932 if (Tok.isNot(tok::l_paren)) {
1933 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1934 return;
1935 }
1936
1937 // Lex the declaration reference(s).
1938 SmallVector<Token, 5> Identifiers;
1939 SourceLocation RParenLoc;
1940 bool LexID = true;
1941
1942 while (true) {
1943 PP.Lex(Tok);
1944
1945 if (LexID) {
1946 if (Tok.is(tok::identifier)) {
1947 Identifiers.push_back(Tok);
1948 LexID = false;
1949 continue;
1950 }
1951
1952 // Illegal token!
1953 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1954 return;
1955 }
1956
1957 // We are execting a ')' or a ','.
1958 if (Tok.is(tok::comma)) {
1959 LexID = true;
1960 continue;
1961 }
1962
1963 if (Tok.is(tok::r_paren)) {
1964 RParenLoc = Tok.getLocation();
1965 break;
1966 }
1967
1968 // Illegal token!
1969 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
1970 return;
1971 }
1972
1973 PP.Lex(Tok);
1974 if (Tok.isNot(tok::eod)) {
1975 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1976 "unused";
1977 return;
1978 }
1979
1980 // Verify that we have a location for the right parenthesis.
1981 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
1982 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
1983
1984 // For each identifier token, insert into the token stream a
1985 // annot_pragma_unused token followed by the identifier token.
1986 // This allows us to cache a "#pragma unused" that occurs inside an inline
1987 // C++ member function.
1988
1989 MutableArrayRef<Token> Toks(
1990 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1991 2 * Identifiers.size());
1992 for (unsigned i=0; i != Identifiers.size(); i++) {
1993 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1994 pragmaUnusedTok.startToken();
1995 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1996 pragmaUnusedTok.setLocation(UnusedLoc);
1997 idTok = Identifiers[i];
1998 }
1999 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2000 /*IsReinject=*/false);
2001 }
2002
2003 // #pragma weak identifier
2004 // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & WeakTok)2005 void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2006 PragmaIntroducer Introducer,
2007 Token &WeakTok) {
2008 SourceLocation WeakLoc = WeakTok.getLocation();
2009
2010 Token Tok;
2011 PP.Lex(Tok);
2012 if (Tok.isNot(tok::identifier)) {
2013 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2014 return;
2015 }
2016
2017 Token WeakName = Tok;
2018 bool HasAlias = false;
2019 Token AliasName;
2020
2021 PP.Lex(Tok);
2022 if (Tok.is(tok::equal)) {
2023 HasAlias = true;
2024 PP.Lex(Tok);
2025 if (Tok.isNot(tok::identifier)) {
2026 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2027 << "weak";
2028 return;
2029 }
2030 AliasName = Tok;
2031 PP.Lex(Tok);
2032 }
2033
2034 if (Tok.isNot(tok::eod)) {
2035 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2036 return;
2037 }
2038
2039 if (HasAlias) {
2040 MutableArrayRef<Token> Toks(
2041 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2042 Token &pragmaUnusedTok = Toks[0];
2043 pragmaUnusedTok.startToken();
2044 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2045 pragmaUnusedTok.setLocation(WeakLoc);
2046 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2047 Toks[1] = WeakName;
2048 Toks[2] = AliasName;
2049 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2050 /*IsReinject=*/false);
2051 } else {
2052 MutableArrayRef<Token> Toks(
2053 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2054 Token &pragmaUnusedTok = Toks[0];
2055 pragmaUnusedTok.startToken();
2056 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2057 pragmaUnusedTok.setLocation(WeakLoc);
2058 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2059 Toks[1] = WeakName;
2060 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2061 /*IsReinject=*/false);
2062 }
2063 }
2064
2065 // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & RedefToken)2066 void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2067 PragmaIntroducer Introducer,
2068 Token &RedefToken) {
2069 SourceLocation RedefLoc = RedefToken.getLocation();
2070
2071 Token Tok;
2072 PP.Lex(Tok);
2073 if (Tok.isNot(tok::identifier)) {
2074 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2075 "redefine_extname";
2076 return;
2077 }
2078
2079 Token RedefName = Tok;
2080 PP.Lex(Tok);
2081
2082 if (Tok.isNot(tok::identifier)) {
2083 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2084 << "redefine_extname";
2085 return;
2086 }
2087
2088 Token AliasName = Tok;
2089 PP.Lex(Tok);
2090
2091 if (Tok.isNot(tok::eod)) {
2092 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2093 "redefine_extname";
2094 return;
2095 }
2096
2097 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2098 3);
2099 Token &pragmaRedefTok = Toks[0];
2100 pragmaRedefTok.startToken();
2101 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2102 pragmaRedefTok.setLocation(RedefLoc);
2103 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2104 Toks[1] = RedefName;
2105 Toks[2] = AliasName;
2106 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2107 /*IsReinject=*/false);
2108 }
2109
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2110 void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2111 PragmaIntroducer Introducer,
2112 Token &Tok) {
2113 tok::OnOffSwitch OOS;
2114 if (PP.LexOnOffSwitch(OOS))
2115 return;
2116
2117 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2118 1);
2119 Toks[0].startToken();
2120 Toks[0].setKind(tok::annot_pragma_fp_contract);
2121 Toks[0].setLocation(Tok.getLocation());
2122 Toks[0].setAnnotationEndLoc(Tok.getLocation());
2123 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2124 static_cast<uintptr_t>(OOS)));
2125 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2126 /*IsReinject=*/false);
2127 }
2128
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2129 void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2130 PragmaIntroducer Introducer,
2131 Token &Tok) {
2132 PP.LexUnexpandedToken(Tok);
2133 if (Tok.isNot(tok::identifier)) {
2134 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2135 "OPENCL";
2136 return;
2137 }
2138 IdentifierInfo *Ext = Tok.getIdentifierInfo();
2139 SourceLocation NameLoc = Tok.getLocation();
2140
2141 PP.Lex(Tok);
2142 if (Tok.isNot(tok::colon)) {
2143 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2144 return;
2145 }
2146
2147 PP.Lex(Tok);
2148 if (Tok.isNot(tok::identifier)) {
2149 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2150 return;
2151 }
2152 IdentifierInfo *Pred = Tok.getIdentifierInfo();
2153
2154 OpenCLExtState State;
2155 if (Pred->isStr("enable")) {
2156 State = Enable;
2157 } else if (Pred->isStr("disable")) {
2158 State = Disable;
2159 } else if (Pred->isStr("begin"))
2160 State = Begin;
2161 else if (Pred->isStr("end"))
2162 State = End;
2163 else {
2164 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2165 << Ext->isStr("all");
2166 return;
2167 }
2168 SourceLocation StateLoc = Tok.getLocation();
2169
2170 PP.Lex(Tok);
2171 if (Tok.isNot(tok::eod)) {
2172 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2173 "OPENCL EXTENSION";
2174 return;
2175 }
2176
2177 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2178 Info->first = Ext;
2179 Info->second = State;
2180 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2181 1);
2182 Toks[0].startToken();
2183 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2184 Toks[0].setLocation(NameLoc);
2185 Toks[0].setAnnotationValue(static_cast<void*>(Info));
2186 Toks[0].setAnnotationEndLoc(StateLoc);
2187 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2188 /*IsReinject=*/false);
2189
2190 if (PP.getPPCallbacks())
2191 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2192 StateLoc, State);
2193 }
2194
2195 /// Handle '#pragma omp ...' when OpenMP is disabled.
2196 ///
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2197 void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2198 PragmaIntroducer Introducer,
2199 Token &FirstTok) {
2200 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2201 FirstTok.getLocation())) {
2202 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
2203 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2204 diag::Severity::Ignored, SourceLocation());
2205 }
2206 PP.DiscardUntilEndOfDirective();
2207 }
2208
2209 /// Handle '#pragma omp ...' when OpenMP is enabled.
2210 ///
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2211 void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2212 PragmaIntroducer Introducer,
2213 Token &FirstTok) {
2214 SmallVector<Token, 16> Pragma;
2215 Token Tok;
2216 Tok.startToken();
2217 Tok.setKind(tok::annot_pragma_openmp);
2218 Tok.setLocation(Introducer.Loc);
2219
2220 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
2221 Pragma.push_back(Tok);
2222 PP.Lex(Tok);
2223 if (Tok.is(tok::annot_pragma_openmp)) {
2224 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2225 unsigned InnerPragmaCnt = 1;
2226 while (InnerPragmaCnt != 0) {
2227 PP.Lex(Tok);
2228 if (Tok.is(tok::annot_pragma_openmp))
2229 ++InnerPragmaCnt;
2230 else if (Tok.is(tok::annot_pragma_openmp_end))
2231 --InnerPragmaCnt;
2232 }
2233 PP.Lex(Tok);
2234 }
2235 }
2236 SourceLocation EodLoc = Tok.getLocation();
2237 Tok.startToken();
2238 Tok.setKind(tok::annot_pragma_openmp_end);
2239 Tok.setLocation(EodLoc);
2240 Pragma.push_back(Tok);
2241
2242 auto Toks = std::make_unique<Token[]>(Pragma.size());
2243 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2244 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2245 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2246 }
2247
2248 /// Handle '#pragma pointers_to_members'
2249 // The grammar for this pragma is as follows:
2250 //
2251 // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2252 //
2253 // #pragma pointers_to_members '(' 'best_case' ')'
2254 // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2255 // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2256 void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2257 PragmaIntroducer Introducer,
2258 Token &Tok) {
2259 SourceLocation PointersToMembersLoc = Tok.getLocation();
2260 PP.Lex(Tok);
2261 if (Tok.isNot(tok::l_paren)) {
2262 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2263 << "pointers_to_members";
2264 return;
2265 }
2266 PP.Lex(Tok);
2267 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2268 if (!Arg) {
2269 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2270 << "pointers_to_members";
2271 return;
2272 }
2273 PP.Lex(Tok);
2274
2275 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2276 if (Arg->isStr("best_case")) {
2277 RepresentationMethod = LangOptions::PPTMK_BestCase;
2278 } else {
2279 if (Arg->isStr("full_generality")) {
2280 if (Tok.is(tok::comma)) {
2281 PP.Lex(Tok);
2282
2283 Arg = Tok.getIdentifierInfo();
2284 if (!Arg) {
2285 PP.Diag(Tok.getLocation(),
2286 diag::err_pragma_pointers_to_members_unknown_kind)
2287 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2288 return;
2289 }
2290 PP.Lex(Tok);
2291 } else if (Tok.is(tok::r_paren)) {
2292 // #pragma pointers_to_members(full_generality) implicitly specifies
2293 // virtual_inheritance.
2294 Arg = nullptr;
2295 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2296 } else {
2297 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2298 << "full_generality";
2299 return;
2300 }
2301 }
2302
2303 if (Arg) {
2304 if (Arg->isStr("single_inheritance")) {
2305 RepresentationMethod =
2306 LangOptions::PPTMK_FullGeneralitySingleInheritance;
2307 } else if (Arg->isStr("multiple_inheritance")) {
2308 RepresentationMethod =
2309 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
2310 } else if (Arg->isStr("virtual_inheritance")) {
2311 RepresentationMethod =
2312 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2313 } else {
2314 PP.Diag(Tok.getLocation(),
2315 diag::err_pragma_pointers_to_members_unknown_kind)
2316 << Arg << /*HasPointerDeclaration*/ 1;
2317 return;
2318 }
2319 }
2320 }
2321
2322 if (Tok.isNot(tok::r_paren)) {
2323 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2324 << (Arg ? Arg->getName() : "full_generality");
2325 return;
2326 }
2327
2328 SourceLocation EndLoc = Tok.getLocation();
2329 PP.Lex(Tok);
2330 if (Tok.isNot(tok::eod)) {
2331 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2332 << "pointers_to_members";
2333 return;
2334 }
2335
2336 Token AnnotTok;
2337 AnnotTok.startToken();
2338 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2339 AnnotTok.setLocation(PointersToMembersLoc);
2340 AnnotTok.setAnnotationEndLoc(EndLoc);
2341 AnnotTok.setAnnotationValue(
2342 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2343 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2344 }
2345
2346 /// Handle '#pragma vtordisp'
2347 // The grammar for this pragma is as follows:
2348 //
2349 // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2350 //
2351 // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2352 // #pragma vtordisp '(' 'pop' ')'
2353 // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2354 void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2355 PragmaIntroducer Introducer, Token &Tok) {
2356 SourceLocation VtorDispLoc = Tok.getLocation();
2357 PP.Lex(Tok);
2358 if (Tok.isNot(tok::l_paren)) {
2359 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2360 return;
2361 }
2362 PP.Lex(Tok);
2363
2364 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2365 const IdentifierInfo *II = Tok.getIdentifierInfo();
2366 if (II) {
2367 if (II->isStr("push")) {
2368 // #pragma vtordisp(push, mode)
2369 PP.Lex(Tok);
2370 if (Tok.isNot(tok::comma)) {
2371 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2372 return;
2373 }
2374 PP.Lex(Tok);
2375 Action = Sema::PSK_Push_Set;
2376 // not push, could be on/off
2377 } else if (II->isStr("pop")) {
2378 // #pragma vtordisp(pop)
2379 PP.Lex(Tok);
2380 Action = Sema::PSK_Pop;
2381 }
2382 // not push or pop, could be on/off
2383 } else {
2384 if (Tok.is(tok::r_paren)) {
2385 // #pragma vtordisp()
2386 Action = Sema::PSK_Reset;
2387 }
2388 }
2389
2390
2391 uint64_t Value = 0;
2392 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
2393 const IdentifierInfo *II = Tok.getIdentifierInfo();
2394 if (II && II->isStr("off")) {
2395 PP.Lex(Tok);
2396 Value = 0;
2397 } else if (II && II->isStr("on")) {
2398 PP.Lex(Tok);
2399 Value = 1;
2400 } else if (Tok.is(tok::numeric_constant) &&
2401 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2402 if (Value > 2) {
2403 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2404 << 0 << 2 << "vtordisp";
2405 return;
2406 }
2407 } else {
2408 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2409 << "vtordisp";
2410 return;
2411 }
2412 }
2413
2414 // Finish the pragma: ')' $
2415 if (Tok.isNot(tok::r_paren)) {
2416 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2417 return;
2418 }
2419 SourceLocation EndLoc = Tok.getLocation();
2420 PP.Lex(Tok);
2421 if (Tok.isNot(tok::eod)) {
2422 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2423 << "vtordisp";
2424 return;
2425 }
2426
2427 // Enter the annotation.
2428 Token AnnotTok;
2429 AnnotTok.startToken();
2430 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2431 AnnotTok.setLocation(VtorDispLoc);
2432 AnnotTok.setAnnotationEndLoc(EndLoc);
2433 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2434 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2435 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2436 }
2437
2438 /// Handle all MS pragmas. Simply forwards the tokens after inserting
2439 /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2440 void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2441 PragmaIntroducer Introducer, Token &Tok) {
2442 Token EoF, AnnotTok;
2443 EoF.startToken();
2444 EoF.setKind(tok::eof);
2445 AnnotTok.startToken();
2446 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2447 AnnotTok.setLocation(Tok.getLocation());
2448 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2449 SmallVector<Token, 8> TokenVector;
2450 // Suck up all of the tokens before the eod.
2451 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
2452 TokenVector.push_back(Tok);
2453 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2454 }
2455 // Add a sentinel EoF token to the end of the list.
2456 TokenVector.push_back(EoF);
2457 // We must allocate this array with new because EnterTokenStream is going to
2458 // delete it later.
2459 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2460 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2461 auto Value = new (PP.getPreprocessorAllocator())
2462 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2463 TokenVector.size());
2464 AnnotTok.setAnnotationValue(Value);
2465 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2466 }
2467
2468 /// Handle the Microsoft \#pragma detect_mismatch extension.
2469 ///
2470 /// The syntax is:
2471 /// \code
2472 /// #pragma detect_mismatch("name", "value")
2473 /// \endcode
2474 /// Where 'name' and 'value' are quoted strings. The values are embedded in
2475 /// the object file and passed along to the linker. If the linker detects a
2476 /// mismatch in the object file's values for the given name, a LNK2038 error
2477 /// is emitted. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2478 void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2479 PragmaIntroducer Introducer,
2480 Token &Tok) {
2481 SourceLocation DetectMismatchLoc = Tok.getLocation();
2482 PP.Lex(Tok);
2483 if (Tok.isNot(tok::l_paren)) {
2484 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
2485 return;
2486 }
2487
2488 // Read the name to embed, which must be a string literal.
2489 std::string NameString;
2490 if (!PP.LexStringLiteral(Tok, NameString,
2491 "pragma detect_mismatch",
2492 /*AllowMacroExpansion=*/true))
2493 return;
2494
2495 // Read the comma followed by a second string literal.
2496 std::string ValueString;
2497 if (Tok.isNot(tok::comma)) {
2498 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2499 return;
2500 }
2501
2502 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2503 /*AllowMacroExpansion=*/true))
2504 return;
2505
2506 if (Tok.isNot(tok::r_paren)) {
2507 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2508 return;
2509 }
2510 PP.Lex(Tok); // Eat the r_paren.
2511
2512 if (Tok.isNot(tok::eod)) {
2513 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2514 return;
2515 }
2516
2517 // If the pragma is lexically sound, notify any interested PPCallbacks.
2518 if (PP.getPPCallbacks())
2519 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
2520 ValueString);
2521
2522 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
2523 }
2524
2525 /// Handle the microsoft \#pragma comment extension.
2526 ///
2527 /// The syntax is:
2528 /// \code
2529 /// #pragma comment(linker, "foo")
2530 /// \endcode
2531 /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2532 /// "foo" is a string, which is fully macro expanded, and permits string
2533 /// concatenation, embedded escape characters etc. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2534 void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2535 PragmaIntroducer Introducer,
2536 Token &Tok) {
2537 SourceLocation CommentLoc = Tok.getLocation();
2538 PP.Lex(Tok);
2539 if (Tok.isNot(tok::l_paren)) {
2540 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2541 return;
2542 }
2543
2544 // Read the identifier.
2545 PP.Lex(Tok);
2546 if (Tok.isNot(tok::identifier)) {
2547 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2548 return;
2549 }
2550
2551 // Verify that this is one of the 5 whitelisted options.
2552 IdentifierInfo *II = Tok.getIdentifierInfo();
2553 PragmaMSCommentKind Kind =
2554 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2555 .Case("linker", PCK_Linker)
2556 .Case("lib", PCK_Lib)
2557 .Case("compiler", PCK_Compiler)
2558 .Case("exestr", PCK_ExeStr)
2559 .Case("user", PCK_User)
2560 .Default(PCK_Unknown);
2561 if (Kind == PCK_Unknown) {
2562 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2563 return;
2564 }
2565
2566 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2567 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2568 << II->getName();
2569 return;
2570 }
2571
2572 // On PS4, issue a warning about any pragma comments other than
2573 // #pragma comment lib.
2574 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
2575 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2576 << II->getName();
2577 return;
2578 }
2579
2580 // Read the optional string if present.
2581 PP.Lex(Tok);
2582 std::string ArgumentString;
2583 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2584 "pragma comment",
2585 /*AllowMacroExpansion=*/true))
2586 return;
2587
2588 // FIXME: warn that 'exestr' is deprecated.
2589 // FIXME: If the kind is "compiler" warn if the string is present (it is
2590 // ignored).
2591 // The MSDN docs say that "lib" and "linker" require a string and have a short
2592 // whitelist of linker options they support, but in practice MSVC doesn't
2593 // issue a diagnostic. Therefore neither does clang.
2594
2595 if (Tok.isNot(tok::r_paren)) {
2596 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2597 return;
2598 }
2599 PP.Lex(Tok); // eat the r_paren.
2600
2601 if (Tok.isNot(tok::eod)) {
2602 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2603 return;
2604 }
2605
2606 // If the pragma is lexically sound, notify any interested PPCallbacks.
2607 if (PP.getPPCallbacks())
2608 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2609
2610 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
2611 }
2612
2613 // #pragma clang optimize off
2614 // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)2615 void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2616 PragmaIntroducer Introducer,
2617 Token &FirstToken) {
2618 Token Tok;
2619 PP.Lex(Tok);
2620 if (Tok.is(tok::eod)) {
2621 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
2622 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
2623 return;
2624 }
2625 if (Tok.isNot(tok::identifier)) {
2626 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2627 << PP.getSpelling(Tok);
2628 return;
2629 }
2630 const IdentifierInfo *II = Tok.getIdentifierInfo();
2631 // The only accepted values are 'on' or 'off'.
2632 bool IsOn = false;
2633 if (II->isStr("on")) {
2634 IsOn = true;
2635 } else if (!II->isStr("off")) {
2636 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2637 << PP.getSpelling(Tok);
2638 return;
2639 }
2640 PP.Lex(Tok);
2641
2642 if (Tok.isNot(tok::eod)) {
2643 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2644 << PP.getSpelling(Tok);
2645 return;
2646 }
2647
2648 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2649 }
2650
2651 namespace {
2652 /// Used as the annotation value for tok::annot_pragma_fp.
2653 struct TokFPAnnotValue {
2654 enum FlagKinds { Contract };
2655 enum FlagValues { On, Off, Fast };
2656
2657 FlagKinds FlagKind;
2658 FlagValues FlagValue;
2659 };
2660 } // end anonymous namespace
2661
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2662 void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2663 PragmaIntroducer Introducer, Token &Tok) {
2664 // fp
2665 Token PragmaName = Tok;
2666 SmallVector<Token, 1> TokenList;
2667
2668 PP.Lex(Tok);
2669 if (Tok.isNot(tok::identifier)) {
2670 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2671 << /*MissingOption=*/true << "";
2672 return;
2673 }
2674
2675 while (Tok.is(tok::identifier)) {
2676 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2677
2678 auto FlagKind =
2679 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2680 OptionInfo->getName())
2681 .Case("contract", TokFPAnnotValue::Contract)
2682 .Default(None);
2683 if (!FlagKind) {
2684 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2685 << /*MissingOption=*/false << OptionInfo;
2686 return;
2687 }
2688 PP.Lex(Tok);
2689
2690 // Read '('
2691 if (Tok.isNot(tok::l_paren)) {
2692 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2693 return;
2694 }
2695 PP.Lex(Tok);
2696
2697 if (Tok.isNot(tok::identifier)) {
2698 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2699 << PP.getSpelling(Tok) << OptionInfo->getName();
2700 return;
2701 }
2702 const IdentifierInfo *II = Tok.getIdentifierInfo();
2703
2704 auto FlagValue =
2705 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2706 II->getName())
2707 .Case("on", TokFPAnnotValue::On)
2708 .Case("off", TokFPAnnotValue::Off)
2709 .Case("fast", TokFPAnnotValue::Fast)
2710 .Default(llvm::None);
2711
2712 if (!FlagValue) {
2713 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2714 << PP.getSpelling(Tok) << OptionInfo->getName();
2715 return;
2716 }
2717 PP.Lex(Tok);
2718
2719 // Read ')'
2720 if (Tok.isNot(tok::r_paren)) {
2721 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2722 return;
2723 }
2724 PP.Lex(Tok);
2725
2726 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2727 TokFPAnnotValue{*FlagKind, *FlagValue};
2728 // Generate the loop hint token.
2729 Token FPTok;
2730 FPTok.startToken();
2731 FPTok.setKind(tok::annot_pragma_fp);
2732 FPTok.setLocation(PragmaName.getLocation());
2733 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2734 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2735 TokenList.push_back(FPTok);
2736 }
2737
2738 if (Tok.isNot(tok::eod)) {
2739 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2740 << "clang fp";
2741 return;
2742 }
2743
2744 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
2745 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2746
2747 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2748 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2749 }
2750
HandlePragmaFP()2751 void Parser::HandlePragmaFP() {
2752 assert(Tok.is(tok::annot_pragma_fp));
2753 auto *AnnotValue =
2754 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2755
2756 LangOptions::FPContractModeKind FPC;
2757 switch (AnnotValue->FlagValue) {
2758 case TokFPAnnotValue::On:
2759 FPC = LangOptions::FPC_On;
2760 break;
2761 case TokFPAnnotValue::Fast:
2762 FPC = LangOptions::FPC_Fast;
2763 break;
2764 case TokFPAnnotValue::Off:
2765 FPC = LangOptions::FPC_Off;
2766 break;
2767 }
2768
2769 Actions.ActOnPragmaFPContract(FPC);
2770 ConsumeAnnotationToken();
2771 }
2772
2773 /// Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)2774 static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2775 Token Option, bool ValueInParens,
2776 PragmaLoopHintInfo &Info) {
2777 SmallVector<Token, 1> ValueList;
2778 int OpenParens = ValueInParens ? 1 : 0;
2779 // Read constant expression.
2780 while (Tok.isNot(tok::eod)) {
2781 if (Tok.is(tok::l_paren))
2782 OpenParens++;
2783 else if (Tok.is(tok::r_paren)) {
2784 OpenParens--;
2785 if (OpenParens == 0 && ValueInParens)
2786 break;
2787 }
2788
2789 ValueList.push_back(Tok);
2790 PP.Lex(Tok);
2791 }
2792
2793 if (ValueInParens) {
2794 // Read ')'
2795 if (Tok.isNot(tok::r_paren)) {
2796 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2797 return true;
2798 }
2799 PP.Lex(Tok);
2800 }
2801
2802 Token EOFTok;
2803 EOFTok.startToken();
2804 EOFTok.setKind(tok::eof);
2805 EOFTok.setLocation(Tok.getLocation());
2806 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2807
2808 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
2809
2810 Info.PragmaName = PragmaName;
2811 Info.Option = Option;
2812 return false;
2813 }
2814
2815 /// Handle the \#pragma clang loop directive.
2816 /// #pragma clang 'loop' loop-hints
2817 ///
2818 /// loop-hints:
2819 /// loop-hint loop-hints[opt]
2820 ///
2821 /// loop-hint:
2822 /// 'vectorize' '(' loop-hint-keyword ')'
2823 /// 'interleave' '(' loop-hint-keyword ')'
2824 /// 'unroll' '(' unroll-hint-keyword ')'
2825 /// 'vectorize_predicate' '(' loop-hint-keyword ')'
2826 /// 'vectorize_width' '(' loop-hint-value ')'
2827 /// 'interleave_count' '(' loop-hint-value ')'
2828 /// 'unroll_count' '(' loop-hint-value ')'
2829 /// 'pipeline' '(' disable ')'
2830 /// 'pipeline_initiation_interval' '(' loop-hint-value ')'
2831 ///
2832 /// loop-hint-keyword:
2833 /// 'enable'
2834 /// 'disable'
2835 /// 'assume_safety'
2836 ///
2837 /// unroll-hint-keyword:
2838 /// 'enable'
2839 /// 'disable'
2840 /// 'full'
2841 ///
2842 /// loop-hint-value:
2843 /// constant-expression
2844 ///
2845 /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2846 /// try vectorizing the instructions of the loop it precedes. Specifying
2847 /// interleave(enable) or interleave_count(_value_) instructs llvm to try
2848 /// interleaving multiple iterations of the loop it precedes. The width of the
2849 /// vector instructions is specified by vectorize_width() and the number of
2850 /// interleaved loop iterations is specified by interleave_count(). Specifying a
2851 /// value of 1 effectively disables vectorization/interleaving, even if it is
2852 /// possible and profitable, and 0 is invalid. The loop vectorizer currently
2853 /// only works on inner loops.
2854 ///
2855 /// The unroll and unroll_count directives control the concatenation
2856 /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2857 /// completely if the trip count is known at compile time and unroll partially
2858 /// if the trip count is not known. Specifying unroll(full) is similar to
2859 /// unroll(enable) but will unroll the loop only if the trip count is known at
2860 /// compile time. Specifying unroll(disable) disables unrolling for the
2861 /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2862 /// loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2863 void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2864 PragmaIntroducer Introducer,
2865 Token &Tok) {
2866 // Incoming token is "loop" from "#pragma clang loop".
2867 Token PragmaName = Tok;
2868 SmallVector<Token, 1> TokenList;
2869
2870 // Lex the optimization option and verify it is an identifier.
2871 PP.Lex(Tok);
2872 if (Tok.isNot(tok::identifier)) {
2873 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2874 << /*MissingOption=*/true << "";
2875 return;
2876 }
2877
2878 while (Tok.is(tok::identifier)) {
2879 Token Option = Tok;
2880 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2881
2882 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
2883 .Case("vectorize", true)
2884 .Case("interleave", true)
2885 .Case("unroll", true)
2886 .Case("distribute", true)
2887 .Case("vectorize_predicate", true)
2888 .Case("vectorize_width", true)
2889 .Case("interleave_count", true)
2890 .Case("unroll_count", true)
2891 .Case("pipeline", true)
2892 .Case("pipeline_initiation_interval", true)
2893 .Default(false);
2894 if (!OptionValid) {
2895 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2896 << /*MissingOption=*/false << OptionInfo;
2897 return;
2898 }
2899 PP.Lex(Tok);
2900
2901 // Read '('
2902 if (Tok.isNot(tok::l_paren)) {
2903 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2904 return;
2905 }
2906 PP.Lex(Tok);
2907
2908 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2909 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2910 *Info))
2911 return;
2912
2913 // Generate the loop hint token.
2914 Token LoopHintTok;
2915 LoopHintTok.startToken();
2916 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
2917 LoopHintTok.setLocation(PragmaName.getLocation());
2918 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
2919 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2920 TokenList.push_back(LoopHintTok);
2921 }
2922
2923 if (Tok.isNot(tok::eod)) {
2924 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2925 << "clang loop";
2926 return;
2927 }
2928
2929 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
2930 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2931
2932 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2933 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2934 }
2935
2936 /// Handle the loop unroll optimization pragmas.
2937 /// #pragma unroll
2938 /// #pragma unroll unroll-hint-value
2939 /// #pragma unroll '(' unroll-hint-value ')'
2940 /// #pragma nounroll
2941 /// #pragma unroll_and_jam
2942 /// #pragma unroll_and_jam unroll-hint-value
2943 /// #pragma unroll_and_jam '(' unroll-hint-value ')'
2944 /// #pragma nounroll_and_jam
2945 ///
2946 /// unroll-hint-value:
2947 /// constant-expression
2948 ///
2949 /// Loop unrolling hints can be specified with '#pragma unroll' or
2950 /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2951 /// contained in parentheses. With no argument the directive instructs llvm to
2952 /// try to unroll the loop completely. A positive integer argument can be
2953 /// specified to indicate the number of times the loop should be unrolled. To
2954 /// maximize compatibility with other compilers the unroll count argument can be
2955 /// specified with or without parentheses. Specifying, '#pragma nounroll'
2956 /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2957 void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2958 PragmaIntroducer Introducer,
2959 Token &Tok) {
2960 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2961 // "#pragma nounroll".
2962 Token PragmaName = Tok;
2963 PP.Lex(Tok);
2964 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2965 if (Tok.is(tok::eod)) {
2966 // nounroll or unroll pragma without an argument.
2967 Info->PragmaName = PragmaName;
2968 Info->Option.startToken();
2969 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
2970 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
2971 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2972 << PragmaName.getIdentifierInfo()->getName();
2973 return;
2974 } else {
2975 // Unroll pragma with an argument: "#pragma unroll N" or
2976 // "#pragma unroll(N)".
2977 // Read '(' if it exists.
2978 bool ValueInParens = Tok.is(tok::l_paren);
2979 if (ValueInParens)
2980 PP.Lex(Tok);
2981
2982 Token Option;
2983 Option.startToken();
2984 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
2985 return;
2986
2987 // In CUDA, the argument to '#pragma unroll' should not be contained in
2988 // parentheses.
2989 if (PP.getLangOpts().CUDA && ValueInParens)
2990 PP.Diag(Info->Toks[0].getLocation(),
2991 diag::warn_pragma_unroll_cuda_value_in_parens);
2992
2993 if (Tok.isNot(tok::eod)) {
2994 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2995 << "unroll";
2996 return;
2997 }
2998 }
2999
3000 // Generate the hint token.
3001 auto TokenArray = std::make_unique<Token[]>(1);
3002 TokenArray[0].startToken();
3003 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3004 TokenArray[0].setLocation(PragmaName.getLocation());
3005 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3006 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3007 PP.EnterTokenStream(std::move(TokenArray), 1,
3008 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3009 }
3010
3011 /// Handle the Microsoft \#pragma intrinsic extension.
3012 ///
3013 /// The syntax is:
3014 /// \code
3015 /// #pragma intrinsic(memset)
3016 /// #pragma intrinsic(strlen, memcpy)
3017 /// \endcode
3018 ///
3019 /// Pragma intrisic tells the compiler to use a builtin version of the
3020 /// function. Clang does it anyway, so the pragma doesn't really do anything.
3021 /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3022 /// isn't an intrinsic in clang and suggest to include intrin.h.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3023 void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3024 PragmaIntroducer Introducer,
3025 Token &Tok) {
3026 PP.Lex(Tok);
3027
3028 if (Tok.isNot(tok::l_paren)) {
3029 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3030 << "intrinsic";
3031 return;
3032 }
3033 PP.Lex(Tok);
3034
3035 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3036
3037 while (Tok.is(tok::identifier)) {
3038 IdentifierInfo *II = Tok.getIdentifierInfo();
3039 if (!II->getBuiltinID())
3040 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3041 << II << SuggestIntrinH;
3042
3043 PP.Lex(Tok);
3044 if (Tok.isNot(tok::comma))
3045 break;
3046 PP.Lex(Tok);
3047 }
3048
3049 if (Tok.isNot(tok::r_paren)) {
3050 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3051 << "intrinsic";
3052 return;
3053 }
3054 PP.Lex(Tok);
3055
3056 if (Tok.isNot(tok::eod))
3057 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3058 << "intrinsic";
3059 }
3060
3061 // #pragma optimize("gsty", on|off)
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3062 void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
3063 PragmaIntroducer Introducer,
3064 Token &Tok) {
3065 SourceLocation StartLoc = Tok.getLocation();
3066 PP.Lex(Tok);
3067
3068 if (Tok.isNot(tok::l_paren)) {
3069 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
3070 return;
3071 }
3072 PP.Lex(Tok);
3073
3074 if (Tok.isNot(tok::string_literal)) {
3075 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
3076 return;
3077 }
3078 // We could syntax check the string but it's probably not worth the effort.
3079 PP.Lex(Tok);
3080
3081 if (Tok.isNot(tok::comma)) {
3082 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
3083 return;
3084 }
3085 PP.Lex(Tok);
3086
3087 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
3088 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
3089 << "optimize" << /*Expected=*/true << "'on' or 'off'";
3090 return;
3091 }
3092 IdentifierInfo *II = Tok.getIdentifierInfo();
3093 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3094 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3095 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
3096 << "'on' or 'off'";
3097 return;
3098 }
3099 PP.Lex(Tok);
3100
3101 if (Tok.isNot(tok::r_paren)) {
3102 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3103 return;
3104 }
3105 PP.Lex(Tok);
3106
3107 if (Tok.isNot(tok::eod)) {
3108 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3109 << "optimize";
3110 return;
3111 }
3112 PP.Diag(StartLoc, diag::warn_pragma_optimize);
3113 }
3114
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3115 void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3116 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3117 Token FirstTok = Tok;
3118
3119 PP.Lex(Tok);
3120 IdentifierInfo *Info = Tok.getIdentifierInfo();
3121 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3122 PP.Diag(FirstTok.getLocation(),
3123 diag::warn_pragma_force_cuda_host_device_bad_arg);
3124 return;
3125 }
3126
3127 if (Info->isStr("begin"))
3128 Actions.PushForceCUDAHostDevice();
3129 else if (!Actions.PopForceCUDAHostDevice())
3130 PP.Diag(FirstTok.getLocation(),
3131 diag::err_pragma_cannot_end_force_cuda_host_device);
3132
3133 PP.Lex(Tok);
3134 if (!Tok.is(tok::eod))
3135 PP.Diag(FirstTok.getLocation(),
3136 diag::warn_pragma_force_cuda_host_device_bad_arg);
3137 }
3138
3139 /// Handle the #pragma clang attribute directive.
3140 ///
3141 /// The syntax is:
3142 /// \code
3143 /// #pragma clang attribute push (attribute, subject-set)
3144 /// #pragma clang attribute push
3145 /// #pragma clang attribute (attribute, subject-set)
3146 /// #pragma clang attribute pop
3147 /// \endcode
3148 ///
3149 /// There are also 'namespace' variants of push and pop directives. The bare
3150 /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3151 /// namespace, since it always applies attributes to the most recently pushed
3152 /// group, regardless of namespace.
3153 /// \code
3154 /// #pragma clang attribute namespace.push (attribute, subject-set)
3155 /// #pragma clang attribute namespace.push
3156 /// #pragma clang attribute namespace.pop
3157 /// \endcode
3158 ///
3159 /// The subject-set clause defines the set of declarations which receive the
3160 /// attribute. Its exact syntax is described in the LanguageExtensions document
3161 /// in Clang's documentation.
3162 ///
3163 /// This directive instructs the compiler to begin/finish applying the specified
3164 /// attribute to the set of attribute-specific declarations in the active range
3165 /// of the pragma.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3166 void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3167 PragmaIntroducer Introducer,
3168 Token &FirstToken) {
3169 Token Tok;
3170 PP.Lex(Tok);
3171 auto *Info = new (PP.getPreprocessorAllocator())
3172 PragmaAttributeInfo(AttributesForPragmaAttribute);
3173
3174 // Parse the optional namespace followed by a period.
3175 if (Tok.is(tok::identifier)) {
3176 IdentifierInfo *II = Tok.getIdentifierInfo();
3177 if (!II->isStr("push") && !II->isStr("pop")) {
3178 Info->Namespace = II;
3179 PP.Lex(Tok);
3180
3181 if (!Tok.is(tok::period)) {
3182 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3183 << II;
3184 return;
3185 }
3186 PP.Lex(Tok);
3187 }
3188 }
3189
3190 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3191 PP.Diag(Tok.getLocation(),
3192 diag::err_pragma_attribute_expected_push_pop_paren);
3193 return;
3194 }
3195
3196 // Determine what action this pragma clang attribute represents.
3197 if (Tok.is(tok::l_paren)) {
3198 if (Info->Namespace) {
3199 PP.Diag(Tok.getLocation(),
3200 diag::err_pragma_attribute_namespace_on_attribute);
3201 PP.Diag(Tok.getLocation(),
3202 diag::note_pragma_attribute_namespace_on_attribute);
3203 return;
3204 }
3205 Info->Action = PragmaAttributeInfo::Attribute;
3206 } else {
3207 const IdentifierInfo *II = Tok.getIdentifierInfo();
3208 if (II->isStr("push"))
3209 Info->Action = PragmaAttributeInfo::Push;
3210 else if (II->isStr("pop"))
3211 Info->Action = PragmaAttributeInfo::Pop;
3212 else {
3213 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3214 << PP.getSpelling(Tok);
3215 return;
3216 }
3217
3218 PP.Lex(Tok);
3219 }
3220
3221 // Parse the actual attribute.
3222 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3223 Info->Action == PragmaAttributeInfo::Attribute) {
3224 if (Tok.isNot(tok::l_paren)) {
3225 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3226 return;
3227 }
3228 PP.Lex(Tok);
3229
3230 // Lex the attribute tokens.
3231 SmallVector<Token, 16> AttributeTokens;
3232 int OpenParens = 1;
3233 while (Tok.isNot(tok::eod)) {
3234 if (Tok.is(tok::l_paren))
3235 OpenParens++;
3236 else if (Tok.is(tok::r_paren)) {
3237 OpenParens--;
3238 if (OpenParens == 0)
3239 break;
3240 }
3241
3242 AttributeTokens.push_back(Tok);
3243 PP.Lex(Tok);
3244 }
3245
3246 if (AttributeTokens.empty()) {
3247 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3248 return;
3249 }
3250 if (Tok.isNot(tok::r_paren)) {
3251 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3252 return;
3253 }
3254 SourceLocation EndLoc = Tok.getLocation();
3255 PP.Lex(Tok);
3256
3257 // Terminate the attribute for parsing.
3258 Token EOFTok;
3259 EOFTok.startToken();
3260 EOFTok.setKind(tok::eof);
3261 EOFTok.setLocation(EndLoc);
3262 AttributeTokens.push_back(EOFTok);
3263
3264 Info->Tokens =
3265 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3266 }
3267
3268 if (Tok.isNot(tok::eod))
3269 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3270 << "clang attribute";
3271
3272 // Generate the annotated pragma token.
3273 auto TokenArray = std::make_unique<Token[]>(1);
3274 TokenArray[0].startToken();
3275 TokenArray[0].setKind(tok::annot_pragma_attribute);
3276 TokenArray[0].setLocation(FirstToken.getLocation());
3277 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3278 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3279 PP.EnterTokenStream(std::move(TokenArray), 1,
3280 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3281 }
3282