blob: 8152176484df250c2586d5eac41df893d5392dc3 [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
Yunzhong Gao99efc032015-03-23 20:41:42 +0000298 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000299 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
300 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000301 }
302
303 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000304 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
305 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
306 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
307 PP.AddPragmaHandler(MSPointersToMembers.get());
308 MSVtorDisp.reset(new PragmaMSVtorDisp());
309 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000310 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000311 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000312 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
313 PP.AddPragmaHandler(MSDataSeg.get());
314 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
315 PP.AddPragmaHandler(MSBSSSeg.get());
316 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
317 PP.AddPragmaHandler(MSConstSeg.get());
318 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
319 PP.AddPragmaHandler(MSCodeSeg.get());
320 MSSection.reset(new PragmaMSPragma("section"));
321 PP.AddPragmaHandler(MSSection.get());
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000322 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
323 PP.AddPragmaHandler(MSRuntimeChecks.get());
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000324 MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
325 PP.AddPragmaHandler(MSIntrinsic.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000326 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000327
Justin Lebar67a78a62016-10-08 22:15:58 +0000328 if (getLangOpts().CUDA) {
329 CUDAForceHostDeviceHandler.reset(
330 new PragmaForceCUDAHostDeviceHandler(Actions));
331 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
332 }
333
Eli Bendersky06a40422014-06-06 20:31:48 +0000334 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
335 PP.AddPragmaHandler("clang", OptimizeHandler.get());
336
337 LoopHintHandler.reset(new PragmaLoopHintHandler());
338 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000339
340 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
341 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000342
343 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
344 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000345
346 FPHandler.reset(new PragmaFPHandler());
347 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000348
349 AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
350 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000351}
352
353void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000354 // Remove the pragma handlers we installed.
355 PP.RemovePragmaHandler(AlignHandler.get());
356 AlignHandler.reset();
357 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
358 GCCVisibilityHandler.reset();
359 PP.RemovePragmaHandler(OptionsHandler.get());
360 OptionsHandler.reset();
361 PP.RemovePragmaHandler(PackHandler.get());
362 PackHandler.reset();
363 PP.RemovePragmaHandler(MSStructHandler.get());
364 MSStructHandler.reset();
365 PP.RemovePragmaHandler(UnusedHandler.get());
366 UnusedHandler.reset();
367 PP.RemovePragmaHandler(WeakHandler.get());
368 WeakHandler.reset();
369 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
370 RedefineExtnameHandler.reset();
371
372 if (getLangOpts().OpenCL) {
373 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
374 OpenCLExtensionHandler.reset();
375 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
376 }
377 PP.RemovePragmaHandler(OpenMPHandler.get());
378 OpenMPHandler.reset();
379
Yunzhong Gao99efc032015-03-23 20:41:42 +0000380 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000381 PP.RemovePragmaHandler(MSCommentHandler.get());
382 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000383 }
384
Javed Absar2a67c9e2017-06-05 10:11:57 +0000385 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
386 PCSectionHandler.reset();
387
Yunzhong Gao99efc032015-03-23 20:41:42 +0000388 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000389 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
390 MSDetectMismatchHandler.reset();
391 PP.RemovePragmaHandler(MSPointersToMembers.get());
392 MSPointersToMembers.reset();
393 PP.RemovePragmaHandler(MSVtorDisp.get());
394 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000395 PP.RemovePragmaHandler(MSInitSeg.get());
396 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000397 PP.RemovePragmaHandler(MSDataSeg.get());
398 MSDataSeg.reset();
399 PP.RemovePragmaHandler(MSBSSSeg.get());
400 MSBSSSeg.reset();
401 PP.RemovePragmaHandler(MSConstSeg.get());
402 MSConstSeg.reset();
403 PP.RemovePragmaHandler(MSCodeSeg.get());
404 MSCodeSeg.reset();
405 PP.RemovePragmaHandler(MSSection.get());
406 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000407 PP.RemovePragmaHandler(MSRuntimeChecks.get());
408 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000409 PP.RemovePragmaHandler(MSIntrinsic.get());
410 MSIntrinsic.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000411 }
412
Justin Lebar67a78a62016-10-08 22:15:58 +0000413 if (getLangOpts().CUDA) {
414 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
415 CUDAForceHostDeviceHandler.reset();
416 }
417
Reid Kleckner5b086462014-02-20 22:52:09 +0000418 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
419 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000420
Steven Wub96a3a42018-01-05 22:45:03 +0000421 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
422 STDCFENVHandler.reset();
423
424 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
425 STDCCXLIMITHandler.reset();
426
427 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
428 STDCUnknownHandler.reset();
429
Eli Bendersky06a40422014-06-06 20:31:48 +0000430 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
431 OptimizeHandler.reset();
432
433 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
434 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000435
436 PP.RemovePragmaHandler(UnrollHintHandler.get());
437 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000438
439 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
440 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000441
442 PP.RemovePragmaHandler("clang", FPHandler.get());
443 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000444
445 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
446 AttributePragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000447}
448
449/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000450///
451/// Each annot_pragma_unused is followed by the argument token so e.g.
452/// "#pragma unused(x,y)" becomes:
453/// annot_pragma_unused 'x' annot_pragma_unused 'y'
454void Parser::HandlePragmaUnused() {
455 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000456 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000457 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
458 ConsumeToken(); // The argument token.
459}
Eli Friedman570024a2010-08-05 06:57:20 +0000460
Rafael Espindola273fd772012-01-26 02:02:57 +0000461void Parser::HandlePragmaVisibility() {
462 assert(Tok.is(tok::annot_pragma_vis));
463 const IdentifierInfo *VisType =
464 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000465 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000466 Actions.ActOnPragmaVisibility(VisType, VisLoc);
467}
468
Benjamin Kramere003ca22015-10-28 13:54:16 +0000469namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000470struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000471 Sema::PragmaMsStackAction Action;
472 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000473 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000474};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000475} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000476
477void Parser::HandlePragmaPack() {
478 assert(Tok.is(tok::annot_pragma_pack));
479 PragmaPackInfo *Info =
480 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000481 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000482 ExprResult Alignment;
483 if (Info->Alignment.is(tok::numeric_constant)) {
484 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000485 if (Alignment.isInvalid()) {
486 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000487 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000488 }
Eli Friedman68be1642012-10-04 02:36:51 +0000489 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000490 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
491 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000492 // Consume the token after processing the pragma to enable pragma-specific
493 // #include warnings.
494 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000495}
496
Eli Friedman68be1642012-10-04 02:36:51 +0000497void Parser::HandlePragmaMSStruct() {
498 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000499 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
500 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000501 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000502 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000503}
504
505void Parser::HandlePragmaAlign() {
506 assert(Tok.is(tok::annot_pragma_align));
507 Sema::PragmaOptionsAlignKind Kind =
508 static_cast<Sema::PragmaOptionsAlignKind>(
509 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000510 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000511 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
512}
513
Richard Smithba3a4f92016-01-12 21:59:26 +0000514void Parser::HandlePragmaDump() {
515 assert(Tok.is(tok::annot_pragma_dump));
516 IdentifierInfo *II =
517 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
518 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000519 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000520}
521
Eli Friedman68be1642012-10-04 02:36:51 +0000522void Parser::HandlePragmaWeak() {
523 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000524 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000525 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
526 Tok.getLocation());
527 ConsumeToken(); // The weak name.
528}
529
530void Parser::HandlePragmaWeakAlias() {
531 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000532 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000533 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
534 SourceLocation WeakNameLoc = Tok.getLocation();
535 ConsumeToken();
536 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
537 SourceLocation AliasNameLoc = Tok.getLocation();
538 ConsumeToken();
539 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
540 WeakNameLoc, AliasNameLoc);
541
542}
543
544void Parser::HandlePragmaRedefineExtname() {
545 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000546 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000547 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
548 SourceLocation RedefNameLoc = Tok.getLocation();
549 ConsumeToken();
550 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
551 SourceLocation AliasNameLoc = Tok.getLocation();
552 ConsumeToken();
553 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
554 RedefNameLoc, AliasNameLoc);
555}
556
557void Parser::HandlePragmaFPContract() {
558 assert(Tok.is(tok::annot_pragma_fp_contract));
559 tok::OnOffSwitch OOS =
560 static_cast<tok::OnOffSwitch>(
561 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000562
563 LangOptions::FPContractModeKind FPC;
564 switch (OOS) {
565 case tok::OOS_ON:
566 FPC = LangOptions::FPC_On;
567 break;
568 case tok::OOS_OFF:
569 FPC = LangOptions::FPC_Off;
570 break;
571 case tok::OOS_DEFAULT:
572 FPC = getLangOpts().getDefaultFPContractMode();
573 break;
574 }
575
576 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000577 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000578}
579
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000580StmtResult Parser::HandlePragmaCaptured()
581{
582 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000583 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000584
585 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000586 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000587 return StmtError();
588 }
589
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000590 SourceLocation Loc = Tok.getLocation();
591
Momchil Velikov57c681f2017-08-10 15:43:06 +0000592 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
593 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000594 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
595 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000596
597 StmtResult R = ParseCompoundStatement();
598 CapturedRegionScope.Exit();
599
600 if (R.isInvalid()) {
601 Actions.ActOnCapturedRegionError();
602 return StmtError();
603 }
604
605 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000606}
607
Eli Friedman68be1642012-10-04 02:36:51 +0000608namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000609 enum OpenCLExtState : char {
610 Disable, Enable, Begin, End
611 };
612 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000613}
614
615void Parser::HandlePragmaOpenCLExtension() {
616 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000617 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
618 auto State = Data->second;
619 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000620 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000621 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000622
Yaxun Liu5b746652016-12-18 05:18:55 +0000623 auto &Opt = Actions.getOpenCLOptions();
624 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000625 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
626 // overriding all previously issued extension directives, but only if the
627 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000628 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000629 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000630 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000631 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
632 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000633 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000634 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000635 } else if (State == Begin) {
636 if (!Opt.isKnown(Name) ||
637 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
638 Opt.support(Name);
639 }
640 Actions.setCurrentOpenCLExtension(Name);
641 } else if (State == End) {
642 if (Name != Actions.getCurrentOpenCLExtension())
643 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
644 Actions.setCurrentOpenCLExtension("");
645 } else if (!Opt.isKnown(Name))
646 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
647 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
648 Opt.enable(Name, State == Enable);
649 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
650 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
651 else
652 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000653}
654
David Majnemer4bb09802014-02-10 19:50:15 +0000655void Parser::HandlePragmaMSPointersToMembers() {
656 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000657 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
658 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000659 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000660 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000661 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
662}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000663
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000664void Parser::HandlePragmaMSVtorDisp() {
665 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
666 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000667 Sema::PragmaMsStackAction Action =
668 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000669 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000670 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000671 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000672}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000673
Warren Huntc3b18962014-04-08 22:30:47 +0000674void Parser::HandlePragmaMSPragma() {
675 assert(Tok.is(tok::annot_pragma_ms_pragma));
676 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000677 auto TheTokens =
678 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
679 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000680 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000681 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000682 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000683 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000684
Warren Huntc3b18962014-04-08 22:30:47 +0000685 // Figure out which #pragma we're dealing with. The switch has no default
686 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000687 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000688 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
689 .Case("data_seg", &Parser::HandlePragmaMSSegment)
690 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
691 .Case("const_seg", &Parser::HandlePragmaMSSegment)
692 .Case("code_seg", &Parser::HandlePragmaMSSegment)
693 .Case("section", &Parser::HandlePragmaMSSection)
694 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000695
696 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
697 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
698 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000699 while (Tok.isNot(tok::eof))
700 PP.Lex(Tok);
701 PP.Lex(Tok);
702 }
703}
704
Reid Kleckner722b1df2014-07-18 00:13:16 +0000705bool Parser::HandlePragmaMSSection(StringRef PragmaName,
706 SourceLocation PragmaLocation) {
707 if (Tok.isNot(tok::l_paren)) {
708 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
709 return false;
710 }
Warren Huntc3b18962014-04-08 22:30:47 +0000711 PP.Lex(Tok); // (
712 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000713 if (Tok.isNot(tok::string_literal)) {
714 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
715 << PragmaName;
716 return false;
717 }
718 ExprResult StringResult = ParseStringLiteralExpression();
719 if (StringResult.isInvalid())
720 return false; // Already diagnosed.
721 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
722 if (SegmentName->getCharByteWidth() != 1) {
723 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
724 << PragmaName;
725 return false;
726 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000727 int SectionFlags = ASTContext::PSF_Read;
728 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000729 while (Tok.is(tok::comma)) {
730 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000731 // Ignore "long" and "short".
732 // They are undocumented, but widely used, section attributes which appear
733 // to do nothing.
734 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
735 PP.Lex(Tok); // long/short
736 continue;
737 }
738
Reid Kleckner722b1df2014-07-18 00:13:16 +0000739 if (!Tok.isAnyIdentifier()) {
740 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
741 << PragmaName;
742 return false;
743 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000744 ASTContext::PragmaSectionFlag Flag =
745 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000746 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000747 .Case("read", ASTContext::PSF_Read)
748 .Case("write", ASTContext::PSF_Write)
749 .Case("execute", ASTContext::PSF_Execute)
750 .Case("shared", ASTContext::PSF_Invalid)
751 .Case("nopage", ASTContext::PSF_Invalid)
752 .Case("nocache", ASTContext::PSF_Invalid)
753 .Case("discard", ASTContext::PSF_Invalid)
754 .Case("remove", ASTContext::PSF_Invalid)
755 .Default(ASTContext::PSF_None);
756 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
757 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000758 ? diag::warn_pragma_invalid_specific_action
759 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000760 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000761 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000762 }
763 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000764 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000765 PP.Lex(Tok); // Identifier
766 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000767 // If no section attributes are specified, the section will be marked as
768 // read/write.
769 if (SectionFlagsAreDefault)
770 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000771 if (Tok.isNot(tok::r_paren)) {
772 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
773 return false;
774 }
Warren Huntc3b18962014-04-08 22:30:47 +0000775 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000776 if (Tok.isNot(tok::eof)) {
777 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
778 << PragmaName;
779 return false;
780 }
Warren Huntc3b18962014-04-08 22:30:47 +0000781 PP.Lex(Tok); // eof
782 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000783 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000784}
785
Reid Kleckner722b1df2014-07-18 00:13:16 +0000786bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
787 SourceLocation PragmaLocation) {
788 if (Tok.isNot(tok::l_paren)) {
789 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
790 return false;
791 }
Warren Huntc3b18962014-04-08 22:30:47 +0000792 PP.Lex(Tok); // (
793 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000794 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000795 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000796 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000797 if (PushPop == "push")
798 Action = Sema::PSK_Push;
799 else if (PushPop == "pop")
800 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000801 else {
802 PP.Diag(PragmaLocation,
803 diag::warn_pragma_expected_section_push_pop_or_name)
804 << PragmaName;
805 return false;
806 }
Warren Huntc3b18962014-04-08 22:30:47 +0000807 if (Action != Sema::PSK_Reset) {
808 PP.Lex(Tok); // push | pop
809 if (Tok.is(tok::comma)) {
810 PP.Lex(Tok); // ,
811 // If we've got a comma, we either need a label or a string.
812 if (Tok.isAnyIdentifier()) {
813 SlotLabel = Tok.getIdentifierInfo()->getName();
814 PP.Lex(Tok); // identifier
815 if (Tok.is(tok::comma))
816 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000817 else if (Tok.isNot(tok::r_paren)) {
818 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
819 << PragmaName;
820 return false;
821 }
Warren Huntc3b18962014-04-08 22:30:47 +0000822 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000823 } else if (Tok.isNot(tok::r_paren)) {
824 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
825 return false;
826 }
Warren Huntc3b18962014-04-08 22:30:47 +0000827 }
828 }
829 // Grab the string literal for our section name.
830 StringLiteral *SegmentName = nullptr;
831 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000832 if (Tok.isNot(tok::string_literal)) {
833 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000834 diag::warn_pragma_expected_section_name :
835 diag::warn_pragma_expected_section_label_or_name :
836 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000837 PP.Diag(PragmaLocation, DiagID) << PragmaName;
838 return false;
839 }
840 ExprResult StringResult = ParseStringLiteralExpression();
841 if (StringResult.isInvalid())
842 return false; // Already diagnosed.
843 SegmentName = cast<StringLiteral>(StringResult.get());
844 if (SegmentName->getCharByteWidth() != 1) {
845 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
846 << PragmaName;
847 return false;
848 }
Warren Huntc3b18962014-04-08 22:30:47 +0000849 // Setting section "" has no effect
850 if (SegmentName->getLength())
851 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
852 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000853 if (Tok.isNot(tok::r_paren)) {
854 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
855 return false;
856 }
Warren Huntc3b18962014-04-08 22:30:47 +0000857 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000858 if (Tok.isNot(tok::eof)) {
859 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
860 << PragmaName;
861 return false;
862 }
Warren Huntc3b18962014-04-08 22:30:47 +0000863 PP.Lex(Tok); // eof
864 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
865 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000866 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000867}
868
Reid Kleckner1a711b12014-07-22 00:53:05 +0000869// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000870bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
871 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000872 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
873 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
874 return false;
875 }
876
Reid Kleckner1a711b12014-07-22 00:53:05 +0000877 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
878 PragmaName))
879 return false;
880
881 // Parse either the known section names or the string section name.
882 StringLiteral *SegmentName = nullptr;
883 if (Tok.isAnyIdentifier()) {
884 auto *II = Tok.getIdentifierInfo();
885 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
886 .Case("compiler", "\".CRT$XCC\"")
887 .Case("lib", "\".CRT$XCL\"")
888 .Case("user", "\".CRT$XCU\"")
889 .Default("");
890
891 if (!Section.empty()) {
892 // Pretend the user wrote the appropriate string literal here.
893 Token Toks[1];
894 Toks[0].startToken();
895 Toks[0].setKind(tok::string_literal);
896 Toks[0].setLocation(Tok.getLocation());
897 Toks[0].setLiteralData(Section.data());
898 Toks[0].setLength(Section.size());
899 SegmentName =
900 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
901 PP.Lex(Tok);
902 }
903 } else if (Tok.is(tok::string_literal)) {
904 ExprResult StringResult = ParseStringLiteralExpression();
905 if (StringResult.isInvalid())
906 return false;
907 SegmentName = cast<StringLiteral>(StringResult.get());
908 if (SegmentName->getCharByteWidth() != 1) {
909 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
910 << PragmaName;
911 return false;
912 }
913 // FIXME: Add support for the '[, func-name]' part of the pragma.
914 }
915
916 if (!SegmentName) {
917 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
918 return false;
919 }
920
921 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
922 PragmaName) ||
923 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
924 PragmaName))
925 return false;
926
927 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
928 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000929}
930
Benjamin Kramere003ca22015-10-28 13:54:16 +0000931namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000932struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000933 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000934 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000935 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000936};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000937} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000938
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000939static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
940 std::string PragmaString;
941 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
942 PragmaString = "clang loop ";
943 PragmaString += Option.getIdentifierInfo()->getName();
944 } else {
945 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
946 "Unexpected pragma name");
947 PragmaString = "unroll";
948 }
949 return PragmaString;
950}
951
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000952bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000953 assert(Tok.is(tok::annot_pragma_loop_hint));
954 PragmaLoopHintInfo *Info =
955 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
956
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000957 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
958 Hint.PragmaNameLoc = IdentifierLoc::create(
959 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000960
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000961 // It is possible that the loop hint has no option identifier, such as
962 // #pragma unroll(4).
963 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
964 ? Info->Option.getIdentifierInfo()
965 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000966 Hint.OptionLoc = IdentifierLoc::create(
967 Actions.Context, Info->Option.getLocation(), OptionInfo);
968
David Blaikie2eabcc92016-02-09 18:52:09 +0000969 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000970
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000971 // Return a valid hint if pragma unroll or nounroll were specified
972 // without an argument.
973 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
974 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000975 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000976 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000977 Hint.Range = Info->PragmaName.getLocation();
978 return true;
979 }
980
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000981 // The constant expression is always followed by an eof token, which increases
982 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000983 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000984 "PragmaLoopHintInfo::Toks must contain at least one token.");
985
986 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +0000987 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +0000988 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000989 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +0000990 if (OptionInfo) { // Pragma Unroll does not specify an option.
991 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +0000992 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000993 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
994 .Case("vectorize", true)
995 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +0000996 .Default(false) ||
997 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000998 }
999
Adam Nemet2de463e2016-06-14 12:04:26 +00001000 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001001 // Verify loop hint has an argument.
1002 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001003 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001004 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +00001005 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
1006 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001007 return false;
1008 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001009
1010 // Validate the argument.
1011 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001012 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001013 SourceLocation StateLoc = Toks[0].getLocation();
1014 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001015
1016 bool Valid = StateInfo &&
1017 llvm::StringSwitch<bool>(StateInfo->getName())
1018 .Cases("enable", "disable", true)
1019 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +00001020 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +00001021 .Default(false);
1022 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001023 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +00001024 << /*FullKeyword=*/OptionUnroll
1025 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001026 return false;
1027 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001028 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001029 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1030 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001031 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1032 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001033 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +00001034 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001035 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001036
1037 ExprResult R = ParseConstantExpression();
1038
1039 // Tokens following an error in an ill-formed constant expression will
1040 // remain in the token stream and must be removed.
1041 if (Tok.isNot(tok::eof)) {
1042 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1043 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1044 while (Tok.isNot(tok::eof))
1045 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001046 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001047
1048 ConsumeToken(); // Consume the constant expression eof terminator.
1049
1050 if (R.isInvalid() ||
1051 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1052 return false;
1053
1054 // Argument is a constant expression with an integer type.
1055 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001056 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001057
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001058 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001059 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001060 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001061}
1062
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001063namespace {
1064struct PragmaAttributeInfo {
1065 enum ActionType { Push, Pop };
1066 ParsedAttributes &Attributes;
1067 ActionType Action;
1068 ArrayRef<Token> Tokens;
1069
1070 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1071};
1072
1073#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1074
1075} // end anonymous namespace
1076
1077static StringRef getIdentifier(const Token &Tok) {
1078 if (Tok.is(tok::identifier))
1079 return Tok.getIdentifierInfo()->getName();
1080 const char *S = tok::getKeywordSpelling(Tok.getKind());
1081 if (!S)
1082 return "";
1083 return S;
1084}
1085
1086static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1087 using namespace attr;
1088 switch (Rule) {
1089#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1090 case Value: \
1091 return IsAbstract;
1092#include "clang/Basic/AttrSubMatchRulesList.inc"
1093 }
1094 llvm_unreachable("Invalid attribute subject match rule");
1095 return false;
1096}
1097
1098static void diagnoseExpectedAttributeSubjectSubRule(
1099 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1100 SourceLocation SubRuleLoc) {
1101 auto Diagnostic =
1102 PRef.Diag(SubRuleLoc,
1103 diag::err_pragma_attribute_expected_subject_sub_identifier)
1104 << PrimaryRuleName;
1105 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1106 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1107 else
1108 Diagnostic << /*SubRulesSupported=*/0;
1109}
1110
1111static void diagnoseUnknownAttributeSubjectSubRule(
1112 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1113 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1114
1115 auto Diagnostic =
1116 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1117 << SubRuleName << PrimaryRuleName;
1118 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1119 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1120 else
1121 Diagnostic << /*SubRulesSupported=*/0;
1122}
1123
1124bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1125 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1126 SourceLocation &LastMatchRuleEndLoc) {
1127 bool IsAny = false;
1128 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1129 if (getIdentifier(Tok) == "any") {
1130 AnyLoc = ConsumeToken();
1131 IsAny = true;
1132 if (AnyParens.expectAndConsume())
1133 return true;
1134 }
1135
1136 do {
1137 // Parse the subject matcher rule.
1138 StringRef Name = getIdentifier(Tok);
1139 if (Name.empty()) {
1140 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1141 return true;
1142 }
1143 std::pair<Optional<attr::SubjectMatchRule>,
1144 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1145 Rule = isAttributeSubjectMatchRule(Name);
1146 if (!Rule.first) {
1147 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1148 return true;
1149 }
1150 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1151 SourceLocation RuleLoc = ConsumeToken();
1152
1153 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1154 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1155 if (Parens.expectAndConsume())
1156 return true;
1157 } else if (Parens.consumeOpen()) {
1158 if (!SubjectMatchRules
1159 .insert(
1160 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1161 .second)
1162 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1163 << Name
1164 << FixItHint::CreateRemoval(SourceRange(
1165 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1166 LastMatchRuleEndLoc = RuleLoc;
1167 continue;
1168 }
1169
1170 // Parse the sub-rules.
1171 StringRef SubRuleName = getIdentifier(Tok);
1172 if (SubRuleName.empty()) {
1173 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1174 Tok.getLocation());
1175 return true;
1176 }
1177 attr::SubjectMatchRule SubRule;
1178 if (SubRuleName == "unless") {
1179 SourceLocation SubRuleLoc = ConsumeToken();
1180 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1181 if (Parens.expectAndConsume())
1182 return true;
1183 SubRuleName = getIdentifier(Tok);
1184 if (SubRuleName.empty()) {
1185 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1186 SubRuleLoc);
1187 return true;
1188 }
1189 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1190 if (!SubRuleOrNone) {
1191 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1192 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1193 SubRuleUnlessName, SubRuleLoc);
1194 return true;
1195 }
1196 SubRule = *SubRuleOrNone;
1197 ConsumeToken();
1198 if (Parens.consumeClose())
1199 return true;
1200 } else {
1201 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1202 if (!SubRuleOrNone) {
1203 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1204 SubRuleName, Tok.getLocation());
1205 return true;
1206 }
1207 SubRule = *SubRuleOrNone;
1208 ConsumeToken();
1209 }
1210 SourceLocation RuleEndLoc = Tok.getLocation();
1211 LastMatchRuleEndLoc = RuleEndLoc;
1212 if (Parens.consumeClose())
1213 return true;
1214 if (!SubjectMatchRules
1215 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1216 .second) {
1217 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1218 << attr::getSubjectMatchRuleSpelling(SubRule)
1219 << FixItHint::CreateRemoval(SourceRange(
1220 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1221 continue;
1222 }
1223 } while (IsAny && TryConsumeToken(tok::comma));
1224
1225 if (IsAny)
1226 if (AnyParens.consumeClose())
1227 return true;
1228
1229 return false;
1230}
1231
1232namespace {
1233
1234/// Describes the stage at which attribute subject rule parsing was interruped.
1235enum class MissingAttributeSubjectRulesRecoveryPoint {
1236 Comma,
1237 ApplyTo,
1238 Equals,
1239 Any,
1240 None,
1241};
1242
1243MissingAttributeSubjectRulesRecoveryPoint
1244getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1245 if (const auto *II = Tok.getIdentifierInfo()) {
1246 if (II->isStr("apply_to"))
1247 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1248 if (II->isStr("any"))
1249 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1250 }
1251 if (Tok.is(tok::equal))
1252 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1253 return MissingAttributeSubjectRulesRecoveryPoint::None;
1254}
1255
1256/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1257/// suggests the possible attribute subject rules in a fix-it together with
1258/// any other missing tokens.
1259DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1260 unsigned DiagID, AttributeList &Attribute,
1261 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1262 SourceLocation Loc = PRef.getEndOfPreviousToken();
1263 if (Loc.isInvalid())
1264 Loc = PRef.getCurToken().getLocation();
1265 auto Diagnostic = PRef.Diag(Loc, DiagID);
1266 std::string FixIt;
1267 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1268 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1269 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1270 FixIt = ", ";
1271 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1272 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1273 FixIt += "apply_to";
1274 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1275 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1276 FixIt += " = ";
1277 SourceRange FixItRange(Loc);
1278 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1279 // Gather the subject match rules that are supported by the attribute.
1280 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1281 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1282 if (SubjectMatchRuleSet.empty()) {
1283 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1284 // placeholders will be supported by the fix-its.
1285 return Diagnostic;
1286 }
1287 FixIt += "any(";
1288 bool NeedsComma = false;
1289 for (const auto &I : SubjectMatchRuleSet) {
1290 // Ensure that the missing rule is reported in the fix-it only when it's
1291 // supported in the current language mode.
1292 if (!I.second)
1293 continue;
1294 if (NeedsComma)
1295 FixIt += ", ";
1296 else
1297 NeedsComma = true;
1298 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1299 }
1300 FixIt += ")";
1301 // Check if we need to remove the range
1302 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1303 FixItRange.setEnd(PRef.getCurToken().getLocation());
1304 }
1305 if (FixItRange.getBegin() == FixItRange.getEnd())
1306 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1307 else
1308 Diagnostic << FixItHint::CreateReplacement(
1309 CharSourceRange::getCharRange(FixItRange), FixIt);
1310 return Diagnostic;
1311}
1312
1313} // end anonymous namespace
1314
1315void Parser::HandlePragmaAttribute() {
1316 assert(Tok.is(tok::annot_pragma_attribute) &&
1317 "Expected #pragma attribute annotation token");
1318 SourceLocation PragmaLoc = Tok.getLocation();
1319 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1320 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001321 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001322 Actions.ActOnPragmaAttributePop(PragmaLoc);
1323 return;
1324 }
1325 // Parse the actual attribute with its arguments.
1326 assert(Info->Action == PragmaAttributeInfo::Push &&
1327 "Unexpected #pragma attribute command");
1328 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001329 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001330
1331 ParsedAttributes &Attrs = Info->Attributes;
1332 Attrs.clearListOnly();
1333
1334 auto SkipToEnd = [this]() {
1335 SkipUntil(tok::eof, StopBeforeMatch);
1336 ConsumeToken();
1337 };
1338
1339 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1340 // Parse the CXX11 style attribute.
1341 ParseCXX11AttributeSpecifier(Attrs);
1342 } else if (Tok.is(tok::kw___attribute)) {
1343 ConsumeToken();
1344 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1345 "attribute"))
1346 return SkipToEnd();
1347 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1348 return SkipToEnd();
1349
1350 if (Tok.isNot(tok::identifier)) {
1351 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1352 SkipToEnd();
1353 return;
1354 }
1355 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1356 SourceLocation AttrNameLoc = ConsumeToken();
1357
1358 if (Tok.isNot(tok::l_paren))
1359 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1360 AttributeList::AS_GNU);
1361 else
1362 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1363 /*ScopeName=*/nullptr,
1364 /*ScopeLoc=*/SourceLocation(),
1365 AttributeList::AS_GNU,
1366 /*Declarator=*/nullptr);
1367
1368 if (ExpectAndConsume(tok::r_paren))
1369 return SkipToEnd();
1370 if (ExpectAndConsume(tok::r_paren))
1371 return SkipToEnd();
1372 } else if (Tok.is(tok::kw___declspec)) {
1373 ParseMicrosoftDeclSpecs(Attrs);
1374 } else {
1375 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1376 if (Tok.getIdentifierInfo()) {
1377 // If we suspect that this is an attribute suggest the use of
1378 // '__attribute__'.
1379 if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1380 AttributeList::AS_GNU) !=
1381 AttributeList::UnknownAttribute) {
1382 SourceLocation InsertStartLoc = Tok.getLocation();
1383 ConsumeToken();
1384 if (Tok.is(tok::l_paren)) {
1385 ConsumeAnyToken();
1386 SkipUntil(tok::r_paren, StopBeforeMatch);
1387 if (Tok.isNot(tok::r_paren))
1388 return SkipToEnd();
1389 }
1390 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1391 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1392 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1393 }
1394 }
1395 SkipToEnd();
1396 return;
1397 }
1398
1399 if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
1400 SkipToEnd();
1401 return;
1402 }
1403
1404 // Ensure that we don't have more than one attribute.
1405 if (Attrs.getList()->getNext()) {
1406 SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
1407 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1408 SkipToEnd();
1409 return;
1410 }
1411
1412 if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
1413 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1414 << Attrs.getList()->getName();
1415 SkipToEnd();
1416 return;
1417 }
1418 AttributeList &Attribute = *Attrs.getList();
1419
1420 // Parse the subject-list.
1421 if (!TryConsumeToken(tok::comma)) {
1422 createExpectedAttributeSubjectRulesTokenDiagnostic(
1423 diag::err_expected, Attribute,
1424 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1425 << tok::comma;
1426 SkipToEnd();
1427 return;
1428 }
1429
1430 if (Tok.isNot(tok::identifier)) {
1431 createExpectedAttributeSubjectRulesTokenDiagnostic(
1432 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1433 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1434 SkipToEnd();
1435 return;
1436 }
1437 const IdentifierInfo *II = Tok.getIdentifierInfo();
1438 if (!II->isStr("apply_to")) {
1439 createExpectedAttributeSubjectRulesTokenDiagnostic(
1440 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1441 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1442 SkipToEnd();
1443 return;
1444 }
1445 ConsumeToken();
1446
1447 if (!TryConsumeToken(tok::equal)) {
1448 createExpectedAttributeSubjectRulesTokenDiagnostic(
1449 diag::err_expected, Attribute,
1450 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1451 << tok::equal;
1452 SkipToEnd();
1453 return;
1454 }
1455
1456 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1457 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1458 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1459 LastMatchRuleEndLoc)) {
1460 SkipToEnd();
1461 return;
1462 }
1463
1464 // Tokens following an ill-formed attribute will remain in the token stream
1465 // and must be removed.
1466 if (Tok.isNot(tok::eof)) {
1467 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1468 SkipToEnd();
1469 return;
1470 }
1471
1472 // Consume the eof terminator token.
1473 ConsumeToken();
1474
1475 Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
1476 std::move(SubjectMatchRules));
1477}
1478
Eli Bendersky06a40422014-06-06 20:31:48 +00001479// #pragma GCC visibility comes in two variants:
1480// 'push' '(' [visibility] ')'
1481// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001482void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1483 PragmaIntroducerKind Introducer,
1484 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001485 SourceLocation VisLoc = VisTok.getLocation();
1486
1487 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001488 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001489
1490 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1491
Eli Friedman570024a2010-08-05 06:57:20 +00001492 const IdentifierInfo *VisType;
1493 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001494 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001495 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001496 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001497 if (Tok.isNot(tok::l_paren)) {
1498 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1499 << "visibility";
1500 return;
1501 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001502 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001503 VisType = Tok.getIdentifierInfo();
1504 if (!VisType) {
1505 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1506 << "visibility";
1507 return;
1508 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001509 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001510 if (Tok.isNot(tok::r_paren)) {
1511 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1512 << "visibility";
1513 return;
1514 }
1515 } else {
1516 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1517 << "visibility";
1518 return;
1519 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001520 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001521 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001522 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001523 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1524 << "visibility";
1525 return;
1526 }
1527
David Blaikie2eabcc92016-02-09 18:52:09 +00001528 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001529 Toks[0].startToken();
1530 Toks[0].setKind(tok::annot_pragma_vis);
1531 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001532 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001533 Toks[0].setAnnotationValue(
1534 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001535 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001536}
1537
Daniel Dunbar921b9682008-10-04 19:21:03 +00001538// #pragma pack(...) comes in the following delicious flavors:
1539// pack '(' [integer] ')'
1540// pack '(' 'show' ')'
1541// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001542void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1543 PragmaIntroducerKind Introducer,
1544 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001545 SourceLocation PackLoc = PackTok.getLocation();
1546
1547 Token Tok;
1548 PP.Lex(Tok);
1549 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001550 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001551 return;
1552 }
1553
Denis Zobnin10c4f452016-04-29 18:17:40 +00001554 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1555 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001556 Token Alignment;
1557 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001558 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001559 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001560 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001561
1562 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001563
1564 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1565 // the push/pop stack.
1566 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001567 Action =
1568 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001569 } else if (Tok.is(tok::identifier)) {
1570 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001571 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001572 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001573 PP.Lex(Tok);
1574 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001575 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001576 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001577 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001578 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001579 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001580 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001581 return;
Mike Stump11289f42009-09-09 15:08:12 +00001582 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001583 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001584
Daniel Dunbar921b9682008-10-04 19:21:03 +00001585 if (Tok.is(tok::comma)) {
1586 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001587
Daniel Dunbar921b9682008-10-04 19:21:03 +00001588 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001589 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001590 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001591
1592 PP.Lex(Tok);
1593 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001594 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001595 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001596
Daniel Dunbar921b9682008-10-04 19:21:03 +00001597 if (Tok.is(tok::comma)) {
1598 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001599
Daniel Dunbar921b9682008-10-04 19:21:03 +00001600 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001601 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001602 return;
1603 }
Mike Stump11289f42009-09-09 15:08:12 +00001604
Denis Zobnin10c4f452016-04-29 18:17:40 +00001605 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001606 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001607
1608 PP.Lex(Tok);
1609 }
1610 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001611 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001612 return;
1613 }
1614 }
1615 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001616 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001617 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1618 // the push/pop stack.
1619 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001620 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001621 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001622
1623 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001624 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001625 return;
1626 }
1627
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001628 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001629 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001630 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001631 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1632 return;
1633 }
1634
David Blaikie2eabcc92016-02-09 18:52:09 +00001635 PragmaPackInfo *Info =
1636 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001637 Info->Action = Action;
1638 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001639 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001640
David Blaikie2eabcc92016-02-09 18:52:09 +00001641 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1642 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001643 Toks[0].startToken();
1644 Toks[0].setKind(tok::annot_pragma_pack);
1645 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001646 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001647 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001648 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001649}
1650
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001651// #pragma ms_struct on
1652// #pragma ms_struct off
1653void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1654 PragmaIntroducerKind Introducer,
1655 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001656 PragmaMSStructKind Kind = PMSST_OFF;
1657
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001658 Token Tok;
1659 PP.Lex(Tok);
1660 if (Tok.isNot(tok::identifier)) {
1661 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1662 return;
1663 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001664 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001665 const IdentifierInfo *II = Tok.getIdentifierInfo();
1666 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001667 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001668 PP.Lex(Tok);
1669 }
1670 else if (II->isStr("off") || II->isStr("reset"))
1671 PP.Lex(Tok);
1672 else {
1673 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1674 return;
1675 }
1676
1677 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001678 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1679 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001680 return;
1681 }
Eli Friedman68be1642012-10-04 02:36:51 +00001682
David Blaikie2eabcc92016-02-09 18:52:09 +00001683 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1684 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001685 Toks[0].startToken();
1686 Toks[0].setKind(tok::annot_pragma_msstruct);
1687 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001688 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001689 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1690 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001691 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001692}
1693
Javed Absar2a67c9e2017-06-05 10:11:57 +00001694// #pragma clang section bss="abc" data="" rodata="def" text=""
1695void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1696 PragmaIntroducerKind Introducer, Token &FirstToken) {
1697
1698 Token Tok;
1699 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1700
1701 PP.Lex(Tok); // eat 'section'
1702 while (Tok.isNot(tok::eod)) {
1703 if (Tok.isNot(tok::identifier)) {
1704 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1705 return;
1706 }
1707
1708 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1709 if (SecType->isStr("bss"))
1710 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1711 else if (SecType->isStr("data"))
1712 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1713 else if (SecType->isStr("rodata"))
1714 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1715 else if (SecType->isStr("text"))
1716 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1717 else {
1718 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1719 return;
1720 }
1721
1722 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1723 if (Tok.isNot(tok::equal)) {
1724 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1725 return;
1726 }
1727
1728 std::string SecName;
1729 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1730 return;
1731
1732 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1733 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1734 Sema::PragmaClangSectionAction::PCSA_Clear),
1735 SecKind, SecName);
1736 }
1737}
1738
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001739// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1740// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001741static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001742 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001743 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001744
1745 if (IsOptions) {
1746 PP.Lex(Tok);
1747 if (Tok.isNot(tok::identifier) ||
1748 !Tok.getIdentifierInfo()->isStr("align")) {
1749 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1750 return;
1751 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001752 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001753
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001754 PP.Lex(Tok);
1755 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001756 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1757 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001758 return;
1759 }
1760
1761 PP.Lex(Tok);
1762 if (Tok.isNot(tok::identifier)) {
1763 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001764 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001765 return;
1766 }
1767
John McCallfaf5fb42010-08-26 23:41:50 +00001768 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001769 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001770 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001771 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001772 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001773 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001774 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001775 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001776 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001777 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001778 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001779 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001780 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001781 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001782 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001783 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1784 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001785 return;
1786 }
1787
David Majnemera8f2f1d2015-03-19 00:10:23 +00001788 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001789 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001790 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001791 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001792 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001793 return;
1794 }
1795
David Blaikie2eabcc92016-02-09 18:52:09 +00001796 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1797 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001798 Toks[0].startToken();
1799 Toks[0].setKind(tok::annot_pragma_align);
1800 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001801 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001802 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1803 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001804 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001805}
1806
Douglas Gregorc7d65762010-09-09 22:45:38 +00001807void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1808 PragmaIntroducerKind Introducer,
1809 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001810 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001811}
1812
Douglas Gregorc7d65762010-09-09 22:45:38 +00001813void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1814 PragmaIntroducerKind Introducer,
1815 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001816 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001817}
1818
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001819// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001820void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1821 PragmaIntroducerKind Introducer,
1822 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001823 // FIXME: Should we be expanding macros here? My guess is no.
1824 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001825
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001826 // Lex the left '('.
1827 Token Tok;
1828 PP.Lex(Tok);
1829 if (Tok.isNot(tok::l_paren)) {
1830 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1831 return;
1832 }
Mike Stump11289f42009-09-09 15:08:12 +00001833
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001834 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001835 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001836 SourceLocation RParenLoc;
1837 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001838
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001839 while (true) {
1840 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001841
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001842 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001843 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001844 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001845 LexID = false;
1846 continue;
1847 }
1848
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001849 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001850 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1851 return;
1852 }
Mike Stump11289f42009-09-09 15:08:12 +00001853
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001854 // We are execting a ')' or a ','.
1855 if (Tok.is(tok::comma)) {
1856 LexID = true;
1857 continue;
1858 }
Mike Stump11289f42009-09-09 15:08:12 +00001859
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001860 if (Tok.is(tok::r_paren)) {
1861 RParenLoc = Tok.getLocation();
1862 break;
1863 }
Mike Stump11289f42009-09-09 15:08:12 +00001864
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001865 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001866 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001867 return;
1868 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001869
1870 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001871 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001872 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1873 "unused";
1874 return;
1875 }
1876
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001877 // Verify that we have a location for the right parenthesis.
1878 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001879 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001880
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001881 // For each identifier token, insert into the token stream a
1882 // annot_pragma_unused token followed by the identifier token.
1883 // This allows us to cache a "#pragma unused" that occurs inside an inline
1884 // C++ member function.
1885
David Blaikie2eabcc92016-02-09 18:52:09 +00001886 MutableArrayRef<Token> Toks(
1887 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1888 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001889 for (unsigned i=0; i != Identifiers.size(); i++) {
1890 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1891 pragmaUnusedTok.startToken();
1892 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1893 pragmaUnusedTok.setLocation(UnusedLoc);
1894 idTok = Identifiers[i];
1895 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001896 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001897}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001898
1899// #pragma weak identifier
1900// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001901void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1902 PragmaIntroducerKind Introducer,
1903 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001904 SourceLocation WeakLoc = WeakTok.getLocation();
1905
1906 Token Tok;
1907 PP.Lex(Tok);
1908 if (Tok.isNot(tok::identifier)) {
1909 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1910 return;
1911 }
1912
Eli Friedman68be1642012-10-04 02:36:51 +00001913 Token WeakName = Tok;
1914 bool HasAlias = false;
1915 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001916
1917 PP.Lex(Tok);
1918 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001919 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001920 PP.Lex(Tok);
1921 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001922 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001923 << "weak";
1924 return;
1925 }
Eli Friedman68be1642012-10-04 02:36:51 +00001926 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001927 PP.Lex(Tok);
1928 }
1929
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001930 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001931 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1932 return;
1933 }
1934
Eli Friedman68be1642012-10-04 02:36:51 +00001935 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001936 MutableArrayRef<Token> Toks(
1937 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001938 Token &pragmaUnusedTok = Toks[0];
1939 pragmaUnusedTok.startToken();
1940 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1941 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001942 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001943 Toks[1] = WeakName;
1944 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001945 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001946 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001947 MutableArrayRef<Token> Toks(
1948 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001949 Token &pragmaUnusedTok = Toks[0];
1950 pragmaUnusedTok.startToken();
1951 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1952 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001953 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001954 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001955 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001956 }
1957}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001958
David Chisnall0867d9c2012-02-18 16:12:34 +00001959// #pragma redefine_extname identifier identifier
1960void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1961 PragmaIntroducerKind Introducer,
1962 Token &RedefToken) {
1963 SourceLocation RedefLoc = RedefToken.getLocation();
1964
1965 Token Tok;
1966 PP.Lex(Tok);
1967 if (Tok.isNot(tok::identifier)) {
1968 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1969 "redefine_extname";
1970 return;
1971 }
1972
Eli Friedman68be1642012-10-04 02:36:51 +00001973 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001974 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001975
David Chisnall0867d9c2012-02-18 16:12:34 +00001976 if (Tok.isNot(tok::identifier)) {
1977 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1978 << "redefine_extname";
1979 return;
1980 }
Eli Friedman68be1642012-10-04 02:36:51 +00001981
1982 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001983 PP.Lex(Tok);
1984
1985 if (Tok.isNot(tok::eod)) {
1986 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1987 "redefine_extname";
1988 return;
1989 }
1990
David Blaikie2eabcc92016-02-09 18:52:09 +00001991 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1992 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001993 Token &pragmaRedefTok = Toks[0];
1994 pragmaRedefTok.startToken();
1995 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1996 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001997 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001998 Toks[1] = RedefName;
1999 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00002000 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00002001}
2002
2003
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002004void
2005PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2006 PragmaIntroducerKind Introducer,
2007 Token &Tok) {
2008 tok::OnOffSwitch OOS;
2009 if (PP.LexOnOffSwitch(OOS))
2010 return;
2011
David Blaikie2eabcc92016-02-09 18:52:09 +00002012 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2013 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002014 Toks[0].startToken();
2015 Toks[0].setKind(tok::annot_pragma_fp_contract);
2016 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002017 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002018 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2019 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00002020 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002021}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002022
2023void
2024PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2025 PragmaIntroducerKind Introducer,
2026 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002027 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002028 if (Tok.isNot(tok::identifier)) {
2029 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2030 "OPENCL";
2031 return;
2032 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002033 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002034 SourceLocation NameLoc = Tok.getLocation();
2035
2036 PP.Lex(Tok);
2037 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002038 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002039 return;
2040 }
2041
2042 PP.Lex(Tok);
2043 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002044 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002045 return;
2046 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002047 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002048
Yaxun Liu5b746652016-12-18 05:18:55 +00002049 OpenCLExtState State;
2050 if (Pred->isStr("enable")) {
2051 State = Enable;
2052 } else if (Pred->isStr("disable")) {
2053 State = Disable;
2054 } else if (Pred->isStr("begin"))
2055 State = Begin;
2056 else if (Pred->isStr("end"))
2057 State = End;
2058 else {
2059 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2060 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002061 return;
2062 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002063 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002064
Eli Friedman68be1642012-10-04 02:36:51 +00002065 PP.Lex(Tok);
2066 if (Tok.isNot(tok::eod)) {
2067 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2068 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002069 return;
2070 }
Eli Friedman68be1642012-10-04 02:36:51 +00002071
Yaxun Liu5b746652016-12-18 05:18:55 +00002072 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2073 Info->first = Ext;
2074 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002075 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2076 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002077 Toks[0].startToken();
2078 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2079 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002080 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002081 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00002082 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002083
2084 if (PP.getPPCallbacks())
Yaxun Liu5b746652016-12-18 05:18:55 +00002085 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2086 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002087}
2088
Alexey Bataeva769e072013-03-22 06:34:35 +00002089/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
2090///
2091void
2092PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2093 PragmaIntroducerKind Introducer,
2094 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002095 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2096 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002097 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002098 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2099 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002100 }
2101 PP.DiscardUntilEndOfDirective();
2102}
2103
2104/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
2105///
2106void
2107PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2108 PragmaIntroducerKind Introducer,
2109 Token &FirstTok) {
2110 SmallVector<Token, 16> Pragma;
2111 Token Tok;
2112 Tok.startToken();
2113 Tok.setKind(tok::annot_pragma_openmp);
2114 Tok.setLocation(FirstTok.getLocation());
2115
2116 while (Tok.isNot(tok::eod)) {
2117 Pragma.push_back(Tok);
2118 PP.Lex(Tok);
2119 }
2120 SourceLocation EodLoc = Tok.getLocation();
2121 Tok.startToken();
2122 Tok.setKind(tok::annot_pragma_openmp_end);
2123 Tok.setLocation(EodLoc);
2124 Pragma.push_back(Tok);
2125
David Blaikie2eabcc92016-02-09 18:52:09 +00002126 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
2127 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2128 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2129 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002130}
Reid Kleckner002562a2013-05-06 21:02:12 +00002131
David Majnemer4bb09802014-02-10 19:50:15 +00002132/// \brief Handle '#pragma pointers_to_members'
2133// The grammar for this pragma is as follows:
2134//
2135// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2136//
2137// #pragma pointers_to_members '(' 'best_case' ')'
2138// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2139// #pragma pointers_to_members '(' inheritance-model ')'
2140void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2141 PragmaIntroducerKind Introducer,
2142 Token &Tok) {
2143 SourceLocation PointersToMembersLoc = Tok.getLocation();
2144 PP.Lex(Tok);
2145 if (Tok.isNot(tok::l_paren)) {
2146 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2147 << "pointers_to_members";
2148 return;
2149 }
2150 PP.Lex(Tok);
2151 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2152 if (!Arg) {
2153 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2154 << "pointers_to_members";
2155 return;
2156 }
2157 PP.Lex(Tok);
2158
David Majnemer86c318f2014-02-11 21:05:00 +00002159 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002160 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002161 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002162 } else {
2163 if (Arg->isStr("full_generality")) {
2164 if (Tok.is(tok::comma)) {
2165 PP.Lex(Tok);
2166
2167 Arg = Tok.getIdentifierInfo();
2168 if (!Arg) {
2169 PP.Diag(Tok.getLocation(),
2170 diag::err_pragma_pointers_to_members_unknown_kind)
2171 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2172 return;
2173 }
2174 PP.Lex(Tok);
2175 } else if (Tok.is(tok::r_paren)) {
2176 // #pragma pointers_to_members(full_generality) implicitly specifies
2177 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002178 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002179 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002180 } else {
2181 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2182 << "full_generality";
2183 return;
2184 }
2185 }
2186
2187 if (Arg) {
2188 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002189 RepresentationMethod =
2190 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002191 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002192 RepresentationMethod =
2193 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002194 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002195 RepresentationMethod =
2196 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002197 } else {
2198 PP.Diag(Tok.getLocation(),
2199 diag::err_pragma_pointers_to_members_unknown_kind)
2200 << Arg << /*HasPointerDeclaration*/ 1;
2201 return;
2202 }
2203 }
2204 }
2205
2206 if (Tok.isNot(tok::r_paren)) {
2207 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2208 << (Arg ? Arg->getName() : "full_generality");
2209 return;
2210 }
2211
David Majnemera8f2f1d2015-03-19 00:10:23 +00002212 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002213 PP.Lex(Tok);
2214 if (Tok.isNot(tok::eod)) {
2215 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2216 << "pointers_to_members";
2217 return;
2218 }
2219
2220 Token AnnotTok;
2221 AnnotTok.startToken();
2222 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2223 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002224 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002225 AnnotTok.setAnnotationValue(
2226 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2227 PP.EnterToken(AnnotTok);
2228}
2229
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002230/// \brief Handle '#pragma vtordisp'
2231// The grammar for this pragma is as follows:
2232//
2233// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2234//
2235// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2236// #pragma vtordisp '(' 'pop' ')'
2237// #pragma vtordisp '(' ')'
2238void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2239 PragmaIntroducerKind Introducer,
2240 Token &Tok) {
2241 SourceLocation VtorDispLoc = Tok.getLocation();
2242 PP.Lex(Tok);
2243 if (Tok.isNot(tok::l_paren)) {
2244 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2245 return;
2246 }
2247 PP.Lex(Tok);
2248
Denis Zobnin2290dac2016-04-29 11:27:00 +00002249 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002250 const IdentifierInfo *II = Tok.getIdentifierInfo();
2251 if (II) {
2252 if (II->isStr("push")) {
2253 // #pragma vtordisp(push, mode)
2254 PP.Lex(Tok);
2255 if (Tok.isNot(tok::comma)) {
2256 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2257 return;
2258 }
2259 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002260 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002261 // not push, could be on/off
2262 } else if (II->isStr("pop")) {
2263 // #pragma vtordisp(pop)
2264 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002265 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002266 }
2267 // not push or pop, could be on/off
2268 } else {
2269 if (Tok.is(tok::r_paren)) {
2270 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002271 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002272 }
2273 }
2274
2275
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002276 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002277 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002278 const IdentifierInfo *II = Tok.getIdentifierInfo();
2279 if (II && II->isStr("off")) {
2280 PP.Lex(Tok);
2281 Value = 0;
2282 } else if (II && II->isStr("on")) {
2283 PP.Lex(Tok);
2284 Value = 1;
2285 } else if (Tok.is(tok::numeric_constant) &&
2286 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2287 if (Value > 2) {
2288 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2289 << 0 << 2 << "vtordisp";
2290 return;
2291 }
2292 } else {
2293 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2294 << "vtordisp";
2295 return;
2296 }
2297 }
2298
2299 // Finish the pragma: ')' $
2300 if (Tok.isNot(tok::r_paren)) {
2301 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2302 return;
2303 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002304 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002305 PP.Lex(Tok);
2306 if (Tok.isNot(tok::eod)) {
2307 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2308 << "vtordisp";
2309 return;
2310 }
2311
2312 // Enter the annotation.
2313 Token AnnotTok;
2314 AnnotTok.startToken();
2315 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2316 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002317 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002318 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002319 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002320 PP.EnterToken(AnnotTok);
2321}
2322
Warren Huntc3b18962014-04-08 22:30:47 +00002323/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
2324/// an annotation token.
2325void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2326 PragmaIntroducerKind Introducer,
2327 Token &Tok) {
2328 Token EoF, AnnotTok;
2329 EoF.startToken();
2330 EoF.setKind(tok::eof);
2331 AnnotTok.startToken();
2332 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2333 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002334 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002335 SmallVector<Token, 8> TokenVector;
2336 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002337 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002338 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002339 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2340 }
Warren Huntc3b18962014-04-08 22:30:47 +00002341 // Add a sentinal EoF token to the end of the list.
2342 TokenVector.push_back(EoF);
2343 // We must allocate this array with new because EnterTokenStream is going to
2344 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00002345 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
2346 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002347 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002348 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2349 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002350 AnnotTok.setAnnotationValue(Value);
2351 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002352}
2353
Aaron Ballman5d041be2013-06-04 02:07:14 +00002354/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
2355///
2356/// The syntax is:
2357/// \code
2358/// #pragma detect_mismatch("name", "value")
2359/// \endcode
2360/// Where 'name' and 'value' are quoted strings. The values are embedded in
2361/// the object file and passed along to the linker. If the linker detects a
2362/// mismatch in the object file's values for the given name, a LNK2038 error
2363/// is emitted. See MSDN for more details.
2364void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2365 PragmaIntroducerKind Introducer,
2366 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002367 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002368 PP.Lex(Tok);
2369 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002370 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002371 return;
2372 }
2373
2374 // Read the name to embed, which must be a string literal.
2375 std::string NameString;
2376 if (!PP.LexStringLiteral(Tok, NameString,
2377 "pragma detect_mismatch",
2378 /*MacroExpansion=*/true))
2379 return;
2380
2381 // Read the comma followed by a second string literal.
2382 std::string ValueString;
2383 if (Tok.isNot(tok::comma)) {
2384 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2385 return;
2386 }
2387
2388 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2389 /*MacroExpansion=*/true))
2390 return;
2391
2392 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002393 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002394 return;
2395 }
2396 PP.Lex(Tok); // Eat the r_paren.
2397
2398 if (Tok.isNot(tok::eod)) {
2399 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2400 return;
2401 }
2402
Reid Kleckner71966c92014-02-20 23:37:45 +00002403 // If the pragma is lexically sound, notify any interested PPCallbacks.
2404 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002405 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002406 ValueString);
2407
Nico Webercbbaeb12016-03-02 19:28:54 +00002408 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002409}
2410
Reid Kleckner002562a2013-05-06 21:02:12 +00002411/// \brief Handle the microsoft \#pragma comment extension.
2412///
2413/// The syntax is:
2414/// \code
2415/// #pragma comment(linker, "foo")
2416/// \endcode
2417/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2418/// "foo" is a string, which is fully macro expanded, and permits string
2419/// concatenation, embedded escape characters etc. See MSDN for more details.
2420void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2421 PragmaIntroducerKind Introducer,
2422 Token &Tok) {
2423 SourceLocation CommentLoc = Tok.getLocation();
2424 PP.Lex(Tok);
2425 if (Tok.isNot(tok::l_paren)) {
2426 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2427 return;
2428 }
2429
2430 // Read the identifier.
2431 PP.Lex(Tok);
2432 if (Tok.isNot(tok::identifier)) {
2433 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2434 return;
2435 }
2436
2437 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002438 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002439 PragmaMSCommentKind Kind =
2440 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2441 .Case("linker", PCK_Linker)
2442 .Case("lib", PCK_Lib)
2443 .Case("compiler", PCK_Compiler)
2444 .Case("exestr", PCK_ExeStr)
2445 .Case("user", PCK_User)
2446 .Default(PCK_Unknown);
2447 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002448 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2449 return;
2450 }
2451
Yunzhong Gao99efc032015-03-23 20:41:42 +00002452 // On PS4, issue a warning about any pragma comments other than
2453 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002454 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002455 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2456 << II->getName();
2457 return;
2458 }
2459
Reid Kleckner002562a2013-05-06 21:02:12 +00002460 // Read the optional string if present.
2461 PP.Lex(Tok);
2462 std::string ArgumentString;
2463 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2464 "pragma comment",
2465 /*MacroExpansion=*/true))
2466 return;
2467
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002468 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002469 // FIXME: If the kind is "compiler" warn if the string is present (it is
2470 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002471 // The MSDN docs say that "lib" and "linker" require a string and have a short
2472 // whitelist of linker options they support, but in practice MSVC doesn't
2473 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002474
2475 if (Tok.isNot(tok::r_paren)) {
2476 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2477 return;
2478 }
2479 PP.Lex(Tok); // eat the r_paren.
2480
2481 if (Tok.isNot(tok::eod)) {
2482 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2483 return;
2484 }
2485
Reid Kleckner71966c92014-02-20 23:37:45 +00002486 // If the pragma is lexically sound, notify any interested PPCallbacks.
2487 if (PP.getPPCallbacks())
2488 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2489
Nico Weber66220292016-03-02 17:28:48 +00002490 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002491}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002492
2493// #pragma clang optimize off
2494// #pragma clang optimize on
2495void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2496 PragmaIntroducerKind Introducer,
2497 Token &FirstToken) {
2498 Token Tok;
2499 PP.Lex(Tok);
2500 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002501 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002502 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002503 return;
2504 }
2505 if (Tok.isNot(tok::identifier)) {
2506 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2507 << PP.getSpelling(Tok);
2508 return;
2509 }
2510 const IdentifierInfo *II = Tok.getIdentifierInfo();
2511 // The only accepted values are 'on' or 'off'.
2512 bool IsOn = false;
2513 if (II->isStr("on")) {
2514 IsOn = true;
2515 } else if (!II->isStr("off")) {
2516 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2517 << PP.getSpelling(Tok);
2518 return;
2519 }
2520 PP.Lex(Tok);
2521
2522 if (Tok.isNot(tok::eod)) {
2523 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2524 << PP.getSpelling(Tok);
2525 return;
2526 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002527
2528 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2529}
2530
Adam Nemet60d32642017-04-04 21:18:36 +00002531namespace {
2532/// Used as the annotation value for tok::annot_pragma_fp.
2533struct TokFPAnnotValue {
2534 enum FlagKinds { Contract };
2535 enum FlagValues { On, Off, Fast };
2536
2537 FlagKinds FlagKind;
2538 FlagValues FlagValue;
2539};
2540} // end anonymous namespace
2541
2542void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2543 PragmaIntroducerKind Introducer,
2544 Token &Tok) {
2545 // fp
2546 Token PragmaName = Tok;
2547 SmallVector<Token, 1> TokenList;
2548
2549 PP.Lex(Tok);
2550 if (Tok.isNot(tok::identifier)) {
2551 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2552 << /*MissingOption=*/true << "";
2553 return;
2554 }
2555
2556 while (Tok.is(tok::identifier)) {
2557 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2558
2559 auto FlagKind =
2560 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2561 OptionInfo->getName())
2562 .Case("contract", TokFPAnnotValue::Contract)
2563 .Default(None);
2564 if (!FlagKind) {
2565 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2566 << /*MissingOption=*/false << OptionInfo;
2567 return;
2568 }
2569 PP.Lex(Tok);
2570
2571 // Read '('
2572 if (Tok.isNot(tok::l_paren)) {
2573 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2574 return;
2575 }
2576 PP.Lex(Tok);
2577
2578 if (Tok.isNot(tok::identifier)) {
2579 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2580 << PP.getSpelling(Tok) << OptionInfo->getName();
2581 return;
2582 }
2583 const IdentifierInfo *II = Tok.getIdentifierInfo();
2584
2585 auto FlagValue =
2586 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2587 II->getName())
2588 .Case("on", TokFPAnnotValue::On)
2589 .Case("off", TokFPAnnotValue::Off)
2590 .Case("fast", TokFPAnnotValue::Fast)
2591 .Default(llvm::None);
2592
2593 if (!FlagValue) {
2594 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2595 << PP.getSpelling(Tok) << OptionInfo->getName();
2596 return;
2597 }
2598 PP.Lex(Tok);
2599
2600 // Read ')'
2601 if (Tok.isNot(tok::r_paren)) {
2602 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2603 return;
2604 }
2605 PP.Lex(Tok);
2606
2607 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2608 TokFPAnnotValue{*FlagKind, *FlagValue};
2609 // Generate the loop hint token.
2610 Token FPTok;
2611 FPTok.startToken();
2612 FPTok.setKind(tok::annot_pragma_fp);
2613 FPTok.setLocation(PragmaName.getLocation());
2614 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2615 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2616 TokenList.push_back(FPTok);
2617 }
2618
2619 if (Tok.isNot(tok::eod)) {
2620 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2621 << "clang fp";
2622 return;
2623 }
2624
2625 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2626 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2627
2628 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2629 /*DisableMacroExpansion=*/false);
2630}
2631
2632void Parser::HandlePragmaFP() {
2633 assert(Tok.is(tok::annot_pragma_fp));
2634 auto *AnnotValue =
2635 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2636
2637 LangOptions::FPContractModeKind FPC;
2638 switch (AnnotValue->FlagValue) {
2639 case TokFPAnnotValue::On:
2640 FPC = LangOptions::FPC_On;
2641 break;
2642 case TokFPAnnotValue::Fast:
2643 FPC = LangOptions::FPC_Fast;
2644 break;
2645 case TokFPAnnotValue::Off:
2646 FPC = LangOptions::FPC_Off;
2647 break;
2648 }
2649
2650 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002651 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002652}
2653
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002654/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002655static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2656 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002657 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002658 SmallVector<Token, 1> ValueList;
2659 int OpenParens = ValueInParens ? 1 : 0;
2660 // Read constant expression.
2661 while (Tok.isNot(tok::eod)) {
2662 if (Tok.is(tok::l_paren))
2663 OpenParens++;
2664 else if (Tok.is(tok::r_paren)) {
2665 OpenParens--;
2666 if (OpenParens == 0 && ValueInParens)
2667 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002668 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002669
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002670 ValueList.push_back(Tok);
2671 PP.Lex(Tok);
2672 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002673
2674 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002675 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002676 if (Tok.isNot(tok::r_paren)) {
2677 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2678 return true;
2679 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002680 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002681 }
2682
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002683 Token EOFTok;
2684 EOFTok.startToken();
2685 EOFTok.setKind(tok::eof);
2686 EOFTok.setLocation(Tok.getLocation());
2687 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2688
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002689 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002690
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002691 Info.PragmaName = PragmaName;
2692 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002693 return false;
2694}
2695
Eli Bendersky06a40422014-06-06 20:31:48 +00002696/// \brief Handle the \#pragma clang loop directive.
2697/// #pragma clang 'loop' loop-hints
2698///
2699/// loop-hints:
2700/// loop-hint loop-hints[opt]
2701///
2702/// loop-hint:
2703/// 'vectorize' '(' loop-hint-keyword ')'
2704/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002705/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002706/// 'vectorize_width' '(' loop-hint-value ')'
2707/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002708/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002709///
2710/// loop-hint-keyword:
2711/// 'enable'
2712/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002713/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002714///
Mark Heffernan450c2382014-07-23 17:31:31 +00002715/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002716/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002717/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002718/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002719///
Eli Bendersky06a40422014-06-06 20:31:48 +00002720/// loop-hint-value:
2721/// constant-expression
2722///
2723/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2724/// try vectorizing the instructions of the loop it precedes. Specifying
2725/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2726/// interleaving multiple iterations of the loop it precedes. The width of the
2727/// vector instructions is specified by vectorize_width() and the number of
2728/// interleaved loop iterations is specified by interleave_count(). Specifying a
2729/// value of 1 effectively disables vectorization/interleaving, even if it is
2730/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2731/// only works on inner loops.
2732///
Eli Bendersky86483b32014-06-11 17:56:26 +00002733/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002734/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2735/// completely if the trip count is known at compile time and unroll partially
2736/// if the trip count is not known. Specifying unroll(full) is similar to
2737/// unroll(enable) but will unroll the loop only if the trip count is known at
2738/// compile time. Specifying unroll(disable) disables unrolling for the
2739/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2740/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002741void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2742 PragmaIntroducerKind Introducer,
2743 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002744 // Incoming token is "loop" from "#pragma clang loop".
2745 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002746 SmallVector<Token, 1> TokenList;
2747
2748 // Lex the optimization option and verify it is an identifier.
2749 PP.Lex(Tok);
2750 if (Tok.isNot(tok::identifier)) {
2751 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2752 << /*MissingOption=*/true << "";
2753 return;
2754 }
2755
2756 while (Tok.is(tok::identifier)) {
2757 Token Option = Tok;
2758 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2759
Eli Bendersky86483b32014-06-11 17:56:26 +00002760 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002761 .Case("vectorize", true)
2762 .Case("interleave", true)
2763 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002764 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002765 .Case("vectorize_width", true)
2766 .Case("interleave_count", true)
2767 .Case("unroll_count", true)
2768 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002769 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002770 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2771 << /*MissingOption=*/false << OptionInfo;
2772 return;
2773 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002774 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002775
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002776 // Read '('
2777 if (Tok.isNot(tok::l_paren)) {
2778 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002779 return;
2780 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002781 PP.Lex(Tok);
2782
2783 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2784 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2785 *Info))
2786 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002787
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002788 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002789 Token LoopHintTok;
2790 LoopHintTok.startToken();
2791 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002792 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002793 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002794 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2795 TokenList.push_back(LoopHintTok);
2796 }
2797
2798 if (Tok.isNot(tok::eod)) {
2799 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2800 << "clang loop";
2801 return;
2802 }
2803
David Blaikie2eabcc92016-02-09 18:52:09 +00002804 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2805 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002806
David Blaikie2eabcc92016-02-09 18:52:09 +00002807 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2808 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002809}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002810
2811/// \brief Handle the loop unroll optimization pragmas.
2812/// #pragma unroll
2813/// #pragma unroll unroll-hint-value
2814/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002815/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002816///
2817/// unroll-hint-value:
2818/// constant-expression
2819///
Mark Heffernanc888e412014-07-24 18:09:38 +00002820/// Loop unrolling hints can be specified with '#pragma unroll' or
2821/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2822/// contained in parentheses. With no argument the directive instructs llvm to
2823/// try to unroll the loop completely. A positive integer argument can be
2824/// specified to indicate the number of times the loop should be unrolled. To
2825/// maximize compatibility with other compilers the unroll count argument can be
2826/// specified with or without parentheses. Specifying, '#pragma nounroll'
2827/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002828void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2829 PragmaIntroducerKind Introducer,
2830 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002831 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2832 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002833 Token PragmaName = Tok;
2834 PP.Lex(Tok);
2835 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2836 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002837 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002838 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002839 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002840 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2841 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2842 << "nounroll";
2843 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002844 } else {
2845 // Unroll pragma with an argument: "#pragma unroll N" or
2846 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002847 // Read '(' if it exists.
2848 bool ValueInParens = Tok.is(tok::l_paren);
2849 if (ValueInParens)
2850 PP.Lex(Tok);
2851
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002852 Token Option;
2853 Option.startToken();
2854 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002855 return;
2856
2857 // In CUDA, the argument to '#pragma unroll' should not be contained in
2858 // parentheses.
2859 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002860 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002861 diag::warn_pragma_unroll_cuda_value_in_parens);
2862
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002863 if (Tok.isNot(tok::eod)) {
2864 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2865 << "unroll";
2866 return;
2867 }
2868 }
2869
2870 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002871 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002872 TokenArray[0].startToken();
2873 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2874 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002875 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002876 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002877 PP.EnterTokenStream(std::move(TokenArray), 1,
2878 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002879}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002880
2881/// \brief Handle the Microsoft \#pragma intrinsic extension.
2882///
2883/// The syntax is:
2884/// \code
2885/// #pragma intrinsic(memset)
2886/// #pragma intrinsic(strlen, memcpy)
2887/// \endcode
2888///
2889/// Pragma intrisic tells the compiler to use a builtin version of the
2890/// function. Clang does it anyway, so the pragma doesn't really do anything.
2891/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2892/// isn't an intrinsic in clang and suggest to include intrin.h.
2893void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2894 PragmaIntroducerKind Introducer,
2895 Token &Tok) {
2896 PP.Lex(Tok);
2897
2898 if (Tok.isNot(tok::l_paren)) {
2899 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2900 << "intrinsic";
2901 return;
2902 }
2903 PP.Lex(Tok);
2904
2905 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2906
2907 while (Tok.is(tok::identifier)) {
2908 IdentifierInfo *II = Tok.getIdentifierInfo();
2909 if (!II->getBuiltinID())
2910 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2911 << II << SuggestIntrinH;
2912
2913 PP.Lex(Tok);
2914 if (Tok.isNot(tok::comma))
2915 break;
2916 PP.Lex(Tok);
2917 }
2918
2919 if (Tok.isNot(tok::r_paren)) {
2920 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2921 << "intrinsic";
2922 return;
2923 }
2924 PP.Lex(Tok);
2925
2926 if (Tok.isNot(tok::eod))
2927 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2928 << "intrinsic";
2929}
Justin Lebar67a78a62016-10-08 22:15:58 +00002930void PragmaForceCUDAHostDeviceHandler::HandlePragma(
2931 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
2932 Token FirstTok = Tok;
2933
2934 PP.Lex(Tok);
2935 IdentifierInfo *Info = Tok.getIdentifierInfo();
2936 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
2937 PP.Diag(FirstTok.getLocation(),
2938 diag::warn_pragma_force_cuda_host_device_bad_arg);
2939 return;
2940 }
2941
2942 if (Info->isStr("begin"))
2943 Actions.PushForceCUDAHostDevice();
2944 else if (!Actions.PopForceCUDAHostDevice())
2945 PP.Diag(FirstTok.getLocation(),
2946 diag::err_pragma_cannot_end_force_cuda_host_device);
2947
2948 PP.Lex(Tok);
2949 if (!Tok.is(tok::eod))
2950 PP.Diag(FirstTok.getLocation(),
2951 diag::warn_pragma_force_cuda_host_device_bad_arg);
2952}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00002953
2954/// \brief Handle the #pragma clang attribute directive.
2955///
2956/// The syntax is:
2957/// \code
2958/// #pragma clang attribute push(attribute, subject-set)
2959/// #pragma clang attribute pop
2960/// \endcode
2961///
2962/// The subject-set clause defines the set of declarations which receive the
2963/// attribute. Its exact syntax is described in the LanguageExtensions document
2964/// in Clang's documentation.
2965///
2966/// This directive instructs the compiler to begin/finish applying the specified
2967/// attribute to the set of attribute-specific declarations in the active range
2968/// of the pragma.
2969void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
2970 PragmaIntroducerKind Introducer,
2971 Token &FirstToken) {
2972 Token Tok;
2973 PP.Lex(Tok);
2974 auto *Info = new (PP.getPreprocessorAllocator())
2975 PragmaAttributeInfo(AttributesForPragmaAttribute);
2976
2977 // Parse the 'push' or 'pop'.
2978 if (Tok.isNot(tok::identifier)) {
2979 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
2980 return;
2981 }
2982 const auto *II = Tok.getIdentifierInfo();
2983 if (II->isStr("push"))
2984 Info->Action = PragmaAttributeInfo::Push;
2985 else if (II->isStr("pop"))
2986 Info->Action = PragmaAttributeInfo::Pop;
2987 else {
2988 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
2989 << PP.getSpelling(Tok);
2990 return;
2991 }
2992 PP.Lex(Tok);
2993
2994 // Parse the actual attribute.
2995 if (Info->Action == PragmaAttributeInfo::Push) {
2996 if (Tok.isNot(tok::l_paren)) {
2997 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2998 return;
2999 }
3000 PP.Lex(Tok);
3001
3002 // Lex the attribute tokens.
3003 SmallVector<Token, 16> AttributeTokens;
3004 int OpenParens = 1;
3005 while (Tok.isNot(tok::eod)) {
3006 if (Tok.is(tok::l_paren))
3007 OpenParens++;
3008 else if (Tok.is(tok::r_paren)) {
3009 OpenParens--;
3010 if (OpenParens == 0)
3011 break;
3012 }
3013
3014 AttributeTokens.push_back(Tok);
3015 PP.Lex(Tok);
3016 }
3017
3018 if (AttributeTokens.empty()) {
3019 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3020 return;
3021 }
3022 if (Tok.isNot(tok::r_paren)) {
3023 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3024 return;
3025 }
3026 SourceLocation EndLoc = Tok.getLocation();
3027 PP.Lex(Tok);
3028
3029 // Terminate the attribute for parsing.
3030 Token EOFTok;
3031 EOFTok.startToken();
3032 EOFTok.setKind(tok::eof);
3033 EOFTok.setLocation(EndLoc);
3034 AttributeTokens.push_back(EOFTok);
3035
3036 Info->Tokens =
3037 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3038 }
3039
3040 if (Tok.isNot(tok::eod))
3041 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3042 << "clang attribute";
3043
3044 // Generate the annotated pragma token.
3045 auto TokenArray = llvm::make_unique<Token[]>(1);
3046 TokenArray[0].startToken();
3047 TokenArray[0].setKind(tok::annot_pragma_attribute);
3048 TokenArray[0].setLocation(FirstToken.getLocation());
3049 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3050 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3051 PP.EnterTokenStream(std::move(TokenArray), 1,
3052 /*DisableMacroExpansion=*/false);
3053}