blob: e815ea1355100e34870d6ca327964b1ddd479ad9 [file] [log] [blame]
Daniel Dunbar921b9682008-10-04 19:21:03 +00001//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the language specific #pragma handlers.
11//
12//===----------------------------------------------------------------------===//
13
Hans Wennborg899ded92014-10-16 20:52:46 +000014#include "clang/AST/ASTContext.h"
Nico Weber66220292016-03-02 17:28:48 +000015#include "clang/Basic/PragmaKinds.h"
David Majnemerad2986e2014-08-14 06:35:08 +000016#include "clang/Basic/TargetInfo.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000017#include "clang/Lex/Preprocessor.h"
18#include "clang/Parse/ParseDiagnostic.h"
19#include "clang/Parse/Parser.h"
Vassil Vassilev11ad3392017-03-23 15:11:07 +000020#include "clang/Parse/RAIIObjectsForParser.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000021#include "clang/Sema/LoopHint.h"
22#include "clang/Sema/Scope.h"
23#include "llvm/ADT/StringSwitch.h"
24using namespace clang;
Daniel Dunbar921b9682008-10-04 19:21:03 +000025
Reid Kleckner5b086462014-02-20 22:52:09 +000026namespace {
27
28struct PragmaAlignHandler : public PragmaHandler {
29 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000030 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
31 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000032};
33
34struct PragmaGCCVisibilityHandler : public PragmaHandler {
35 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000036 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
37 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000038};
39
40struct PragmaOptionsHandler : public PragmaHandler {
41 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000042 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
43 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000044};
45
46struct PragmaPackHandler : public PragmaHandler {
47 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000048 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
49 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000050};
51
Javed Absar2a67c9e2017-06-05 10:11:57 +000052struct PragmaClangSectionHandler : public PragmaHandler {
53 explicit PragmaClangSectionHandler(Sema &S)
54 : PragmaHandler("section"), Actions(S) {}
55 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
56 Token &FirstToken) override;
57private:
58 Sema &Actions;
59};
60
Reid Kleckner5b086462014-02-20 22:52:09 +000061struct PragmaMSStructHandler : public PragmaHandler {
62 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000063 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
64 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000065};
66
67struct PragmaUnusedHandler : public PragmaHandler {
68 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000069 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
70 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000071};
72
73struct PragmaWeakHandler : public PragmaHandler {
74 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000075 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
76 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000077};
78
79struct PragmaRedefineExtnameHandler : public PragmaHandler {
80 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000081 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
82 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000083};
84
85struct PragmaOpenCLExtensionHandler : public PragmaHandler {
86 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000087 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
88 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000089};
90
91
92struct PragmaFPContractHandler : public PragmaHandler {
93 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000094 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
95 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000096};
97
Steven Wub96a3a42018-01-05 22:45:03 +000098// Pragma STDC implementations.
99
100/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
101struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
102 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
103
104 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind 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
114/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
115struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
116 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
117
118 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
119 Token &Tok) override {
120 tok::OnOffSwitch OOS;
121 PP.LexOnOffSwitch(OOS);
122 }
123};
124
125/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
126struct PragmaSTDC_UnknownHandler : public PragmaHandler {
127 PragmaSTDC_UnknownHandler() = default;
128
129 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
130 Token &UnknownTok) override {
131 // C99 6.10.6p2, unknown forms are not allowed.
132 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
133 }
134};
135
Adam Nemet60d32642017-04-04 21:18:36 +0000136struct PragmaFPHandler : public PragmaHandler {
137 PragmaFPHandler() : PragmaHandler("fp") {}
138 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
139 Token &FirstToken) override;
140};
141
Reid Kleckner5b086462014-02-20 22:52:09 +0000142struct PragmaNoOpenMPHandler : public PragmaHandler {
143 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +0000144 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
145 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000146};
147
148struct PragmaOpenMPHandler : public PragmaHandler {
149 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +0000150 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
151 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000152};
153
154/// PragmaCommentHandler - "\#pragma comment ...".
155struct PragmaCommentHandler : public PragmaHandler {
156 PragmaCommentHandler(Sema &Actions)
157 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000158 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
159 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000160private:
161 Sema &Actions;
162};
163
164struct PragmaDetectMismatchHandler : public PragmaHandler {
165 PragmaDetectMismatchHandler(Sema &Actions)
166 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000167 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
168 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000169private:
170 Sema &Actions;
171};
172
173struct PragmaMSPointersToMembers : public PragmaHandler {
174 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000175 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
176 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000177};
178
179struct PragmaMSVtorDisp : public PragmaHandler {
180 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000181 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
182 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000183};
184
Warren Huntc3b18962014-04-08 22:30:47 +0000185struct PragmaMSPragma : public PragmaHandler {
186 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000187 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
188 Token &FirstToken) override;
189};
190
Dario Domizioli13a0a382014-05-23 12:13:25 +0000191/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
192struct PragmaOptimizeHandler : public PragmaHandler {
193 PragmaOptimizeHandler(Sema &S)
194 : PragmaHandler("optimize"), Actions(S) {}
195 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
196 Token &FirstToken) override;
197private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000198 Sema &Actions;
199};
200
201struct PragmaLoopHintHandler : public PragmaHandler {
202 PragmaLoopHintHandler() : PragmaHandler("loop") {}
203 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
204 Token &FirstToken) override;
205};
206
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000207struct PragmaUnrollHintHandler : public PragmaHandler {
208 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
209 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
210 Token &FirstToken) override;
211};
212
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000213struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
214 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
215};
216
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000217struct PragmaMSIntrinsicHandler : public PragmaHandler {
218 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
219 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
220 Token &FirstToken) override;
221};
222
Justin Lebar67a78a62016-10-08 22:15:58 +0000223struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
224 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
225 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
226 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
227 Token &FirstToken) override;
228
229private:
230 Sema &Actions;
231};
232
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000233/// PragmaAttributeHandler - "\#pragma clang attribute ...".
234struct PragmaAttributeHandler : public PragmaHandler {
235 PragmaAttributeHandler(AttributeFactory &AttrFactory)
236 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
237 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
238 Token &FirstToken) override;
239
240 /// A pool of attributes that were parsed in \#pragma clang attribute.
241 ParsedAttributes AttributesForPragmaAttribute;
242};
243
Eli Bendersky06a40422014-06-06 20:31:48 +0000244} // end namespace
245
246void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000247 AlignHandler.reset(new PragmaAlignHandler());
248 PP.AddPragmaHandler(AlignHandler.get());
249
250 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
251 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
252
253 OptionsHandler.reset(new PragmaOptionsHandler());
254 PP.AddPragmaHandler(OptionsHandler.get());
255
256 PackHandler.reset(new PragmaPackHandler());
257 PP.AddPragmaHandler(PackHandler.get());
258
259 MSStructHandler.reset(new PragmaMSStructHandler());
260 PP.AddPragmaHandler(MSStructHandler.get());
261
262 UnusedHandler.reset(new PragmaUnusedHandler());
263 PP.AddPragmaHandler(UnusedHandler.get());
264
265 WeakHandler.reset(new PragmaWeakHandler());
266 PP.AddPragmaHandler(WeakHandler.get());
267
268 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
269 PP.AddPragmaHandler(RedefineExtnameHandler.get());
270
271 FPContractHandler.reset(new PragmaFPContractHandler());
272 PP.AddPragmaHandler("STDC", FPContractHandler.get());
273
Steven Wub96a3a42018-01-05 22:45:03 +0000274 STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler());
275 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
276
277 STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler());
278 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
279
280 STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler());
281 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
282
Javed Absar2a67c9e2017-06-05 10:11:57 +0000283 PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
284 PP.AddPragmaHandler("clang", PCSectionHandler.get());
285
Reid Kleckner5b086462014-02-20 22:52:09 +0000286 if (getLangOpts().OpenCL) {
287 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
288 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
289
290 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
291 }
292 if (getLangOpts().OpenMP)
293 OpenMPHandler.reset(new PragmaOpenMPHandler());
294 else
295 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
296 PP.AddPragmaHandler(OpenMPHandler.get());
297
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000298 if (getLangOpts().MicrosoftExt ||
299 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000300 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
301 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000302 }
303
304 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000305 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
306 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
307 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
308 PP.AddPragmaHandler(MSPointersToMembers.get());
309 MSVtorDisp.reset(new PragmaMSVtorDisp());
310 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000311 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000312 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000313 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
314 PP.AddPragmaHandler(MSDataSeg.get());
315 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
316 PP.AddPragmaHandler(MSBSSSeg.get());
317 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
318 PP.AddPragmaHandler(MSConstSeg.get());
319 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
320 PP.AddPragmaHandler(MSCodeSeg.get());
321 MSSection.reset(new PragmaMSPragma("section"));
322 PP.AddPragmaHandler(MSSection.get());
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000323 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
324 PP.AddPragmaHandler(MSRuntimeChecks.get());
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000325 MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
326 PP.AddPragmaHandler(MSIntrinsic.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000327 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000328
Justin Lebar67a78a62016-10-08 22:15:58 +0000329 if (getLangOpts().CUDA) {
330 CUDAForceHostDeviceHandler.reset(
331 new PragmaForceCUDAHostDeviceHandler(Actions));
332 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
333 }
334
Eli Bendersky06a40422014-06-06 20:31:48 +0000335 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
336 PP.AddPragmaHandler("clang", OptimizeHandler.get());
337
338 LoopHintHandler.reset(new PragmaLoopHintHandler());
339 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000340
341 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
342 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000343
344 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
345 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000346
347 FPHandler.reset(new PragmaFPHandler());
348 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000349
350 AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
351 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000352}
353
354void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000355 // Remove the pragma handlers we installed.
356 PP.RemovePragmaHandler(AlignHandler.get());
357 AlignHandler.reset();
358 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
359 GCCVisibilityHandler.reset();
360 PP.RemovePragmaHandler(OptionsHandler.get());
361 OptionsHandler.reset();
362 PP.RemovePragmaHandler(PackHandler.get());
363 PackHandler.reset();
364 PP.RemovePragmaHandler(MSStructHandler.get());
365 MSStructHandler.reset();
366 PP.RemovePragmaHandler(UnusedHandler.get());
367 UnusedHandler.reset();
368 PP.RemovePragmaHandler(WeakHandler.get());
369 WeakHandler.reset();
370 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
371 RedefineExtnameHandler.reset();
372
373 if (getLangOpts().OpenCL) {
374 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
375 OpenCLExtensionHandler.reset();
376 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
377 }
378 PP.RemovePragmaHandler(OpenMPHandler.get());
379 OpenMPHandler.reset();
380
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000381 if (getLangOpts().MicrosoftExt ||
382 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000383 PP.RemovePragmaHandler(MSCommentHandler.get());
384 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000385 }
386
Javed Absar2a67c9e2017-06-05 10:11:57 +0000387 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
388 PCSectionHandler.reset();
389
Yunzhong Gao99efc032015-03-23 20:41:42 +0000390 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000391 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
392 MSDetectMismatchHandler.reset();
393 PP.RemovePragmaHandler(MSPointersToMembers.get());
394 MSPointersToMembers.reset();
395 PP.RemovePragmaHandler(MSVtorDisp.get());
396 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000397 PP.RemovePragmaHandler(MSInitSeg.get());
398 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000399 PP.RemovePragmaHandler(MSDataSeg.get());
400 MSDataSeg.reset();
401 PP.RemovePragmaHandler(MSBSSSeg.get());
402 MSBSSSeg.reset();
403 PP.RemovePragmaHandler(MSConstSeg.get());
404 MSConstSeg.reset();
405 PP.RemovePragmaHandler(MSCodeSeg.get());
406 MSCodeSeg.reset();
407 PP.RemovePragmaHandler(MSSection.get());
408 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000409 PP.RemovePragmaHandler(MSRuntimeChecks.get());
410 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000411 PP.RemovePragmaHandler(MSIntrinsic.get());
412 MSIntrinsic.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000413 }
414
Justin Lebar67a78a62016-10-08 22:15:58 +0000415 if (getLangOpts().CUDA) {
416 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
417 CUDAForceHostDeviceHandler.reset();
418 }
419
Reid Kleckner5b086462014-02-20 22:52:09 +0000420 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
421 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000422
Steven Wub96a3a42018-01-05 22:45:03 +0000423 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
424 STDCFENVHandler.reset();
425
426 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
427 STDCCXLIMITHandler.reset();
428
429 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
430 STDCUnknownHandler.reset();
431
Eli Bendersky06a40422014-06-06 20:31:48 +0000432 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
433 OptimizeHandler.reset();
434
435 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
436 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000437
438 PP.RemovePragmaHandler(UnrollHintHandler.get());
439 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000440
441 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
442 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000443
444 PP.RemovePragmaHandler("clang", FPHandler.get());
445 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000446
447 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
448 AttributePragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000449}
450
451/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000452///
453/// Each annot_pragma_unused is followed by the argument token so e.g.
454/// "#pragma unused(x,y)" becomes:
455/// annot_pragma_unused 'x' annot_pragma_unused 'y'
456void Parser::HandlePragmaUnused() {
457 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000458 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000459 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
460 ConsumeToken(); // The argument token.
461}
Eli Friedman570024a2010-08-05 06:57:20 +0000462
Rafael Espindola273fd772012-01-26 02:02:57 +0000463void Parser::HandlePragmaVisibility() {
464 assert(Tok.is(tok::annot_pragma_vis));
465 const IdentifierInfo *VisType =
466 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000467 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000468 Actions.ActOnPragmaVisibility(VisType, VisLoc);
469}
470
Benjamin Kramere003ca22015-10-28 13:54:16 +0000471namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000472struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000473 Sema::PragmaMsStackAction Action;
474 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000475 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000476};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000477} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000478
479void Parser::HandlePragmaPack() {
480 assert(Tok.is(tok::annot_pragma_pack));
481 PragmaPackInfo *Info =
482 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000483 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000484 ExprResult Alignment;
485 if (Info->Alignment.is(tok::numeric_constant)) {
486 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000487 if (Alignment.isInvalid()) {
488 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000489 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000490 }
Eli Friedman68be1642012-10-04 02:36:51 +0000491 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000492 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
493 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000494 // Consume the token after processing the pragma to enable pragma-specific
495 // #include warnings.
496 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000497}
498
Eli Friedman68be1642012-10-04 02:36:51 +0000499void Parser::HandlePragmaMSStruct() {
500 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000501 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
502 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000503 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000504 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000505}
506
507void Parser::HandlePragmaAlign() {
508 assert(Tok.is(tok::annot_pragma_align));
509 Sema::PragmaOptionsAlignKind Kind =
510 static_cast<Sema::PragmaOptionsAlignKind>(
511 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Alex Lorenz692821a2018-02-08 21:20:43 +0000512 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
513 // Consume the token after processing the pragma to enable pragma-specific
514 // #include warnings.
515 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000516}
517
Richard Smithba3a4f92016-01-12 21:59:26 +0000518void Parser::HandlePragmaDump() {
519 assert(Tok.is(tok::annot_pragma_dump));
520 IdentifierInfo *II =
521 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
522 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000523 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000524}
525
Eli Friedman68be1642012-10-04 02:36:51 +0000526void Parser::HandlePragmaWeak() {
527 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000528 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000529 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
530 Tok.getLocation());
531 ConsumeToken(); // The weak name.
532}
533
534void Parser::HandlePragmaWeakAlias() {
535 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000536 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000537 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
538 SourceLocation WeakNameLoc = Tok.getLocation();
539 ConsumeToken();
540 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
541 SourceLocation AliasNameLoc = Tok.getLocation();
542 ConsumeToken();
543 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
544 WeakNameLoc, AliasNameLoc);
545
546}
547
548void Parser::HandlePragmaRedefineExtname() {
549 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000550 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000551 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
552 SourceLocation RedefNameLoc = Tok.getLocation();
553 ConsumeToken();
554 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
555 SourceLocation AliasNameLoc = Tok.getLocation();
556 ConsumeToken();
557 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
558 RedefNameLoc, AliasNameLoc);
559}
560
561void Parser::HandlePragmaFPContract() {
562 assert(Tok.is(tok::annot_pragma_fp_contract));
563 tok::OnOffSwitch OOS =
564 static_cast<tok::OnOffSwitch>(
565 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000566
567 LangOptions::FPContractModeKind FPC;
568 switch (OOS) {
569 case tok::OOS_ON:
570 FPC = LangOptions::FPC_On;
571 break;
572 case tok::OOS_OFF:
573 FPC = LangOptions::FPC_Off;
574 break;
575 case tok::OOS_DEFAULT:
576 FPC = getLangOpts().getDefaultFPContractMode();
577 break;
578 }
579
580 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000581 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000582}
583
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000584StmtResult Parser::HandlePragmaCaptured()
585{
586 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000587 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000588
589 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000590 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000591 return StmtError();
592 }
593
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000594 SourceLocation Loc = Tok.getLocation();
595
Momchil Velikov57c681f2017-08-10 15:43:06 +0000596 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
597 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000598 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
599 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000600
601 StmtResult R = ParseCompoundStatement();
602 CapturedRegionScope.Exit();
603
604 if (R.isInvalid()) {
605 Actions.ActOnCapturedRegionError();
606 return StmtError();
607 }
608
609 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000610}
611
Eli Friedman68be1642012-10-04 02:36:51 +0000612namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000613 enum OpenCLExtState : char {
614 Disable, Enable, Begin, End
615 };
616 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000617}
618
619void Parser::HandlePragmaOpenCLExtension() {
620 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000621 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
622 auto State = Data->second;
623 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000624 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000625 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000626
Yaxun Liu5b746652016-12-18 05:18:55 +0000627 auto &Opt = Actions.getOpenCLOptions();
628 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000629 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
630 // overriding all previously issued extension directives, but only if the
631 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000632 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000633 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000634 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000635 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
636 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000637 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000638 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000639 } else if (State == Begin) {
640 if (!Opt.isKnown(Name) ||
641 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
642 Opt.support(Name);
643 }
644 Actions.setCurrentOpenCLExtension(Name);
645 } else if (State == End) {
646 if (Name != Actions.getCurrentOpenCLExtension())
647 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
648 Actions.setCurrentOpenCLExtension("");
649 } else if (!Opt.isKnown(Name))
650 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
651 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
652 Opt.enable(Name, State == Enable);
653 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
654 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
655 else
656 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000657}
658
David Majnemer4bb09802014-02-10 19:50:15 +0000659void Parser::HandlePragmaMSPointersToMembers() {
660 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000661 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
662 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000663 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000664 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000665 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
666}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000667
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000668void Parser::HandlePragmaMSVtorDisp() {
669 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
670 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000671 Sema::PragmaMsStackAction Action =
672 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000673 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000674 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000675 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000676}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000677
Warren Huntc3b18962014-04-08 22:30:47 +0000678void Parser::HandlePragmaMSPragma() {
679 assert(Tok.is(tok::annot_pragma_ms_pragma));
680 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000681 auto TheTokens =
682 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
683 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000684 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000685 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000686 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000687 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000688
Warren Huntc3b18962014-04-08 22:30:47 +0000689 // Figure out which #pragma we're dealing with. The switch has no default
690 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000691 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000692 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
693 .Case("data_seg", &Parser::HandlePragmaMSSegment)
694 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
695 .Case("const_seg", &Parser::HandlePragmaMSSegment)
696 .Case("code_seg", &Parser::HandlePragmaMSSegment)
697 .Case("section", &Parser::HandlePragmaMSSection)
698 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000699
700 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
701 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
702 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000703 while (Tok.isNot(tok::eof))
704 PP.Lex(Tok);
705 PP.Lex(Tok);
706 }
707}
708
Reid Kleckner722b1df2014-07-18 00:13:16 +0000709bool Parser::HandlePragmaMSSection(StringRef PragmaName,
710 SourceLocation PragmaLocation) {
711 if (Tok.isNot(tok::l_paren)) {
712 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
713 return false;
714 }
Warren Huntc3b18962014-04-08 22:30:47 +0000715 PP.Lex(Tok); // (
716 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000717 if (Tok.isNot(tok::string_literal)) {
718 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
719 << PragmaName;
720 return false;
721 }
722 ExprResult StringResult = ParseStringLiteralExpression();
723 if (StringResult.isInvalid())
724 return false; // Already diagnosed.
725 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
726 if (SegmentName->getCharByteWidth() != 1) {
727 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
728 << PragmaName;
729 return false;
730 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000731 int SectionFlags = ASTContext::PSF_Read;
732 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000733 while (Tok.is(tok::comma)) {
734 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000735 // Ignore "long" and "short".
736 // They are undocumented, but widely used, section attributes which appear
737 // to do nothing.
738 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
739 PP.Lex(Tok); // long/short
740 continue;
741 }
742
Reid Kleckner722b1df2014-07-18 00:13:16 +0000743 if (!Tok.isAnyIdentifier()) {
744 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
745 << PragmaName;
746 return false;
747 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000748 ASTContext::PragmaSectionFlag Flag =
749 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000750 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000751 .Case("read", ASTContext::PSF_Read)
752 .Case("write", ASTContext::PSF_Write)
753 .Case("execute", ASTContext::PSF_Execute)
754 .Case("shared", ASTContext::PSF_Invalid)
755 .Case("nopage", ASTContext::PSF_Invalid)
756 .Case("nocache", ASTContext::PSF_Invalid)
757 .Case("discard", ASTContext::PSF_Invalid)
758 .Case("remove", ASTContext::PSF_Invalid)
759 .Default(ASTContext::PSF_None);
760 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
761 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000762 ? diag::warn_pragma_invalid_specific_action
763 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000764 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000765 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000766 }
767 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000768 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000769 PP.Lex(Tok); // Identifier
770 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000771 // If no section attributes are specified, the section will be marked as
772 // read/write.
773 if (SectionFlagsAreDefault)
774 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000775 if (Tok.isNot(tok::r_paren)) {
776 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
777 return false;
778 }
Warren Huntc3b18962014-04-08 22:30:47 +0000779 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000780 if (Tok.isNot(tok::eof)) {
781 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
782 << PragmaName;
783 return false;
784 }
Warren Huntc3b18962014-04-08 22:30:47 +0000785 PP.Lex(Tok); // eof
786 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000787 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000788}
789
Reid Kleckner722b1df2014-07-18 00:13:16 +0000790bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
791 SourceLocation PragmaLocation) {
792 if (Tok.isNot(tok::l_paren)) {
793 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
794 return false;
795 }
Warren Huntc3b18962014-04-08 22:30:47 +0000796 PP.Lex(Tok); // (
797 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000798 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000799 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000800 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000801 if (PushPop == "push")
802 Action = Sema::PSK_Push;
803 else if (PushPop == "pop")
804 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000805 else {
806 PP.Diag(PragmaLocation,
807 diag::warn_pragma_expected_section_push_pop_or_name)
808 << PragmaName;
809 return false;
810 }
Warren Huntc3b18962014-04-08 22:30:47 +0000811 if (Action != Sema::PSK_Reset) {
812 PP.Lex(Tok); // push | pop
813 if (Tok.is(tok::comma)) {
814 PP.Lex(Tok); // ,
815 // If we've got a comma, we either need a label or a string.
816 if (Tok.isAnyIdentifier()) {
817 SlotLabel = Tok.getIdentifierInfo()->getName();
818 PP.Lex(Tok); // identifier
819 if (Tok.is(tok::comma))
820 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000821 else if (Tok.isNot(tok::r_paren)) {
822 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
823 << PragmaName;
824 return false;
825 }
Warren Huntc3b18962014-04-08 22:30:47 +0000826 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000827 } else if (Tok.isNot(tok::r_paren)) {
828 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
829 return false;
830 }
Warren Huntc3b18962014-04-08 22:30:47 +0000831 }
832 }
833 // Grab the string literal for our section name.
834 StringLiteral *SegmentName = nullptr;
835 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000836 if (Tok.isNot(tok::string_literal)) {
837 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000838 diag::warn_pragma_expected_section_name :
839 diag::warn_pragma_expected_section_label_or_name :
840 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000841 PP.Diag(PragmaLocation, DiagID) << PragmaName;
842 return false;
843 }
844 ExprResult StringResult = ParseStringLiteralExpression();
845 if (StringResult.isInvalid())
846 return false; // Already diagnosed.
847 SegmentName = cast<StringLiteral>(StringResult.get());
848 if (SegmentName->getCharByteWidth() != 1) {
849 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
850 << PragmaName;
851 return false;
852 }
Warren Huntc3b18962014-04-08 22:30:47 +0000853 // Setting section "" has no effect
854 if (SegmentName->getLength())
855 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
856 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000857 if (Tok.isNot(tok::r_paren)) {
858 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
859 return false;
860 }
Warren Huntc3b18962014-04-08 22:30:47 +0000861 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000862 if (Tok.isNot(tok::eof)) {
863 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
864 << PragmaName;
865 return false;
866 }
Warren Huntc3b18962014-04-08 22:30:47 +0000867 PP.Lex(Tok); // eof
868 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
869 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000870 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000871}
872
Reid Kleckner1a711b12014-07-22 00:53:05 +0000873// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000874bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
875 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000876 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
877 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
878 return false;
879 }
880
Reid Kleckner1a711b12014-07-22 00:53:05 +0000881 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
882 PragmaName))
883 return false;
884
885 // Parse either the known section names or the string section name.
886 StringLiteral *SegmentName = nullptr;
887 if (Tok.isAnyIdentifier()) {
888 auto *II = Tok.getIdentifierInfo();
889 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
890 .Case("compiler", "\".CRT$XCC\"")
891 .Case("lib", "\".CRT$XCL\"")
892 .Case("user", "\".CRT$XCU\"")
893 .Default("");
894
895 if (!Section.empty()) {
896 // Pretend the user wrote the appropriate string literal here.
897 Token Toks[1];
898 Toks[0].startToken();
899 Toks[0].setKind(tok::string_literal);
900 Toks[0].setLocation(Tok.getLocation());
901 Toks[0].setLiteralData(Section.data());
902 Toks[0].setLength(Section.size());
903 SegmentName =
904 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
905 PP.Lex(Tok);
906 }
907 } else if (Tok.is(tok::string_literal)) {
908 ExprResult StringResult = ParseStringLiteralExpression();
909 if (StringResult.isInvalid())
910 return false;
911 SegmentName = cast<StringLiteral>(StringResult.get());
912 if (SegmentName->getCharByteWidth() != 1) {
913 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
914 << PragmaName;
915 return false;
916 }
917 // FIXME: Add support for the '[, func-name]' part of the pragma.
918 }
919
920 if (!SegmentName) {
921 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
922 return false;
923 }
924
925 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
926 PragmaName) ||
927 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
928 PragmaName))
929 return false;
930
931 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
932 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000933}
934
Benjamin Kramere003ca22015-10-28 13:54:16 +0000935namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000936struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000937 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000938 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000939 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000940};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000941} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000942
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000943static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
944 std::string PragmaString;
945 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
946 PragmaString = "clang loop ";
947 PragmaString += Option.getIdentifierInfo()->getName();
948 } else {
949 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
950 "Unexpected pragma name");
951 PragmaString = "unroll";
952 }
953 return PragmaString;
954}
955
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000956bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000957 assert(Tok.is(tok::annot_pragma_loop_hint));
958 PragmaLoopHintInfo *Info =
959 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
960
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000961 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
962 Hint.PragmaNameLoc = IdentifierLoc::create(
963 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000964
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000965 // It is possible that the loop hint has no option identifier, such as
966 // #pragma unroll(4).
967 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
968 ? Info->Option.getIdentifierInfo()
969 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000970 Hint.OptionLoc = IdentifierLoc::create(
971 Actions.Context, Info->Option.getLocation(), OptionInfo);
972
David Blaikie2eabcc92016-02-09 18:52:09 +0000973 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000974
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000975 // Return a valid hint if pragma unroll or nounroll were specified
976 // without an argument.
977 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
978 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000979 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000980 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000981 Hint.Range = Info->PragmaName.getLocation();
982 return true;
983 }
984
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000985 // The constant expression is always followed by an eof token, which increases
986 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000987 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000988 "PragmaLoopHintInfo::Toks must contain at least one token.");
989
990 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +0000991 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +0000992 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000993 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +0000994 if (OptionInfo) { // Pragma Unroll does not specify an option.
995 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +0000996 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000997 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
998 .Case("vectorize", true)
999 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00001000 .Default(false) ||
1001 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001002 }
1003
Adam Nemet2de463e2016-06-14 12:04:26 +00001004 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001005 // Verify loop hint has an argument.
1006 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001007 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001008 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +00001009 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
1010 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001011 return false;
1012 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001013
1014 // Validate the argument.
1015 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001016 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001017 SourceLocation StateLoc = Toks[0].getLocation();
1018 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001019
1020 bool Valid = StateInfo &&
1021 llvm::StringSwitch<bool>(StateInfo->getName())
1022 .Cases("enable", "disable", true)
1023 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +00001024 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +00001025 .Default(false);
1026 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001027 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +00001028 << /*FullKeyword=*/OptionUnroll
1029 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001030 return false;
1031 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001032 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001033 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1034 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001035 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1036 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001037 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +00001038 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001039 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001040
1041 ExprResult R = ParseConstantExpression();
1042
1043 // Tokens following an error in an ill-formed constant expression will
1044 // remain in the token stream and must be removed.
1045 if (Tok.isNot(tok::eof)) {
1046 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1047 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1048 while (Tok.isNot(tok::eof))
1049 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001050 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001051
1052 ConsumeToken(); // Consume the constant expression eof terminator.
1053
1054 if (R.isInvalid() ||
1055 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1056 return false;
1057
1058 // Argument is a constant expression with an integer type.
1059 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001060 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001061
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001062 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001063 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001064 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001065}
1066
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001067namespace {
1068struct PragmaAttributeInfo {
1069 enum ActionType { Push, Pop };
1070 ParsedAttributes &Attributes;
1071 ActionType Action;
1072 ArrayRef<Token> Tokens;
1073
1074 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1075};
1076
1077#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1078
1079} // end anonymous namespace
1080
1081static StringRef getIdentifier(const Token &Tok) {
1082 if (Tok.is(tok::identifier))
1083 return Tok.getIdentifierInfo()->getName();
1084 const char *S = tok::getKeywordSpelling(Tok.getKind());
1085 if (!S)
1086 return "";
1087 return S;
1088}
1089
1090static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1091 using namespace attr;
1092 switch (Rule) {
1093#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1094 case Value: \
1095 return IsAbstract;
1096#include "clang/Basic/AttrSubMatchRulesList.inc"
1097 }
1098 llvm_unreachable("Invalid attribute subject match rule");
1099 return false;
1100}
1101
1102static void diagnoseExpectedAttributeSubjectSubRule(
1103 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1104 SourceLocation SubRuleLoc) {
1105 auto Diagnostic =
1106 PRef.Diag(SubRuleLoc,
1107 diag::err_pragma_attribute_expected_subject_sub_identifier)
1108 << PrimaryRuleName;
1109 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1110 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1111 else
1112 Diagnostic << /*SubRulesSupported=*/0;
1113}
1114
1115static void diagnoseUnknownAttributeSubjectSubRule(
1116 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1117 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1118
1119 auto Diagnostic =
1120 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1121 << SubRuleName << PrimaryRuleName;
1122 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1123 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1124 else
1125 Diagnostic << /*SubRulesSupported=*/0;
1126}
1127
1128bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1129 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1130 SourceLocation &LastMatchRuleEndLoc) {
1131 bool IsAny = false;
1132 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1133 if (getIdentifier(Tok) == "any") {
1134 AnyLoc = ConsumeToken();
1135 IsAny = true;
1136 if (AnyParens.expectAndConsume())
1137 return true;
1138 }
1139
1140 do {
1141 // Parse the subject matcher rule.
1142 StringRef Name = getIdentifier(Tok);
1143 if (Name.empty()) {
1144 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1145 return true;
1146 }
1147 std::pair<Optional<attr::SubjectMatchRule>,
1148 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1149 Rule = isAttributeSubjectMatchRule(Name);
1150 if (!Rule.first) {
1151 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1152 return true;
1153 }
1154 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1155 SourceLocation RuleLoc = ConsumeToken();
1156
1157 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1158 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1159 if (Parens.expectAndConsume())
1160 return true;
1161 } else if (Parens.consumeOpen()) {
1162 if (!SubjectMatchRules
1163 .insert(
1164 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1165 .second)
1166 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1167 << Name
1168 << FixItHint::CreateRemoval(SourceRange(
1169 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1170 LastMatchRuleEndLoc = RuleLoc;
1171 continue;
1172 }
1173
1174 // Parse the sub-rules.
1175 StringRef SubRuleName = getIdentifier(Tok);
1176 if (SubRuleName.empty()) {
1177 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1178 Tok.getLocation());
1179 return true;
1180 }
1181 attr::SubjectMatchRule SubRule;
1182 if (SubRuleName == "unless") {
1183 SourceLocation SubRuleLoc = ConsumeToken();
1184 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1185 if (Parens.expectAndConsume())
1186 return true;
1187 SubRuleName = getIdentifier(Tok);
1188 if (SubRuleName.empty()) {
1189 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1190 SubRuleLoc);
1191 return true;
1192 }
1193 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1194 if (!SubRuleOrNone) {
1195 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1196 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1197 SubRuleUnlessName, SubRuleLoc);
1198 return true;
1199 }
1200 SubRule = *SubRuleOrNone;
1201 ConsumeToken();
1202 if (Parens.consumeClose())
1203 return true;
1204 } else {
1205 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1206 if (!SubRuleOrNone) {
1207 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1208 SubRuleName, Tok.getLocation());
1209 return true;
1210 }
1211 SubRule = *SubRuleOrNone;
1212 ConsumeToken();
1213 }
1214 SourceLocation RuleEndLoc = Tok.getLocation();
1215 LastMatchRuleEndLoc = RuleEndLoc;
1216 if (Parens.consumeClose())
1217 return true;
1218 if (!SubjectMatchRules
1219 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1220 .second) {
1221 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1222 << attr::getSubjectMatchRuleSpelling(SubRule)
1223 << FixItHint::CreateRemoval(SourceRange(
1224 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1225 continue;
1226 }
1227 } while (IsAny && TryConsumeToken(tok::comma));
1228
1229 if (IsAny)
1230 if (AnyParens.consumeClose())
1231 return true;
1232
1233 return false;
1234}
1235
1236namespace {
1237
1238/// Describes the stage at which attribute subject rule parsing was interruped.
1239enum class MissingAttributeSubjectRulesRecoveryPoint {
1240 Comma,
1241 ApplyTo,
1242 Equals,
1243 Any,
1244 None,
1245};
1246
1247MissingAttributeSubjectRulesRecoveryPoint
1248getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1249 if (const auto *II = Tok.getIdentifierInfo()) {
1250 if (II->isStr("apply_to"))
1251 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1252 if (II->isStr("any"))
1253 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1254 }
1255 if (Tok.is(tok::equal))
1256 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1257 return MissingAttributeSubjectRulesRecoveryPoint::None;
1258}
1259
1260/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1261/// suggests the possible attribute subject rules in a fix-it together with
1262/// any other missing tokens.
1263DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1264 unsigned DiagID, AttributeList &Attribute,
1265 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1266 SourceLocation Loc = PRef.getEndOfPreviousToken();
1267 if (Loc.isInvalid())
1268 Loc = PRef.getCurToken().getLocation();
1269 auto Diagnostic = PRef.Diag(Loc, DiagID);
1270 std::string FixIt;
1271 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1272 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1273 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1274 FixIt = ", ";
1275 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1276 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1277 FixIt += "apply_to";
1278 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1279 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1280 FixIt += " = ";
1281 SourceRange FixItRange(Loc);
1282 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1283 // Gather the subject match rules that are supported by the attribute.
1284 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1285 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1286 if (SubjectMatchRuleSet.empty()) {
1287 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1288 // placeholders will be supported by the fix-its.
1289 return Diagnostic;
1290 }
1291 FixIt += "any(";
1292 bool NeedsComma = false;
1293 for (const auto &I : SubjectMatchRuleSet) {
1294 // Ensure that the missing rule is reported in the fix-it only when it's
1295 // supported in the current language mode.
1296 if (!I.second)
1297 continue;
1298 if (NeedsComma)
1299 FixIt += ", ";
1300 else
1301 NeedsComma = true;
1302 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1303 }
1304 FixIt += ")";
1305 // Check if we need to remove the range
1306 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1307 FixItRange.setEnd(PRef.getCurToken().getLocation());
1308 }
1309 if (FixItRange.getBegin() == FixItRange.getEnd())
1310 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1311 else
1312 Diagnostic << FixItHint::CreateReplacement(
1313 CharSourceRange::getCharRange(FixItRange), FixIt);
1314 return Diagnostic;
1315}
1316
1317} // end anonymous namespace
1318
1319void Parser::HandlePragmaAttribute() {
1320 assert(Tok.is(tok::annot_pragma_attribute) &&
1321 "Expected #pragma attribute annotation token");
1322 SourceLocation PragmaLoc = Tok.getLocation();
1323 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1324 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001325 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001326 Actions.ActOnPragmaAttributePop(PragmaLoc);
1327 return;
1328 }
1329 // Parse the actual attribute with its arguments.
1330 assert(Info->Action == PragmaAttributeInfo::Push &&
1331 "Unexpected #pragma attribute command");
1332 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001333 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001334
1335 ParsedAttributes &Attrs = Info->Attributes;
1336 Attrs.clearListOnly();
1337
1338 auto SkipToEnd = [this]() {
1339 SkipUntil(tok::eof, StopBeforeMatch);
1340 ConsumeToken();
1341 };
1342
1343 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1344 // Parse the CXX11 style attribute.
1345 ParseCXX11AttributeSpecifier(Attrs);
1346 } else if (Tok.is(tok::kw___attribute)) {
1347 ConsumeToken();
1348 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1349 "attribute"))
1350 return SkipToEnd();
1351 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1352 return SkipToEnd();
1353
1354 if (Tok.isNot(tok::identifier)) {
1355 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1356 SkipToEnd();
1357 return;
1358 }
1359 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1360 SourceLocation AttrNameLoc = ConsumeToken();
1361
1362 if (Tok.isNot(tok::l_paren))
1363 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1364 AttributeList::AS_GNU);
1365 else
1366 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1367 /*ScopeName=*/nullptr,
1368 /*ScopeLoc=*/SourceLocation(),
1369 AttributeList::AS_GNU,
1370 /*Declarator=*/nullptr);
1371
1372 if (ExpectAndConsume(tok::r_paren))
1373 return SkipToEnd();
1374 if (ExpectAndConsume(tok::r_paren))
1375 return SkipToEnd();
1376 } else if (Tok.is(tok::kw___declspec)) {
1377 ParseMicrosoftDeclSpecs(Attrs);
1378 } else {
1379 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1380 if (Tok.getIdentifierInfo()) {
1381 // If we suspect that this is an attribute suggest the use of
1382 // '__attribute__'.
1383 if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1384 AttributeList::AS_GNU) !=
1385 AttributeList::UnknownAttribute) {
1386 SourceLocation InsertStartLoc = Tok.getLocation();
1387 ConsumeToken();
1388 if (Tok.is(tok::l_paren)) {
1389 ConsumeAnyToken();
1390 SkipUntil(tok::r_paren, StopBeforeMatch);
1391 if (Tok.isNot(tok::r_paren))
1392 return SkipToEnd();
1393 }
1394 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1395 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1396 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1397 }
1398 }
1399 SkipToEnd();
1400 return;
1401 }
1402
1403 if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
1404 SkipToEnd();
1405 return;
1406 }
1407
1408 // Ensure that we don't have more than one attribute.
1409 if (Attrs.getList()->getNext()) {
1410 SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
1411 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1412 SkipToEnd();
1413 return;
1414 }
1415
1416 if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
1417 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1418 << Attrs.getList()->getName();
1419 SkipToEnd();
1420 return;
1421 }
1422 AttributeList &Attribute = *Attrs.getList();
1423
1424 // Parse the subject-list.
1425 if (!TryConsumeToken(tok::comma)) {
1426 createExpectedAttributeSubjectRulesTokenDiagnostic(
1427 diag::err_expected, Attribute,
1428 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1429 << tok::comma;
1430 SkipToEnd();
1431 return;
1432 }
1433
1434 if (Tok.isNot(tok::identifier)) {
1435 createExpectedAttributeSubjectRulesTokenDiagnostic(
1436 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1437 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1438 SkipToEnd();
1439 return;
1440 }
1441 const IdentifierInfo *II = Tok.getIdentifierInfo();
1442 if (!II->isStr("apply_to")) {
1443 createExpectedAttributeSubjectRulesTokenDiagnostic(
1444 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1445 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1446 SkipToEnd();
1447 return;
1448 }
1449 ConsumeToken();
1450
1451 if (!TryConsumeToken(tok::equal)) {
1452 createExpectedAttributeSubjectRulesTokenDiagnostic(
1453 diag::err_expected, Attribute,
1454 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1455 << tok::equal;
1456 SkipToEnd();
1457 return;
1458 }
1459
1460 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1461 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1462 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1463 LastMatchRuleEndLoc)) {
1464 SkipToEnd();
1465 return;
1466 }
1467
1468 // Tokens following an ill-formed attribute will remain in the token stream
1469 // and must be removed.
1470 if (Tok.isNot(tok::eof)) {
1471 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1472 SkipToEnd();
1473 return;
1474 }
1475
1476 // Consume the eof terminator token.
1477 ConsumeToken();
1478
1479 Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
1480 std::move(SubjectMatchRules));
1481}
1482
Eli Bendersky06a40422014-06-06 20:31:48 +00001483// #pragma GCC visibility comes in two variants:
1484// 'push' '(' [visibility] ')'
1485// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001486void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1487 PragmaIntroducerKind Introducer,
1488 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001489 SourceLocation VisLoc = VisTok.getLocation();
1490
1491 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001492 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001493
1494 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1495
Eli Friedman570024a2010-08-05 06:57:20 +00001496 const IdentifierInfo *VisType;
1497 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001498 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001499 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001500 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001501 if (Tok.isNot(tok::l_paren)) {
1502 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1503 << "visibility";
1504 return;
1505 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001506 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001507 VisType = Tok.getIdentifierInfo();
1508 if (!VisType) {
1509 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1510 << "visibility";
1511 return;
1512 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001513 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001514 if (Tok.isNot(tok::r_paren)) {
1515 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1516 << "visibility";
1517 return;
1518 }
1519 } else {
1520 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1521 << "visibility";
1522 return;
1523 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001524 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001525 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001526 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001527 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1528 << "visibility";
1529 return;
1530 }
1531
David Blaikie2eabcc92016-02-09 18:52:09 +00001532 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001533 Toks[0].startToken();
1534 Toks[0].setKind(tok::annot_pragma_vis);
1535 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001536 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001537 Toks[0].setAnnotationValue(
1538 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001539 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001540}
1541
Daniel Dunbar921b9682008-10-04 19:21:03 +00001542// #pragma pack(...) comes in the following delicious flavors:
1543// pack '(' [integer] ')'
1544// pack '(' 'show' ')'
1545// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001546void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1547 PragmaIntroducerKind Introducer,
1548 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001549 SourceLocation PackLoc = PackTok.getLocation();
1550
1551 Token Tok;
1552 PP.Lex(Tok);
1553 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001554 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001555 return;
1556 }
1557
Denis Zobnin10c4f452016-04-29 18:17:40 +00001558 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1559 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001560 Token Alignment;
1561 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001562 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001563 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001564 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001565
1566 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001567
1568 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1569 // the push/pop stack.
1570 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001571 Action =
1572 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001573 } else if (Tok.is(tok::identifier)) {
1574 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001575 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001576 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001577 PP.Lex(Tok);
1578 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001579 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001580 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001581 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001582 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001583 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001584 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001585 return;
Mike Stump11289f42009-09-09 15:08:12 +00001586 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001587 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001588
Daniel Dunbar921b9682008-10-04 19:21:03 +00001589 if (Tok.is(tok::comma)) {
1590 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001591
Daniel Dunbar921b9682008-10-04 19:21:03 +00001592 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001593 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001594 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001595
1596 PP.Lex(Tok);
1597 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001598 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001599 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001600
Daniel Dunbar921b9682008-10-04 19:21:03 +00001601 if (Tok.is(tok::comma)) {
1602 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001603
Daniel Dunbar921b9682008-10-04 19:21:03 +00001604 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001605 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001606 return;
1607 }
Mike Stump11289f42009-09-09 15:08:12 +00001608
Denis Zobnin10c4f452016-04-29 18:17:40 +00001609 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001610 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001611
1612 PP.Lex(Tok);
1613 }
1614 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001615 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001616 return;
1617 }
1618 }
1619 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001620 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001621 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1622 // the push/pop stack.
1623 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001624 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001625 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001626
1627 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001628 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001629 return;
1630 }
1631
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001632 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001633 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001634 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001635 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1636 return;
1637 }
1638
David Blaikie2eabcc92016-02-09 18:52:09 +00001639 PragmaPackInfo *Info =
1640 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001641 Info->Action = Action;
1642 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001643 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001644
David Blaikie2eabcc92016-02-09 18:52:09 +00001645 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1646 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001647 Toks[0].startToken();
1648 Toks[0].setKind(tok::annot_pragma_pack);
1649 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001650 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001651 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001652 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001653}
1654
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001655// #pragma ms_struct on
1656// #pragma ms_struct off
1657void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1658 PragmaIntroducerKind Introducer,
1659 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001660 PragmaMSStructKind Kind = PMSST_OFF;
1661
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001662 Token Tok;
1663 PP.Lex(Tok);
1664 if (Tok.isNot(tok::identifier)) {
1665 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1666 return;
1667 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001668 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001669 const IdentifierInfo *II = Tok.getIdentifierInfo();
1670 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001671 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001672 PP.Lex(Tok);
1673 }
1674 else if (II->isStr("off") || II->isStr("reset"))
1675 PP.Lex(Tok);
1676 else {
1677 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1678 return;
1679 }
1680
1681 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001682 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1683 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001684 return;
1685 }
Eli Friedman68be1642012-10-04 02:36:51 +00001686
David Blaikie2eabcc92016-02-09 18:52:09 +00001687 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1688 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001689 Toks[0].startToken();
1690 Toks[0].setKind(tok::annot_pragma_msstruct);
1691 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001692 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001693 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1694 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001695 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001696}
1697
Javed Absar2a67c9e2017-06-05 10:11:57 +00001698// #pragma clang section bss="abc" data="" rodata="def" text=""
1699void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1700 PragmaIntroducerKind Introducer, Token &FirstToken) {
1701
1702 Token Tok;
1703 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1704
1705 PP.Lex(Tok); // eat 'section'
1706 while (Tok.isNot(tok::eod)) {
1707 if (Tok.isNot(tok::identifier)) {
1708 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1709 return;
1710 }
1711
1712 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1713 if (SecType->isStr("bss"))
1714 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1715 else if (SecType->isStr("data"))
1716 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1717 else if (SecType->isStr("rodata"))
1718 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1719 else if (SecType->isStr("text"))
1720 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1721 else {
1722 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1723 return;
1724 }
1725
1726 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1727 if (Tok.isNot(tok::equal)) {
1728 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1729 return;
1730 }
1731
1732 std::string SecName;
1733 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1734 return;
1735
1736 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1737 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1738 Sema::PragmaClangSectionAction::PCSA_Clear),
1739 SecKind, SecName);
1740 }
1741}
1742
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001743// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1744// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001745static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001746 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001747 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001748
1749 if (IsOptions) {
1750 PP.Lex(Tok);
1751 if (Tok.isNot(tok::identifier) ||
1752 !Tok.getIdentifierInfo()->isStr("align")) {
1753 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1754 return;
1755 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001756 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001757
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001758 PP.Lex(Tok);
1759 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001760 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1761 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001762 return;
1763 }
1764
1765 PP.Lex(Tok);
1766 if (Tok.isNot(tok::identifier)) {
1767 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001768 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001769 return;
1770 }
1771
John McCallfaf5fb42010-08-26 23:41:50 +00001772 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001773 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001774 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001775 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001776 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001777 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001778 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001779 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001780 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001781 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001782 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001783 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001784 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001785 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001786 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001787 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1788 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001789 return;
1790 }
1791
David Majnemera8f2f1d2015-03-19 00:10:23 +00001792 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001793 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001794 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001795 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001796 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001797 return;
1798 }
1799
David Blaikie2eabcc92016-02-09 18:52:09 +00001800 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1801 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001802 Toks[0].startToken();
1803 Toks[0].setKind(tok::annot_pragma_align);
1804 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001805 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001806 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1807 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001808 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001809}
1810
Douglas Gregorc7d65762010-09-09 22:45:38 +00001811void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1812 PragmaIntroducerKind Introducer,
1813 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001814 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001815}
1816
Douglas Gregorc7d65762010-09-09 22:45:38 +00001817void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1818 PragmaIntroducerKind Introducer,
1819 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001820 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001821}
1822
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001823// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001824void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1825 PragmaIntroducerKind Introducer,
1826 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001827 // FIXME: Should we be expanding macros here? My guess is no.
1828 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001829
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001830 // Lex the left '('.
1831 Token Tok;
1832 PP.Lex(Tok);
1833 if (Tok.isNot(tok::l_paren)) {
1834 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1835 return;
1836 }
Mike Stump11289f42009-09-09 15:08:12 +00001837
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001838 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001839 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001840 SourceLocation RParenLoc;
1841 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001842
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001843 while (true) {
1844 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001845
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001846 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001847 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001848 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001849 LexID = false;
1850 continue;
1851 }
1852
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001853 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001854 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1855 return;
1856 }
Mike Stump11289f42009-09-09 15:08:12 +00001857
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001858 // We are execting a ')' or a ','.
1859 if (Tok.is(tok::comma)) {
1860 LexID = true;
1861 continue;
1862 }
Mike Stump11289f42009-09-09 15:08:12 +00001863
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001864 if (Tok.is(tok::r_paren)) {
1865 RParenLoc = Tok.getLocation();
1866 break;
1867 }
Mike Stump11289f42009-09-09 15:08:12 +00001868
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001869 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001870 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001871 return;
1872 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001873
1874 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001875 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001876 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1877 "unused";
1878 return;
1879 }
1880
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001881 // Verify that we have a location for the right parenthesis.
1882 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001883 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001884
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001885 // For each identifier token, insert into the token stream a
1886 // annot_pragma_unused token followed by the identifier token.
1887 // This allows us to cache a "#pragma unused" that occurs inside an inline
1888 // C++ member function.
1889
David Blaikie2eabcc92016-02-09 18:52:09 +00001890 MutableArrayRef<Token> Toks(
1891 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1892 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001893 for (unsigned i=0; i != Identifiers.size(); i++) {
1894 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1895 pragmaUnusedTok.startToken();
1896 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1897 pragmaUnusedTok.setLocation(UnusedLoc);
1898 idTok = Identifiers[i];
1899 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001900 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001901}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001902
1903// #pragma weak identifier
1904// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001905void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1906 PragmaIntroducerKind Introducer,
1907 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001908 SourceLocation WeakLoc = WeakTok.getLocation();
1909
1910 Token Tok;
1911 PP.Lex(Tok);
1912 if (Tok.isNot(tok::identifier)) {
1913 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1914 return;
1915 }
1916
Eli Friedman68be1642012-10-04 02:36:51 +00001917 Token WeakName = Tok;
1918 bool HasAlias = false;
1919 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001920
1921 PP.Lex(Tok);
1922 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001923 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001924 PP.Lex(Tok);
1925 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001926 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001927 << "weak";
1928 return;
1929 }
Eli Friedman68be1642012-10-04 02:36:51 +00001930 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001931 PP.Lex(Tok);
1932 }
1933
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001934 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001935 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1936 return;
1937 }
1938
Eli Friedman68be1642012-10-04 02:36:51 +00001939 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001940 MutableArrayRef<Token> Toks(
1941 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001942 Token &pragmaUnusedTok = Toks[0];
1943 pragmaUnusedTok.startToken();
1944 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1945 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001946 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001947 Toks[1] = WeakName;
1948 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001949 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001950 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001951 MutableArrayRef<Token> Toks(
1952 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001953 Token &pragmaUnusedTok = Toks[0];
1954 pragmaUnusedTok.startToken();
1955 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1956 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001957 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001958 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001959 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001960 }
1961}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001962
David Chisnall0867d9c2012-02-18 16:12:34 +00001963// #pragma redefine_extname identifier identifier
1964void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1965 PragmaIntroducerKind Introducer,
1966 Token &RedefToken) {
1967 SourceLocation RedefLoc = RedefToken.getLocation();
1968
1969 Token Tok;
1970 PP.Lex(Tok);
1971 if (Tok.isNot(tok::identifier)) {
1972 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1973 "redefine_extname";
1974 return;
1975 }
1976
Eli Friedman68be1642012-10-04 02:36:51 +00001977 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001978 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001979
David Chisnall0867d9c2012-02-18 16:12:34 +00001980 if (Tok.isNot(tok::identifier)) {
1981 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1982 << "redefine_extname";
1983 return;
1984 }
Eli Friedman68be1642012-10-04 02:36:51 +00001985
1986 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001987 PP.Lex(Tok);
1988
1989 if (Tok.isNot(tok::eod)) {
1990 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1991 "redefine_extname";
1992 return;
1993 }
1994
David Blaikie2eabcc92016-02-09 18:52:09 +00001995 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1996 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001997 Token &pragmaRedefTok = Toks[0];
1998 pragmaRedefTok.startToken();
1999 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2000 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002001 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002002 Toks[1] = RedefName;
2003 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00002004 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00002005}
2006
2007
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002008void
2009PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2010 PragmaIntroducerKind Introducer,
2011 Token &Tok) {
2012 tok::OnOffSwitch OOS;
2013 if (PP.LexOnOffSwitch(OOS))
2014 return;
2015
David Blaikie2eabcc92016-02-09 18:52:09 +00002016 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2017 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002018 Toks[0].startToken();
2019 Toks[0].setKind(tok::annot_pragma_fp_contract);
2020 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002021 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002022 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2023 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00002024 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002025}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002026
2027void
2028PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2029 PragmaIntroducerKind Introducer,
2030 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002031 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002032 if (Tok.isNot(tok::identifier)) {
2033 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2034 "OPENCL";
2035 return;
2036 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002037 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002038 SourceLocation NameLoc = Tok.getLocation();
2039
2040 PP.Lex(Tok);
2041 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002042 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002043 return;
2044 }
2045
2046 PP.Lex(Tok);
2047 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002048 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002049 return;
2050 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002051 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002052
Yaxun Liu5b746652016-12-18 05:18:55 +00002053 OpenCLExtState State;
2054 if (Pred->isStr("enable")) {
2055 State = Enable;
2056 } else if (Pred->isStr("disable")) {
2057 State = Disable;
2058 } else if (Pred->isStr("begin"))
2059 State = Begin;
2060 else if (Pred->isStr("end"))
2061 State = End;
2062 else {
2063 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2064 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002065 return;
2066 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002067 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002068
Eli Friedman68be1642012-10-04 02:36:51 +00002069 PP.Lex(Tok);
2070 if (Tok.isNot(tok::eod)) {
2071 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2072 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002073 return;
2074 }
Eli Friedman68be1642012-10-04 02:36:51 +00002075
Yaxun Liu5b746652016-12-18 05:18:55 +00002076 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2077 Info->first = Ext;
2078 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002079 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2080 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002081 Toks[0].startToken();
2082 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2083 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002084 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002085 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00002086 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002087
2088 if (PP.getPPCallbacks())
Yaxun Liu5b746652016-12-18 05:18:55 +00002089 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2090 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002091}
2092
Alexey Bataeva769e072013-03-22 06:34:35 +00002093/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
2094///
2095void
2096PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2097 PragmaIntroducerKind Introducer,
2098 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002099 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2100 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002101 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002102 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2103 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002104 }
2105 PP.DiscardUntilEndOfDirective();
2106}
2107
2108/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
2109///
2110void
2111PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2112 PragmaIntroducerKind Introducer,
2113 Token &FirstTok) {
2114 SmallVector<Token, 16> Pragma;
2115 Token Tok;
2116 Tok.startToken();
2117 Tok.setKind(tok::annot_pragma_openmp);
2118 Tok.setLocation(FirstTok.getLocation());
2119
Alexey Bataev96dae812018-02-16 18:36:44 +00002120 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002121 Pragma.push_back(Tok);
2122 PP.Lex(Tok);
Alexey Bataev96dae812018-02-16 18:36:44 +00002123 if (Tok.is(tok::annot_pragma_openmp)) {
2124 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2125 unsigned InnerPragmaCnt = 1;
2126 while (InnerPragmaCnt != 0) {
2127 PP.Lex(Tok);
2128 if (Tok.is(tok::annot_pragma_openmp))
2129 ++InnerPragmaCnt;
2130 else if (Tok.is(tok::annot_pragma_openmp_end))
2131 --InnerPragmaCnt;
2132 }
2133 PP.Lex(Tok);
2134 }
Alexey Bataeva769e072013-03-22 06:34:35 +00002135 }
2136 SourceLocation EodLoc = Tok.getLocation();
2137 Tok.startToken();
2138 Tok.setKind(tok::annot_pragma_openmp_end);
2139 Tok.setLocation(EodLoc);
2140 Pragma.push_back(Tok);
2141
David Blaikie2eabcc92016-02-09 18:52:09 +00002142 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
2143 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2144 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2145 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002146}
Reid Kleckner002562a2013-05-06 21:02:12 +00002147
David Majnemer4bb09802014-02-10 19:50:15 +00002148/// \brief Handle '#pragma pointers_to_members'
2149// The grammar for this pragma is as follows:
2150//
2151// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2152//
2153// #pragma pointers_to_members '(' 'best_case' ')'
2154// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2155// #pragma pointers_to_members '(' inheritance-model ')'
2156void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2157 PragmaIntroducerKind Introducer,
2158 Token &Tok) {
2159 SourceLocation PointersToMembersLoc = Tok.getLocation();
2160 PP.Lex(Tok);
2161 if (Tok.isNot(tok::l_paren)) {
2162 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2163 << "pointers_to_members";
2164 return;
2165 }
2166 PP.Lex(Tok);
2167 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2168 if (!Arg) {
2169 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2170 << "pointers_to_members";
2171 return;
2172 }
2173 PP.Lex(Tok);
2174
David Majnemer86c318f2014-02-11 21:05:00 +00002175 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002176 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002177 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002178 } else {
2179 if (Arg->isStr("full_generality")) {
2180 if (Tok.is(tok::comma)) {
2181 PP.Lex(Tok);
2182
2183 Arg = Tok.getIdentifierInfo();
2184 if (!Arg) {
2185 PP.Diag(Tok.getLocation(),
2186 diag::err_pragma_pointers_to_members_unknown_kind)
2187 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2188 return;
2189 }
2190 PP.Lex(Tok);
2191 } else if (Tok.is(tok::r_paren)) {
2192 // #pragma pointers_to_members(full_generality) implicitly specifies
2193 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002194 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002195 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002196 } else {
2197 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2198 << "full_generality";
2199 return;
2200 }
2201 }
2202
2203 if (Arg) {
2204 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002205 RepresentationMethod =
2206 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002207 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002208 RepresentationMethod =
2209 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002210 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002211 RepresentationMethod =
2212 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002213 } else {
2214 PP.Diag(Tok.getLocation(),
2215 diag::err_pragma_pointers_to_members_unknown_kind)
2216 << Arg << /*HasPointerDeclaration*/ 1;
2217 return;
2218 }
2219 }
2220 }
2221
2222 if (Tok.isNot(tok::r_paren)) {
2223 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2224 << (Arg ? Arg->getName() : "full_generality");
2225 return;
2226 }
2227
David Majnemera8f2f1d2015-03-19 00:10:23 +00002228 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002229 PP.Lex(Tok);
2230 if (Tok.isNot(tok::eod)) {
2231 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2232 << "pointers_to_members";
2233 return;
2234 }
2235
2236 Token AnnotTok;
2237 AnnotTok.startToken();
2238 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2239 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002240 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002241 AnnotTok.setAnnotationValue(
2242 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2243 PP.EnterToken(AnnotTok);
2244}
2245
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002246/// \brief Handle '#pragma vtordisp'
2247// The grammar for this pragma is as follows:
2248//
2249// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2250//
2251// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2252// #pragma vtordisp '(' 'pop' ')'
2253// #pragma vtordisp '(' ')'
2254void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2255 PragmaIntroducerKind Introducer,
2256 Token &Tok) {
2257 SourceLocation VtorDispLoc = Tok.getLocation();
2258 PP.Lex(Tok);
2259 if (Tok.isNot(tok::l_paren)) {
2260 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2261 return;
2262 }
2263 PP.Lex(Tok);
2264
Denis Zobnin2290dac2016-04-29 11:27:00 +00002265 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002266 const IdentifierInfo *II = Tok.getIdentifierInfo();
2267 if (II) {
2268 if (II->isStr("push")) {
2269 // #pragma vtordisp(push, mode)
2270 PP.Lex(Tok);
2271 if (Tok.isNot(tok::comma)) {
2272 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2273 return;
2274 }
2275 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002276 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002277 // not push, could be on/off
2278 } else if (II->isStr("pop")) {
2279 // #pragma vtordisp(pop)
2280 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002281 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002282 }
2283 // not push or pop, could be on/off
2284 } else {
2285 if (Tok.is(tok::r_paren)) {
2286 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002287 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002288 }
2289 }
2290
2291
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002292 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002293 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002294 const IdentifierInfo *II = Tok.getIdentifierInfo();
2295 if (II && II->isStr("off")) {
2296 PP.Lex(Tok);
2297 Value = 0;
2298 } else if (II && II->isStr("on")) {
2299 PP.Lex(Tok);
2300 Value = 1;
2301 } else if (Tok.is(tok::numeric_constant) &&
2302 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2303 if (Value > 2) {
2304 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2305 << 0 << 2 << "vtordisp";
2306 return;
2307 }
2308 } else {
2309 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2310 << "vtordisp";
2311 return;
2312 }
2313 }
2314
2315 // Finish the pragma: ')' $
2316 if (Tok.isNot(tok::r_paren)) {
2317 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2318 return;
2319 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002320 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002321 PP.Lex(Tok);
2322 if (Tok.isNot(tok::eod)) {
2323 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2324 << "vtordisp";
2325 return;
2326 }
2327
2328 // Enter the annotation.
2329 Token AnnotTok;
2330 AnnotTok.startToken();
2331 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2332 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002333 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002334 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002335 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002336 PP.EnterToken(AnnotTok);
2337}
2338
Warren Huntc3b18962014-04-08 22:30:47 +00002339/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
2340/// an annotation token.
2341void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2342 PragmaIntroducerKind Introducer,
2343 Token &Tok) {
2344 Token EoF, AnnotTok;
2345 EoF.startToken();
2346 EoF.setKind(tok::eof);
2347 AnnotTok.startToken();
2348 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2349 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002350 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002351 SmallVector<Token, 8> TokenVector;
2352 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002353 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002354 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002355 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2356 }
Warren Huntc3b18962014-04-08 22:30:47 +00002357 // Add a sentinal EoF token to the end of the list.
2358 TokenVector.push_back(EoF);
2359 // We must allocate this array with new because EnterTokenStream is going to
2360 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00002361 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
2362 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002363 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002364 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2365 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002366 AnnotTok.setAnnotationValue(Value);
2367 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002368}
2369
Aaron Ballman5d041be2013-06-04 02:07:14 +00002370/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
2371///
2372/// The syntax is:
2373/// \code
2374/// #pragma detect_mismatch("name", "value")
2375/// \endcode
2376/// Where 'name' and 'value' are quoted strings. The values are embedded in
2377/// the object file and passed along to the linker. If the linker detects a
2378/// mismatch in the object file's values for the given name, a LNK2038 error
2379/// is emitted. See MSDN for more details.
2380void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2381 PragmaIntroducerKind Introducer,
2382 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002383 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002384 PP.Lex(Tok);
2385 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002386 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002387 return;
2388 }
2389
2390 // Read the name to embed, which must be a string literal.
2391 std::string NameString;
2392 if (!PP.LexStringLiteral(Tok, NameString,
2393 "pragma detect_mismatch",
2394 /*MacroExpansion=*/true))
2395 return;
2396
2397 // Read the comma followed by a second string literal.
2398 std::string ValueString;
2399 if (Tok.isNot(tok::comma)) {
2400 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2401 return;
2402 }
2403
2404 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2405 /*MacroExpansion=*/true))
2406 return;
2407
2408 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002409 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002410 return;
2411 }
2412 PP.Lex(Tok); // Eat the r_paren.
2413
2414 if (Tok.isNot(tok::eod)) {
2415 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2416 return;
2417 }
2418
Reid Kleckner71966c92014-02-20 23:37:45 +00002419 // If the pragma is lexically sound, notify any interested PPCallbacks.
2420 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002421 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002422 ValueString);
2423
Nico Webercbbaeb12016-03-02 19:28:54 +00002424 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002425}
2426
Reid Kleckner002562a2013-05-06 21:02:12 +00002427/// \brief Handle the microsoft \#pragma comment extension.
2428///
2429/// The syntax is:
2430/// \code
2431/// #pragma comment(linker, "foo")
2432/// \endcode
2433/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2434/// "foo" is a string, which is fully macro expanded, and permits string
2435/// concatenation, embedded escape characters etc. See MSDN for more details.
2436void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2437 PragmaIntroducerKind Introducer,
2438 Token &Tok) {
2439 SourceLocation CommentLoc = Tok.getLocation();
2440 PP.Lex(Tok);
2441 if (Tok.isNot(tok::l_paren)) {
2442 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2443 return;
2444 }
2445
2446 // Read the identifier.
2447 PP.Lex(Tok);
2448 if (Tok.isNot(tok::identifier)) {
2449 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2450 return;
2451 }
2452
2453 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002454 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002455 PragmaMSCommentKind Kind =
2456 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2457 .Case("linker", PCK_Linker)
2458 .Case("lib", PCK_Lib)
2459 .Case("compiler", PCK_Compiler)
2460 .Case("exestr", PCK_ExeStr)
2461 .Case("user", PCK_User)
2462 .Default(PCK_Unknown);
2463 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002464 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2465 return;
2466 }
2467
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +00002468 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2469 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2470 << II->getName();
2471 return;
2472 }
2473
Yunzhong Gao99efc032015-03-23 20:41:42 +00002474 // On PS4, issue a warning about any pragma comments other than
2475 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002476 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002477 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2478 << II->getName();
2479 return;
2480 }
2481
Reid Kleckner002562a2013-05-06 21:02:12 +00002482 // Read the optional string if present.
2483 PP.Lex(Tok);
2484 std::string ArgumentString;
2485 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2486 "pragma comment",
2487 /*MacroExpansion=*/true))
2488 return;
2489
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002490 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002491 // FIXME: If the kind is "compiler" warn if the string is present (it is
2492 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002493 // The MSDN docs say that "lib" and "linker" require a string and have a short
2494 // whitelist of linker options they support, but in practice MSVC doesn't
2495 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002496
2497 if (Tok.isNot(tok::r_paren)) {
2498 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2499 return;
2500 }
2501 PP.Lex(Tok); // eat the r_paren.
2502
2503 if (Tok.isNot(tok::eod)) {
2504 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2505 return;
2506 }
2507
Reid Kleckner71966c92014-02-20 23:37:45 +00002508 // If the pragma is lexically sound, notify any interested PPCallbacks.
2509 if (PP.getPPCallbacks())
2510 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2511
Nico Weber66220292016-03-02 17:28:48 +00002512 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002513}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002514
2515// #pragma clang optimize off
2516// #pragma clang optimize on
2517void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2518 PragmaIntroducerKind Introducer,
2519 Token &FirstToken) {
2520 Token Tok;
2521 PP.Lex(Tok);
2522 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002523 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002524 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002525 return;
2526 }
2527 if (Tok.isNot(tok::identifier)) {
2528 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2529 << PP.getSpelling(Tok);
2530 return;
2531 }
2532 const IdentifierInfo *II = Tok.getIdentifierInfo();
2533 // The only accepted values are 'on' or 'off'.
2534 bool IsOn = false;
2535 if (II->isStr("on")) {
2536 IsOn = true;
2537 } else if (!II->isStr("off")) {
2538 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2539 << PP.getSpelling(Tok);
2540 return;
2541 }
2542 PP.Lex(Tok);
2543
2544 if (Tok.isNot(tok::eod)) {
2545 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2546 << PP.getSpelling(Tok);
2547 return;
2548 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002549
2550 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2551}
2552
Adam Nemet60d32642017-04-04 21:18:36 +00002553namespace {
2554/// Used as the annotation value for tok::annot_pragma_fp.
2555struct TokFPAnnotValue {
2556 enum FlagKinds { Contract };
2557 enum FlagValues { On, Off, Fast };
2558
2559 FlagKinds FlagKind;
2560 FlagValues FlagValue;
2561};
2562} // end anonymous namespace
2563
2564void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2565 PragmaIntroducerKind Introducer,
2566 Token &Tok) {
2567 // fp
2568 Token PragmaName = Tok;
2569 SmallVector<Token, 1> TokenList;
2570
2571 PP.Lex(Tok);
2572 if (Tok.isNot(tok::identifier)) {
2573 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2574 << /*MissingOption=*/true << "";
2575 return;
2576 }
2577
2578 while (Tok.is(tok::identifier)) {
2579 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2580
2581 auto FlagKind =
2582 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2583 OptionInfo->getName())
2584 .Case("contract", TokFPAnnotValue::Contract)
2585 .Default(None);
2586 if (!FlagKind) {
2587 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2588 << /*MissingOption=*/false << OptionInfo;
2589 return;
2590 }
2591 PP.Lex(Tok);
2592
2593 // Read '('
2594 if (Tok.isNot(tok::l_paren)) {
2595 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2596 return;
2597 }
2598 PP.Lex(Tok);
2599
2600 if (Tok.isNot(tok::identifier)) {
2601 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2602 << PP.getSpelling(Tok) << OptionInfo->getName();
2603 return;
2604 }
2605 const IdentifierInfo *II = Tok.getIdentifierInfo();
2606
2607 auto FlagValue =
2608 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2609 II->getName())
2610 .Case("on", TokFPAnnotValue::On)
2611 .Case("off", TokFPAnnotValue::Off)
2612 .Case("fast", TokFPAnnotValue::Fast)
2613 .Default(llvm::None);
2614
2615 if (!FlagValue) {
2616 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2617 << PP.getSpelling(Tok) << OptionInfo->getName();
2618 return;
2619 }
2620 PP.Lex(Tok);
2621
2622 // Read ')'
2623 if (Tok.isNot(tok::r_paren)) {
2624 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2625 return;
2626 }
2627 PP.Lex(Tok);
2628
2629 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2630 TokFPAnnotValue{*FlagKind, *FlagValue};
2631 // Generate the loop hint token.
2632 Token FPTok;
2633 FPTok.startToken();
2634 FPTok.setKind(tok::annot_pragma_fp);
2635 FPTok.setLocation(PragmaName.getLocation());
2636 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2637 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2638 TokenList.push_back(FPTok);
2639 }
2640
2641 if (Tok.isNot(tok::eod)) {
2642 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2643 << "clang fp";
2644 return;
2645 }
2646
2647 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2648 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2649
2650 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2651 /*DisableMacroExpansion=*/false);
2652}
2653
2654void Parser::HandlePragmaFP() {
2655 assert(Tok.is(tok::annot_pragma_fp));
2656 auto *AnnotValue =
2657 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2658
2659 LangOptions::FPContractModeKind FPC;
2660 switch (AnnotValue->FlagValue) {
2661 case TokFPAnnotValue::On:
2662 FPC = LangOptions::FPC_On;
2663 break;
2664 case TokFPAnnotValue::Fast:
2665 FPC = LangOptions::FPC_Fast;
2666 break;
2667 case TokFPAnnotValue::Off:
2668 FPC = LangOptions::FPC_Off;
2669 break;
2670 }
2671
2672 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002673 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002674}
2675
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002676/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002677static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2678 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002679 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002680 SmallVector<Token, 1> ValueList;
2681 int OpenParens = ValueInParens ? 1 : 0;
2682 // Read constant expression.
2683 while (Tok.isNot(tok::eod)) {
2684 if (Tok.is(tok::l_paren))
2685 OpenParens++;
2686 else if (Tok.is(tok::r_paren)) {
2687 OpenParens--;
2688 if (OpenParens == 0 && ValueInParens)
2689 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002690 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002691
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002692 ValueList.push_back(Tok);
2693 PP.Lex(Tok);
2694 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002695
2696 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002697 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002698 if (Tok.isNot(tok::r_paren)) {
2699 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2700 return true;
2701 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002702 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002703 }
2704
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002705 Token EOFTok;
2706 EOFTok.startToken();
2707 EOFTok.setKind(tok::eof);
2708 EOFTok.setLocation(Tok.getLocation());
2709 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2710
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002711 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002712
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002713 Info.PragmaName = PragmaName;
2714 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002715 return false;
2716}
2717
Eli Bendersky06a40422014-06-06 20:31:48 +00002718/// \brief Handle the \#pragma clang loop directive.
2719/// #pragma clang 'loop' loop-hints
2720///
2721/// loop-hints:
2722/// loop-hint loop-hints[opt]
2723///
2724/// loop-hint:
2725/// 'vectorize' '(' loop-hint-keyword ')'
2726/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002727/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002728/// 'vectorize_width' '(' loop-hint-value ')'
2729/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002730/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002731///
2732/// loop-hint-keyword:
2733/// 'enable'
2734/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002735/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002736///
Mark Heffernan450c2382014-07-23 17:31:31 +00002737/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002738/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002739/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002740/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002741///
Eli Bendersky06a40422014-06-06 20:31:48 +00002742/// loop-hint-value:
2743/// constant-expression
2744///
2745/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2746/// try vectorizing the instructions of the loop it precedes. Specifying
2747/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2748/// interleaving multiple iterations of the loop it precedes. The width of the
2749/// vector instructions is specified by vectorize_width() and the number of
2750/// interleaved loop iterations is specified by interleave_count(). Specifying a
2751/// value of 1 effectively disables vectorization/interleaving, even if it is
2752/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2753/// only works on inner loops.
2754///
Eli Bendersky86483b32014-06-11 17:56:26 +00002755/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002756/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2757/// completely if the trip count is known at compile time and unroll partially
2758/// if the trip count is not known. Specifying unroll(full) is similar to
2759/// unroll(enable) but will unroll the loop only if the trip count is known at
2760/// compile time. Specifying unroll(disable) disables unrolling for the
2761/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2762/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002763void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2764 PragmaIntroducerKind Introducer,
2765 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002766 // Incoming token is "loop" from "#pragma clang loop".
2767 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002768 SmallVector<Token, 1> TokenList;
2769
2770 // Lex the optimization option and verify it is an identifier.
2771 PP.Lex(Tok);
2772 if (Tok.isNot(tok::identifier)) {
2773 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2774 << /*MissingOption=*/true << "";
2775 return;
2776 }
2777
2778 while (Tok.is(tok::identifier)) {
2779 Token Option = Tok;
2780 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2781
Eli Bendersky86483b32014-06-11 17:56:26 +00002782 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002783 .Case("vectorize", true)
2784 .Case("interleave", true)
2785 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002786 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002787 .Case("vectorize_width", true)
2788 .Case("interleave_count", true)
2789 .Case("unroll_count", true)
2790 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002791 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002792 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2793 << /*MissingOption=*/false << OptionInfo;
2794 return;
2795 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002796 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002797
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002798 // Read '('
2799 if (Tok.isNot(tok::l_paren)) {
2800 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002801 return;
2802 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002803 PP.Lex(Tok);
2804
2805 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2806 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2807 *Info))
2808 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002809
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002810 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002811 Token LoopHintTok;
2812 LoopHintTok.startToken();
2813 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002814 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002815 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002816 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2817 TokenList.push_back(LoopHintTok);
2818 }
2819
2820 if (Tok.isNot(tok::eod)) {
2821 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2822 << "clang loop";
2823 return;
2824 }
2825
David Blaikie2eabcc92016-02-09 18:52:09 +00002826 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2827 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002828
David Blaikie2eabcc92016-02-09 18:52:09 +00002829 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2830 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002831}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002832
2833/// \brief Handle the loop unroll optimization pragmas.
2834/// #pragma unroll
2835/// #pragma unroll unroll-hint-value
2836/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002837/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002838///
2839/// unroll-hint-value:
2840/// constant-expression
2841///
Mark Heffernanc888e412014-07-24 18:09:38 +00002842/// Loop unrolling hints can be specified with '#pragma unroll' or
2843/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2844/// contained in parentheses. With no argument the directive instructs llvm to
2845/// try to unroll the loop completely. A positive integer argument can be
2846/// specified to indicate the number of times the loop should be unrolled. To
2847/// maximize compatibility with other compilers the unroll count argument can be
2848/// specified with or without parentheses. Specifying, '#pragma nounroll'
2849/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002850void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2851 PragmaIntroducerKind Introducer,
2852 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002853 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2854 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002855 Token PragmaName = Tok;
2856 PP.Lex(Tok);
2857 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2858 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002859 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002860 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002861 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002862 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2863 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2864 << "nounroll";
2865 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002866 } else {
2867 // Unroll pragma with an argument: "#pragma unroll N" or
2868 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002869 // Read '(' if it exists.
2870 bool ValueInParens = Tok.is(tok::l_paren);
2871 if (ValueInParens)
2872 PP.Lex(Tok);
2873
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002874 Token Option;
2875 Option.startToken();
2876 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002877 return;
2878
2879 // In CUDA, the argument to '#pragma unroll' should not be contained in
2880 // parentheses.
2881 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002882 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002883 diag::warn_pragma_unroll_cuda_value_in_parens);
2884
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002885 if (Tok.isNot(tok::eod)) {
2886 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2887 << "unroll";
2888 return;
2889 }
2890 }
2891
2892 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002893 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002894 TokenArray[0].startToken();
2895 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2896 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002897 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002898 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002899 PP.EnterTokenStream(std::move(TokenArray), 1,
2900 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002901}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002902
2903/// \brief Handle the Microsoft \#pragma intrinsic extension.
2904///
2905/// The syntax is:
2906/// \code
2907/// #pragma intrinsic(memset)
2908/// #pragma intrinsic(strlen, memcpy)
2909/// \endcode
2910///
2911/// Pragma intrisic tells the compiler to use a builtin version of the
2912/// function. Clang does it anyway, so the pragma doesn't really do anything.
2913/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2914/// isn't an intrinsic in clang and suggest to include intrin.h.
2915void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2916 PragmaIntroducerKind Introducer,
2917 Token &Tok) {
2918 PP.Lex(Tok);
2919
2920 if (Tok.isNot(tok::l_paren)) {
2921 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2922 << "intrinsic";
2923 return;
2924 }
2925 PP.Lex(Tok);
2926
2927 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2928
2929 while (Tok.is(tok::identifier)) {
2930 IdentifierInfo *II = Tok.getIdentifierInfo();
2931 if (!II->getBuiltinID())
2932 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2933 << II << SuggestIntrinH;
2934
2935 PP.Lex(Tok);
2936 if (Tok.isNot(tok::comma))
2937 break;
2938 PP.Lex(Tok);
2939 }
2940
2941 if (Tok.isNot(tok::r_paren)) {
2942 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2943 << "intrinsic";
2944 return;
2945 }
2946 PP.Lex(Tok);
2947
2948 if (Tok.isNot(tok::eod))
2949 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2950 << "intrinsic";
2951}
Justin Lebar67a78a62016-10-08 22:15:58 +00002952void PragmaForceCUDAHostDeviceHandler::HandlePragma(
2953 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
2954 Token FirstTok = Tok;
2955
2956 PP.Lex(Tok);
2957 IdentifierInfo *Info = Tok.getIdentifierInfo();
2958 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
2959 PP.Diag(FirstTok.getLocation(),
2960 diag::warn_pragma_force_cuda_host_device_bad_arg);
2961 return;
2962 }
2963
2964 if (Info->isStr("begin"))
2965 Actions.PushForceCUDAHostDevice();
2966 else if (!Actions.PopForceCUDAHostDevice())
2967 PP.Diag(FirstTok.getLocation(),
2968 diag::err_pragma_cannot_end_force_cuda_host_device);
2969
2970 PP.Lex(Tok);
2971 if (!Tok.is(tok::eod))
2972 PP.Diag(FirstTok.getLocation(),
2973 diag::warn_pragma_force_cuda_host_device_bad_arg);
2974}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00002975
2976/// \brief Handle the #pragma clang attribute directive.
2977///
2978/// The syntax is:
2979/// \code
2980/// #pragma clang attribute push(attribute, subject-set)
2981/// #pragma clang attribute pop
2982/// \endcode
2983///
2984/// The subject-set clause defines the set of declarations which receive the
2985/// attribute. Its exact syntax is described in the LanguageExtensions document
2986/// in Clang's documentation.
2987///
2988/// This directive instructs the compiler to begin/finish applying the specified
2989/// attribute to the set of attribute-specific declarations in the active range
2990/// of the pragma.
2991void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
2992 PragmaIntroducerKind Introducer,
2993 Token &FirstToken) {
2994 Token Tok;
2995 PP.Lex(Tok);
2996 auto *Info = new (PP.getPreprocessorAllocator())
2997 PragmaAttributeInfo(AttributesForPragmaAttribute);
2998
2999 // Parse the 'push' or 'pop'.
3000 if (Tok.isNot(tok::identifier)) {
3001 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
3002 return;
3003 }
3004 const auto *II = Tok.getIdentifierInfo();
3005 if (II->isStr("push"))
3006 Info->Action = PragmaAttributeInfo::Push;
3007 else if (II->isStr("pop"))
3008 Info->Action = PragmaAttributeInfo::Pop;
3009 else {
3010 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3011 << PP.getSpelling(Tok);
3012 return;
3013 }
3014 PP.Lex(Tok);
3015
3016 // Parse the actual attribute.
3017 if (Info->Action == PragmaAttributeInfo::Push) {
3018 if (Tok.isNot(tok::l_paren)) {
3019 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3020 return;
3021 }
3022 PP.Lex(Tok);
3023
3024 // Lex the attribute tokens.
3025 SmallVector<Token, 16> AttributeTokens;
3026 int OpenParens = 1;
3027 while (Tok.isNot(tok::eod)) {
3028 if (Tok.is(tok::l_paren))
3029 OpenParens++;
3030 else if (Tok.is(tok::r_paren)) {
3031 OpenParens--;
3032 if (OpenParens == 0)
3033 break;
3034 }
3035
3036 AttributeTokens.push_back(Tok);
3037 PP.Lex(Tok);
3038 }
3039
3040 if (AttributeTokens.empty()) {
3041 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3042 return;
3043 }
3044 if (Tok.isNot(tok::r_paren)) {
3045 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3046 return;
3047 }
3048 SourceLocation EndLoc = Tok.getLocation();
3049 PP.Lex(Tok);
3050
3051 // Terminate the attribute for parsing.
3052 Token EOFTok;
3053 EOFTok.startToken();
3054 EOFTok.setKind(tok::eof);
3055 EOFTok.setLocation(EndLoc);
3056 AttributeTokens.push_back(EOFTok);
3057
3058 Info->Tokens =
3059 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3060 }
3061
3062 if (Tok.isNot(tok::eod))
3063 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3064 << "clang attribute";
3065
3066 // Generate the annotated pragma token.
3067 auto TokenArray = llvm::make_unique<Token[]>(1);
3068 TokenArray[0].startToken();
3069 TokenArray[0].setKind(tok::annot_pragma_attribute);
3070 TokenArray[0].setLocation(FirstToken.getLocation());
3071 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3072 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3073 PP.EnterTokenStream(std::move(TokenArray), 1,
3074 /*DisableMacroExpansion=*/false);
3075}