blob: 2fec665ec114f5dd4bff1bd4bfca3d43287f2b2d [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
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000223struct PragmaMSOptimizeHandler : public PragmaHandler {
224 PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
225 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
226 Token &FirstToken) override;
227};
228
Justin Lebar67a78a62016-10-08 22:15:58 +0000229struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
230 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
231 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
232 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
233 Token &FirstToken) override;
234
235private:
236 Sema &Actions;
237};
238
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000239/// PragmaAttributeHandler - "\#pragma clang attribute ...".
240struct PragmaAttributeHandler : public PragmaHandler {
241 PragmaAttributeHandler(AttributeFactory &AttrFactory)
242 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
243 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
244 Token &FirstToken) override;
245
246 /// A pool of attributes that were parsed in \#pragma clang attribute.
247 ParsedAttributes AttributesForPragmaAttribute;
248};
249
Eli Bendersky06a40422014-06-06 20:31:48 +0000250} // end namespace
251
252void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000253 AlignHandler.reset(new PragmaAlignHandler());
254 PP.AddPragmaHandler(AlignHandler.get());
255
256 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
257 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
258
259 OptionsHandler.reset(new PragmaOptionsHandler());
260 PP.AddPragmaHandler(OptionsHandler.get());
261
262 PackHandler.reset(new PragmaPackHandler());
263 PP.AddPragmaHandler(PackHandler.get());
264
265 MSStructHandler.reset(new PragmaMSStructHandler());
266 PP.AddPragmaHandler(MSStructHandler.get());
267
268 UnusedHandler.reset(new PragmaUnusedHandler());
269 PP.AddPragmaHandler(UnusedHandler.get());
270
271 WeakHandler.reset(new PragmaWeakHandler());
272 PP.AddPragmaHandler(WeakHandler.get());
273
274 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
275 PP.AddPragmaHandler(RedefineExtnameHandler.get());
276
277 FPContractHandler.reset(new PragmaFPContractHandler());
278 PP.AddPragmaHandler("STDC", FPContractHandler.get());
279
Steven Wub96a3a42018-01-05 22:45:03 +0000280 STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler());
281 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
282
283 STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler());
284 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
285
286 STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler());
287 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
288
Javed Absar2a67c9e2017-06-05 10:11:57 +0000289 PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
290 PP.AddPragmaHandler("clang", PCSectionHandler.get());
291
Reid Kleckner5b086462014-02-20 22:52:09 +0000292 if (getLangOpts().OpenCL) {
293 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
294 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
295
296 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
297 }
298 if (getLangOpts().OpenMP)
299 OpenMPHandler.reset(new PragmaOpenMPHandler());
300 else
301 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
302 PP.AddPragmaHandler(OpenMPHandler.get());
303
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000304 if (getLangOpts().MicrosoftExt ||
305 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000306 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
307 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000308 }
309
310 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000311 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
312 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
313 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
314 PP.AddPragmaHandler(MSPointersToMembers.get());
315 MSVtorDisp.reset(new PragmaMSVtorDisp());
316 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000317 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000318 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000319 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
320 PP.AddPragmaHandler(MSDataSeg.get());
321 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
322 PP.AddPragmaHandler(MSBSSSeg.get());
323 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
324 PP.AddPragmaHandler(MSConstSeg.get());
325 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
326 PP.AddPragmaHandler(MSCodeSeg.get());
327 MSSection.reset(new PragmaMSPragma("section"));
328 PP.AddPragmaHandler(MSSection.get());
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000329 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
330 PP.AddPragmaHandler(MSRuntimeChecks.get());
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000331 MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
332 PP.AddPragmaHandler(MSIntrinsic.get());
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000333 MSOptimize.reset(new PragmaMSOptimizeHandler());
334 PP.AddPragmaHandler(MSOptimize.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000335 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000336
Justin Lebar67a78a62016-10-08 22:15:58 +0000337 if (getLangOpts().CUDA) {
338 CUDAForceHostDeviceHandler.reset(
339 new PragmaForceCUDAHostDeviceHandler(Actions));
340 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
341 }
342
Eli Bendersky06a40422014-06-06 20:31:48 +0000343 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
344 PP.AddPragmaHandler("clang", OptimizeHandler.get());
345
346 LoopHintHandler.reset(new PragmaLoopHintHandler());
347 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000348
349 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
350 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000351
352 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
353 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000354
355 FPHandler.reset(new PragmaFPHandler());
356 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000357
358 AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
359 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000360}
361
362void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000363 // Remove the pragma handlers we installed.
364 PP.RemovePragmaHandler(AlignHandler.get());
365 AlignHandler.reset();
366 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
367 GCCVisibilityHandler.reset();
368 PP.RemovePragmaHandler(OptionsHandler.get());
369 OptionsHandler.reset();
370 PP.RemovePragmaHandler(PackHandler.get());
371 PackHandler.reset();
372 PP.RemovePragmaHandler(MSStructHandler.get());
373 MSStructHandler.reset();
374 PP.RemovePragmaHandler(UnusedHandler.get());
375 UnusedHandler.reset();
376 PP.RemovePragmaHandler(WeakHandler.get());
377 WeakHandler.reset();
378 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
379 RedefineExtnameHandler.reset();
380
381 if (getLangOpts().OpenCL) {
382 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
383 OpenCLExtensionHandler.reset();
384 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
385 }
386 PP.RemovePragmaHandler(OpenMPHandler.get());
387 OpenMPHandler.reset();
388
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000389 if (getLangOpts().MicrosoftExt ||
390 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000391 PP.RemovePragmaHandler(MSCommentHandler.get());
392 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000393 }
394
Javed Absar2a67c9e2017-06-05 10:11:57 +0000395 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
396 PCSectionHandler.reset();
397
Yunzhong Gao99efc032015-03-23 20:41:42 +0000398 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000399 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
400 MSDetectMismatchHandler.reset();
401 PP.RemovePragmaHandler(MSPointersToMembers.get());
402 MSPointersToMembers.reset();
403 PP.RemovePragmaHandler(MSVtorDisp.get());
404 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000405 PP.RemovePragmaHandler(MSInitSeg.get());
406 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000407 PP.RemovePragmaHandler(MSDataSeg.get());
408 MSDataSeg.reset();
409 PP.RemovePragmaHandler(MSBSSSeg.get());
410 MSBSSSeg.reset();
411 PP.RemovePragmaHandler(MSConstSeg.get());
412 MSConstSeg.reset();
413 PP.RemovePragmaHandler(MSCodeSeg.get());
414 MSCodeSeg.reset();
415 PP.RemovePragmaHandler(MSSection.get());
416 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000417 PP.RemovePragmaHandler(MSRuntimeChecks.get());
418 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000419 PP.RemovePragmaHandler(MSIntrinsic.get());
420 MSIntrinsic.reset();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000421 PP.RemovePragmaHandler(MSOptimize.get());
422 MSOptimize.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000423 }
424
Justin Lebar67a78a62016-10-08 22:15:58 +0000425 if (getLangOpts().CUDA) {
426 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
427 CUDAForceHostDeviceHandler.reset();
428 }
429
Reid Kleckner5b086462014-02-20 22:52:09 +0000430 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
431 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000432
Steven Wub96a3a42018-01-05 22:45:03 +0000433 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
434 STDCFENVHandler.reset();
435
436 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
437 STDCCXLIMITHandler.reset();
438
439 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
440 STDCUnknownHandler.reset();
441
Eli Bendersky06a40422014-06-06 20:31:48 +0000442 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
443 OptimizeHandler.reset();
444
445 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
446 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000447
448 PP.RemovePragmaHandler(UnrollHintHandler.get());
449 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000450
451 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
452 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000453
454 PP.RemovePragmaHandler("clang", FPHandler.get());
455 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000456
457 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
458 AttributePragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000459}
460
461/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000462///
463/// Each annot_pragma_unused is followed by the argument token so e.g.
464/// "#pragma unused(x,y)" becomes:
465/// annot_pragma_unused 'x' annot_pragma_unused 'y'
466void Parser::HandlePragmaUnused() {
467 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000468 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000469 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
470 ConsumeToken(); // The argument token.
471}
Eli Friedman570024a2010-08-05 06:57:20 +0000472
Rafael Espindola273fd772012-01-26 02:02:57 +0000473void Parser::HandlePragmaVisibility() {
474 assert(Tok.is(tok::annot_pragma_vis));
475 const IdentifierInfo *VisType =
476 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000477 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000478 Actions.ActOnPragmaVisibility(VisType, VisLoc);
479}
480
Benjamin Kramere003ca22015-10-28 13:54:16 +0000481namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000482struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000483 Sema::PragmaMsStackAction Action;
484 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000485 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000486};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000487} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000488
489void Parser::HandlePragmaPack() {
490 assert(Tok.is(tok::annot_pragma_pack));
491 PragmaPackInfo *Info =
492 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000493 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000494 ExprResult Alignment;
495 if (Info->Alignment.is(tok::numeric_constant)) {
496 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000497 if (Alignment.isInvalid()) {
498 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000499 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000500 }
Eli Friedman68be1642012-10-04 02:36:51 +0000501 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000502 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
503 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000504 // Consume the token after processing the pragma to enable pragma-specific
505 // #include warnings.
506 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000507}
508
Eli Friedman68be1642012-10-04 02:36:51 +0000509void Parser::HandlePragmaMSStruct() {
510 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000511 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
512 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000513 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000514 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000515}
516
517void Parser::HandlePragmaAlign() {
518 assert(Tok.is(tok::annot_pragma_align));
519 Sema::PragmaOptionsAlignKind Kind =
520 static_cast<Sema::PragmaOptionsAlignKind>(
521 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Alex Lorenz692821a2018-02-08 21:20:43 +0000522 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
523 // Consume the token after processing the pragma to enable pragma-specific
524 // #include warnings.
525 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000526}
527
Richard Smithba3a4f92016-01-12 21:59:26 +0000528void Parser::HandlePragmaDump() {
529 assert(Tok.is(tok::annot_pragma_dump));
530 IdentifierInfo *II =
531 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
532 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000533 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000534}
535
Eli Friedman68be1642012-10-04 02:36:51 +0000536void Parser::HandlePragmaWeak() {
537 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000538 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000539 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
540 Tok.getLocation());
541 ConsumeToken(); // The weak name.
542}
543
544void Parser::HandlePragmaWeakAlias() {
545 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000546 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000547 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
548 SourceLocation WeakNameLoc = Tok.getLocation();
549 ConsumeToken();
550 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
551 SourceLocation AliasNameLoc = Tok.getLocation();
552 ConsumeToken();
553 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
554 WeakNameLoc, AliasNameLoc);
555
556}
557
558void Parser::HandlePragmaRedefineExtname() {
559 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000560 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000561 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
562 SourceLocation RedefNameLoc = Tok.getLocation();
563 ConsumeToken();
564 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
565 SourceLocation AliasNameLoc = Tok.getLocation();
566 ConsumeToken();
567 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
568 RedefNameLoc, AliasNameLoc);
569}
570
571void Parser::HandlePragmaFPContract() {
572 assert(Tok.is(tok::annot_pragma_fp_contract));
573 tok::OnOffSwitch OOS =
574 static_cast<tok::OnOffSwitch>(
575 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000576
577 LangOptions::FPContractModeKind FPC;
578 switch (OOS) {
579 case tok::OOS_ON:
580 FPC = LangOptions::FPC_On;
581 break;
582 case tok::OOS_OFF:
583 FPC = LangOptions::FPC_Off;
584 break;
585 case tok::OOS_DEFAULT:
586 FPC = getLangOpts().getDefaultFPContractMode();
587 break;
588 }
589
590 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000591 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000592}
593
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000594StmtResult Parser::HandlePragmaCaptured()
595{
596 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000597 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000598
599 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000600 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000601 return StmtError();
602 }
603
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000604 SourceLocation Loc = Tok.getLocation();
605
Momchil Velikov57c681f2017-08-10 15:43:06 +0000606 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
607 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000608 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
609 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000610
611 StmtResult R = ParseCompoundStatement();
612 CapturedRegionScope.Exit();
613
614 if (R.isInvalid()) {
615 Actions.ActOnCapturedRegionError();
616 return StmtError();
617 }
618
619 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000620}
621
Eli Friedman68be1642012-10-04 02:36:51 +0000622namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000623 enum OpenCLExtState : char {
624 Disable, Enable, Begin, End
625 };
626 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000627}
628
629void Parser::HandlePragmaOpenCLExtension() {
630 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000631 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
632 auto State = Data->second;
633 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000634 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000635 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000636
Yaxun Liu5b746652016-12-18 05:18:55 +0000637 auto &Opt = Actions.getOpenCLOptions();
638 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000639 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
640 // overriding all previously issued extension directives, but only if the
641 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000642 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000643 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000644 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000645 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
646 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000647 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000648 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000649 } else if (State == Begin) {
650 if (!Opt.isKnown(Name) ||
651 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
652 Opt.support(Name);
653 }
654 Actions.setCurrentOpenCLExtension(Name);
655 } else if (State == End) {
656 if (Name != Actions.getCurrentOpenCLExtension())
657 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
658 Actions.setCurrentOpenCLExtension("");
659 } else if (!Opt.isKnown(Name))
660 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
661 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
662 Opt.enable(Name, State == Enable);
663 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
664 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
665 else
666 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000667}
668
David Majnemer4bb09802014-02-10 19:50:15 +0000669void Parser::HandlePragmaMSPointersToMembers() {
670 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000671 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
672 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000673 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000674 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000675 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
676}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000677
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000678void Parser::HandlePragmaMSVtorDisp() {
679 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
680 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000681 Sema::PragmaMsStackAction Action =
682 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000683 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000684 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000685 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000686}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000687
Warren Huntc3b18962014-04-08 22:30:47 +0000688void Parser::HandlePragmaMSPragma() {
689 assert(Tok.is(tok::annot_pragma_ms_pragma));
690 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000691 auto TheTokens =
692 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
693 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000694 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000695 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000696 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000697 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000698
Warren Huntc3b18962014-04-08 22:30:47 +0000699 // Figure out which #pragma we're dealing with. The switch has no default
700 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000701 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000702 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
703 .Case("data_seg", &Parser::HandlePragmaMSSegment)
704 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
705 .Case("const_seg", &Parser::HandlePragmaMSSegment)
706 .Case("code_seg", &Parser::HandlePragmaMSSegment)
707 .Case("section", &Parser::HandlePragmaMSSection)
708 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000709
710 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
711 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
712 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000713 while (Tok.isNot(tok::eof))
714 PP.Lex(Tok);
715 PP.Lex(Tok);
716 }
717}
718
Reid Kleckner722b1df2014-07-18 00:13:16 +0000719bool Parser::HandlePragmaMSSection(StringRef PragmaName,
720 SourceLocation PragmaLocation) {
721 if (Tok.isNot(tok::l_paren)) {
722 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
723 return false;
724 }
Warren Huntc3b18962014-04-08 22:30:47 +0000725 PP.Lex(Tok); // (
726 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000727 if (Tok.isNot(tok::string_literal)) {
728 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
729 << PragmaName;
730 return false;
731 }
732 ExprResult StringResult = ParseStringLiteralExpression();
733 if (StringResult.isInvalid())
734 return false; // Already diagnosed.
735 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
736 if (SegmentName->getCharByteWidth() != 1) {
737 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
738 << PragmaName;
739 return false;
740 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000741 int SectionFlags = ASTContext::PSF_Read;
742 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000743 while (Tok.is(tok::comma)) {
744 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000745 // Ignore "long" and "short".
746 // They are undocumented, but widely used, section attributes which appear
747 // to do nothing.
748 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
749 PP.Lex(Tok); // long/short
750 continue;
751 }
752
Reid Kleckner722b1df2014-07-18 00:13:16 +0000753 if (!Tok.isAnyIdentifier()) {
754 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
755 << PragmaName;
756 return false;
757 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000758 ASTContext::PragmaSectionFlag Flag =
759 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000760 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000761 .Case("read", ASTContext::PSF_Read)
762 .Case("write", ASTContext::PSF_Write)
763 .Case("execute", ASTContext::PSF_Execute)
764 .Case("shared", ASTContext::PSF_Invalid)
765 .Case("nopage", ASTContext::PSF_Invalid)
766 .Case("nocache", ASTContext::PSF_Invalid)
767 .Case("discard", ASTContext::PSF_Invalid)
768 .Case("remove", ASTContext::PSF_Invalid)
769 .Default(ASTContext::PSF_None);
770 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
771 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000772 ? diag::warn_pragma_invalid_specific_action
773 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000774 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000775 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000776 }
777 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000778 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000779 PP.Lex(Tok); // Identifier
780 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000781 // If no section attributes are specified, the section will be marked as
782 // read/write.
783 if (SectionFlagsAreDefault)
784 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000785 if (Tok.isNot(tok::r_paren)) {
786 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
787 return false;
788 }
Warren Huntc3b18962014-04-08 22:30:47 +0000789 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000790 if (Tok.isNot(tok::eof)) {
791 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
792 << PragmaName;
793 return false;
794 }
Warren Huntc3b18962014-04-08 22:30:47 +0000795 PP.Lex(Tok); // eof
796 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000797 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000798}
799
Reid Kleckner722b1df2014-07-18 00:13:16 +0000800bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
801 SourceLocation PragmaLocation) {
802 if (Tok.isNot(tok::l_paren)) {
803 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
804 return false;
805 }
Warren Huntc3b18962014-04-08 22:30:47 +0000806 PP.Lex(Tok); // (
807 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000808 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000809 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000810 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000811 if (PushPop == "push")
812 Action = Sema::PSK_Push;
813 else if (PushPop == "pop")
814 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000815 else {
816 PP.Diag(PragmaLocation,
817 diag::warn_pragma_expected_section_push_pop_or_name)
818 << PragmaName;
819 return false;
820 }
Warren Huntc3b18962014-04-08 22:30:47 +0000821 if (Action != Sema::PSK_Reset) {
822 PP.Lex(Tok); // push | pop
823 if (Tok.is(tok::comma)) {
824 PP.Lex(Tok); // ,
825 // If we've got a comma, we either need a label or a string.
826 if (Tok.isAnyIdentifier()) {
827 SlotLabel = Tok.getIdentifierInfo()->getName();
828 PP.Lex(Tok); // identifier
829 if (Tok.is(tok::comma))
830 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000831 else if (Tok.isNot(tok::r_paren)) {
832 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
833 << PragmaName;
834 return false;
835 }
Warren Huntc3b18962014-04-08 22:30:47 +0000836 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000837 } else if (Tok.isNot(tok::r_paren)) {
838 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
839 return false;
840 }
Warren Huntc3b18962014-04-08 22:30:47 +0000841 }
842 }
843 // Grab the string literal for our section name.
844 StringLiteral *SegmentName = nullptr;
845 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000846 if (Tok.isNot(tok::string_literal)) {
847 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000848 diag::warn_pragma_expected_section_name :
849 diag::warn_pragma_expected_section_label_or_name :
850 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000851 PP.Diag(PragmaLocation, DiagID) << PragmaName;
852 return false;
853 }
854 ExprResult StringResult = ParseStringLiteralExpression();
855 if (StringResult.isInvalid())
856 return false; // Already diagnosed.
857 SegmentName = cast<StringLiteral>(StringResult.get());
858 if (SegmentName->getCharByteWidth() != 1) {
859 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
860 << PragmaName;
861 return false;
862 }
Warren Huntc3b18962014-04-08 22:30:47 +0000863 // Setting section "" has no effect
864 if (SegmentName->getLength())
865 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
866 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000867 if (Tok.isNot(tok::r_paren)) {
868 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
869 return false;
870 }
Warren Huntc3b18962014-04-08 22:30:47 +0000871 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000872 if (Tok.isNot(tok::eof)) {
873 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
874 << PragmaName;
875 return false;
876 }
Warren Huntc3b18962014-04-08 22:30:47 +0000877 PP.Lex(Tok); // eof
878 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
879 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000880 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000881}
882
Reid Kleckner1a711b12014-07-22 00:53:05 +0000883// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000884bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
885 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000886 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
887 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
888 return false;
889 }
890
Reid Kleckner1a711b12014-07-22 00:53:05 +0000891 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
892 PragmaName))
893 return false;
894
895 // Parse either the known section names or the string section name.
896 StringLiteral *SegmentName = nullptr;
897 if (Tok.isAnyIdentifier()) {
898 auto *II = Tok.getIdentifierInfo();
899 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
900 .Case("compiler", "\".CRT$XCC\"")
901 .Case("lib", "\".CRT$XCL\"")
902 .Case("user", "\".CRT$XCU\"")
903 .Default("");
904
905 if (!Section.empty()) {
906 // Pretend the user wrote the appropriate string literal here.
907 Token Toks[1];
908 Toks[0].startToken();
909 Toks[0].setKind(tok::string_literal);
910 Toks[0].setLocation(Tok.getLocation());
911 Toks[0].setLiteralData(Section.data());
912 Toks[0].setLength(Section.size());
913 SegmentName =
914 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
915 PP.Lex(Tok);
916 }
917 } else if (Tok.is(tok::string_literal)) {
918 ExprResult StringResult = ParseStringLiteralExpression();
919 if (StringResult.isInvalid())
920 return false;
921 SegmentName = cast<StringLiteral>(StringResult.get());
922 if (SegmentName->getCharByteWidth() != 1) {
923 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
924 << PragmaName;
925 return false;
926 }
927 // FIXME: Add support for the '[, func-name]' part of the pragma.
928 }
929
930 if (!SegmentName) {
931 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
932 return false;
933 }
934
935 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
936 PragmaName) ||
937 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
938 PragmaName))
939 return false;
940
941 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
942 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000943}
944
Benjamin Kramere003ca22015-10-28 13:54:16 +0000945namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000946struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000947 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000948 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000949 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000950};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000951} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000952
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000953static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
954 std::string PragmaString;
955 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
956 PragmaString = "clang loop ";
957 PragmaString += Option.getIdentifierInfo()->getName();
958 } else {
959 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
960 "Unexpected pragma name");
961 PragmaString = "unroll";
962 }
963 return PragmaString;
964}
965
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000966bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000967 assert(Tok.is(tok::annot_pragma_loop_hint));
968 PragmaLoopHintInfo *Info =
969 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
970
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000971 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
972 Hint.PragmaNameLoc = IdentifierLoc::create(
973 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000974
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000975 // It is possible that the loop hint has no option identifier, such as
976 // #pragma unroll(4).
977 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
978 ? Info->Option.getIdentifierInfo()
979 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000980 Hint.OptionLoc = IdentifierLoc::create(
981 Actions.Context, Info->Option.getLocation(), OptionInfo);
982
David Blaikie2eabcc92016-02-09 18:52:09 +0000983 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000984
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000985 // Return a valid hint if pragma unroll or nounroll were specified
986 // without an argument.
987 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
988 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000989 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000990 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000991 Hint.Range = Info->PragmaName.getLocation();
992 return true;
993 }
994
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000995 // The constant expression is always followed by an eof token, which increases
996 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000997 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000998 "PragmaLoopHintInfo::Toks must contain at least one token.");
999
1000 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +00001001 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +00001002 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001003 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +00001004 if (OptionInfo) { // Pragma Unroll does not specify an option.
1005 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +00001006 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001007 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1008 .Case("vectorize", true)
1009 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00001010 .Default(false) ||
1011 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001012 }
1013
Adam Nemet2de463e2016-06-14 12:04:26 +00001014 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001015 // Verify loop hint has an argument.
1016 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001017 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001018 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +00001019 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
1020 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001021 return false;
1022 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001023
1024 // Validate the argument.
1025 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001026 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001027 SourceLocation StateLoc = Toks[0].getLocation();
1028 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001029
1030 bool Valid = StateInfo &&
1031 llvm::StringSwitch<bool>(StateInfo->getName())
1032 .Cases("enable", "disable", true)
1033 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +00001034 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +00001035 .Default(false);
1036 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001037 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +00001038 << /*FullKeyword=*/OptionUnroll
1039 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001040 return false;
1041 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001042 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001043 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1044 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001045 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1046 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001047 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +00001048 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001049 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001050
1051 ExprResult R = ParseConstantExpression();
1052
1053 // Tokens following an error in an ill-formed constant expression will
1054 // remain in the token stream and must be removed.
1055 if (Tok.isNot(tok::eof)) {
1056 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1057 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1058 while (Tok.isNot(tok::eof))
1059 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001060 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001061
1062 ConsumeToken(); // Consume the constant expression eof terminator.
1063
1064 if (R.isInvalid() ||
1065 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1066 return false;
1067
1068 // Argument is a constant expression with an integer type.
1069 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001070 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001071
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001072 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001073 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001074 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001075}
1076
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001077namespace {
1078struct PragmaAttributeInfo {
1079 enum ActionType { Push, Pop };
1080 ParsedAttributes &Attributes;
1081 ActionType Action;
1082 ArrayRef<Token> Tokens;
1083
1084 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1085};
1086
1087#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1088
1089} // end anonymous namespace
1090
1091static StringRef getIdentifier(const Token &Tok) {
1092 if (Tok.is(tok::identifier))
1093 return Tok.getIdentifierInfo()->getName();
1094 const char *S = tok::getKeywordSpelling(Tok.getKind());
1095 if (!S)
1096 return "";
1097 return S;
1098}
1099
1100static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1101 using namespace attr;
1102 switch (Rule) {
1103#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1104 case Value: \
1105 return IsAbstract;
1106#include "clang/Basic/AttrSubMatchRulesList.inc"
1107 }
1108 llvm_unreachable("Invalid attribute subject match rule");
1109 return false;
1110}
1111
1112static void diagnoseExpectedAttributeSubjectSubRule(
1113 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1114 SourceLocation SubRuleLoc) {
1115 auto Diagnostic =
1116 PRef.Diag(SubRuleLoc,
1117 diag::err_pragma_attribute_expected_subject_sub_identifier)
1118 << PrimaryRuleName;
1119 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1120 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1121 else
1122 Diagnostic << /*SubRulesSupported=*/0;
1123}
1124
1125static void diagnoseUnknownAttributeSubjectSubRule(
1126 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1127 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1128
1129 auto Diagnostic =
1130 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1131 << SubRuleName << PrimaryRuleName;
1132 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1133 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1134 else
1135 Diagnostic << /*SubRulesSupported=*/0;
1136}
1137
1138bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1139 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1140 SourceLocation &LastMatchRuleEndLoc) {
1141 bool IsAny = false;
1142 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1143 if (getIdentifier(Tok) == "any") {
1144 AnyLoc = ConsumeToken();
1145 IsAny = true;
1146 if (AnyParens.expectAndConsume())
1147 return true;
1148 }
1149
1150 do {
1151 // Parse the subject matcher rule.
1152 StringRef Name = getIdentifier(Tok);
1153 if (Name.empty()) {
1154 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1155 return true;
1156 }
1157 std::pair<Optional<attr::SubjectMatchRule>,
1158 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1159 Rule = isAttributeSubjectMatchRule(Name);
1160 if (!Rule.first) {
1161 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1162 return true;
1163 }
1164 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1165 SourceLocation RuleLoc = ConsumeToken();
1166
1167 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1168 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1169 if (Parens.expectAndConsume())
1170 return true;
1171 } else if (Parens.consumeOpen()) {
1172 if (!SubjectMatchRules
1173 .insert(
1174 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1175 .second)
1176 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1177 << Name
1178 << FixItHint::CreateRemoval(SourceRange(
1179 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1180 LastMatchRuleEndLoc = RuleLoc;
1181 continue;
1182 }
1183
1184 // Parse the sub-rules.
1185 StringRef SubRuleName = getIdentifier(Tok);
1186 if (SubRuleName.empty()) {
1187 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1188 Tok.getLocation());
1189 return true;
1190 }
1191 attr::SubjectMatchRule SubRule;
1192 if (SubRuleName == "unless") {
1193 SourceLocation SubRuleLoc = ConsumeToken();
1194 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1195 if (Parens.expectAndConsume())
1196 return true;
1197 SubRuleName = getIdentifier(Tok);
1198 if (SubRuleName.empty()) {
1199 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1200 SubRuleLoc);
1201 return true;
1202 }
1203 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1204 if (!SubRuleOrNone) {
1205 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1206 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1207 SubRuleUnlessName, SubRuleLoc);
1208 return true;
1209 }
1210 SubRule = *SubRuleOrNone;
1211 ConsumeToken();
1212 if (Parens.consumeClose())
1213 return true;
1214 } else {
1215 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1216 if (!SubRuleOrNone) {
1217 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1218 SubRuleName, Tok.getLocation());
1219 return true;
1220 }
1221 SubRule = *SubRuleOrNone;
1222 ConsumeToken();
1223 }
1224 SourceLocation RuleEndLoc = Tok.getLocation();
1225 LastMatchRuleEndLoc = RuleEndLoc;
1226 if (Parens.consumeClose())
1227 return true;
1228 if (!SubjectMatchRules
1229 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1230 .second) {
1231 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1232 << attr::getSubjectMatchRuleSpelling(SubRule)
1233 << FixItHint::CreateRemoval(SourceRange(
1234 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1235 continue;
1236 }
1237 } while (IsAny && TryConsumeToken(tok::comma));
1238
1239 if (IsAny)
1240 if (AnyParens.consumeClose())
1241 return true;
1242
1243 return false;
1244}
1245
1246namespace {
1247
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00001248/// Describes the stage at which attribute subject rule parsing was interrupted.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001249enum class MissingAttributeSubjectRulesRecoveryPoint {
1250 Comma,
1251 ApplyTo,
1252 Equals,
1253 Any,
1254 None,
1255};
1256
1257MissingAttributeSubjectRulesRecoveryPoint
1258getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1259 if (const auto *II = Tok.getIdentifierInfo()) {
1260 if (II->isStr("apply_to"))
1261 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1262 if (II->isStr("any"))
1263 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1264 }
1265 if (Tok.is(tok::equal))
1266 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1267 return MissingAttributeSubjectRulesRecoveryPoint::None;
1268}
1269
1270/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1271/// suggests the possible attribute subject rules in a fix-it together with
1272/// any other missing tokens.
1273DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1274 unsigned DiagID, AttributeList &Attribute,
1275 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1276 SourceLocation Loc = PRef.getEndOfPreviousToken();
1277 if (Loc.isInvalid())
1278 Loc = PRef.getCurToken().getLocation();
1279 auto Diagnostic = PRef.Diag(Loc, DiagID);
1280 std::string FixIt;
1281 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1282 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1283 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1284 FixIt = ", ";
1285 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1286 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1287 FixIt += "apply_to";
1288 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1289 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1290 FixIt += " = ";
1291 SourceRange FixItRange(Loc);
1292 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1293 // Gather the subject match rules that are supported by the attribute.
1294 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1295 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1296 if (SubjectMatchRuleSet.empty()) {
1297 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1298 // placeholders will be supported by the fix-its.
1299 return Diagnostic;
1300 }
1301 FixIt += "any(";
1302 bool NeedsComma = false;
1303 for (const auto &I : SubjectMatchRuleSet) {
1304 // Ensure that the missing rule is reported in the fix-it only when it's
1305 // supported in the current language mode.
1306 if (!I.second)
1307 continue;
1308 if (NeedsComma)
1309 FixIt += ", ";
1310 else
1311 NeedsComma = true;
1312 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1313 }
1314 FixIt += ")";
1315 // Check if we need to remove the range
1316 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1317 FixItRange.setEnd(PRef.getCurToken().getLocation());
1318 }
1319 if (FixItRange.getBegin() == FixItRange.getEnd())
1320 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1321 else
1322 Diagnostic << FixItHint::CreateReplacement(
1323 CharSourceRange::getCharRange(FixItRange), FixIt);
1324 return Diagnostic;
1325}
1326
1327} // end anonymous namespace
1328
1329void Parser::HandlePragmaAttribute() {
1330 assert(Tok.is(tok::annot_pragma_attribute) &&
1331 "Expected #pragma attribute annotation token");
1332 SourceLocation PragmaLoc = Tok.getLocation();
1333 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1334 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001335 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001336 Actions.ActOnPragmaAttributePop(PragmaLoc);
1337 return;
1338 }
1339 // Parse the actual attribute with its arguments.
1340 assert(Info->Action == PragmaAttributeInfo::Push &&
1341 "Unexpected #pragma attribute command");
1342 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001343 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001344
1345 ParsedAttributes &Attrs = Info->Attributes;
1346 Attrs.clearListOnly();
1347
1348 auto SkipToEnd = [this]() {
1349 SkipUntil(tok::eof, StopBeforeMatch);
1350 ConsumeToken();
1351 };
1352
1353 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1354 // Parse the CXX11 style attribute.
1355 ParseCXX11AttributeSpecifier(Attrs);
1356 } else if (Tok.is(tok::kw___attribute)) {
1357 ConsumeToken();
1358 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1359 "attribute"))
1360 return SkipToEnd();
1361 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1362 return SkipToEnd();
1363
1364 if (Tok.isNot(tok::identifier)) {
1365 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1366 SkipToEnd();
1367 return;
1368 }
1369 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1370 SourceLocation AttrNameLoc = ConsumeToken();
1371
1372 if (Tok.isNot(tok::l_paren))
1373 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1374 AttributeList::AS_GNU);
1375 else
1376 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1377 /*ScopeName=*/nullptr,
1378 /*ScopeLoc=*/SourceLocation(),
1379 AttributeList::AS_GNU,
1380 /*Declarator=*/nullptr);
1381
1382 if (ExpectAndConsume(tok::r_paren))
1383 return SkipToEnd();
1384 if (ExpectAndConsume(tok::r_paren))
1385 return SkipToEnd();
1386 } else if (Tok.is(tok::kw___declspec)) {
1387 ParseMicrosoftDeclSpecs(Attrs);
1388 } else {
1389 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1390 if (Tok.getIdentifierInfo()) {
1391 // If we suspect that this is an attribute suggest the use of
1392 // '__attribute__'.
1393 if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1394 AttributeList::AS_GNU) !=
1395 AttributeList::UnknownAttribute) {
1396 SourceLocation InsertStartLoc = Tok.getLocation();
1397 ConsumeToken();
1398 if (Tok.is(tok::l_paren)) {
1399 ConsumeAnyToken();
1400 SkipUntil(tok::r_paren, StopBeforeMatch);
1401 if (Tok.isNot(tok::r_paren))
1402 return SkipToEnd();
1403 }
1404 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1405 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1406 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1407 }
1408 }
1409 SkipToEnd();
1410 return;
1411 }
1412
1413 if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
1414 SkipToEnd();
1415 return;
1416 }
1417
1418 // Ensure that we don't have more than one attribute.
1419 if (Attrs.getList()->getNext()) {
1420 SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
1421 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1422 SkipToEnd();
1423 return;
1424 }
1425
1426 if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
1427 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1428 << Attrs.getList()->getName();
1429 SkipToEnd();
1430 return;
1431 }
1432 AttributeList &Attribute = *Attrs.getList();
1433
1434 // Parse the subject-list.
1435 if (!TryConsumeToken(tok::comma)) {
1436 createExpectedAttributeSubjectRulesTokenDiagnostic(
1437 diag::err_expected, Attribute,
1438 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1439 << tok::comma;
1440 SkipToEnd();
1441 return;
1442 }
1443
1444 if (Tok.isNot(tok::identifier)) {
1445 createExpectedAttributeSubjectRulesTokenDiagnostic(
1446 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1447 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1448 SkipToEnd();
1449 return;
1450 }
1451 const IdentifierInfo *II = Tok.getIdentifierInfo();
1452 if (!II->isStr("apply_to")) {
1453 createExpectedAttributeSubjectRulesTokenDiagnostic(
1454 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1455 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1456 SkipToEnd();
1457 return;
1458 }
1459 ConsumeToken();
1460
1461 if (!TryConsumeToken(tok::equal)) {
1462 createExpectedAttributeSubjectRulesTokenDiagnostic(
1463 diag::err_expected, Attribute,
1464 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1465 << tok::equal;
1466 SkipToEnd();
1467 return;
1468 }
1469
1470 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1471 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1472 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1473 LastMatchRuleEndLoc)) {
1474 SkipToEnd();
1475 return;
1476 }
1477
1478 // Tokens following an ill-formed attribute will remain in the token stream
1479 // and must be removed.
1480 if (Tok.isNot(tok::eof)) {
1481 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1482 SkipToEnd();
1483 return;
1484 }
1485
1486 // Consume the eof terminator token.
1487 ConsumeToken();
1488
1489 Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
1490 std::move(SubjectMatchRules));
1491}
1492
Eli Bendersky06a40422014-06-06 20:31:48 +00001493// #pragma GCC visibility comes in two variants:
1494// 'push' '(' [visibility] ')'
1495// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001496void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1497 PragmaIntroducerKind Introducer,
1498 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001499 SourceLocation VisLoc = VisTok.getLocation();
1500
1501 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001502 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001503
1504 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1505
Eli Friedman570024a2010-08-05 06:57:20 +00001506 const IdentifierInfo *VisType;
1507 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001508 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001509 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001510 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001511 if (Tok.isNot(tok::l_paren)) {
1512 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1513 << "visibility";
1514 return;
1515 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001516 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001517 VisType = Tok.getIdentifierInfo();
1518 if (!VisType) {
1519 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1520 << "visibility";
1521 return;
1522 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001523 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001524 if (Tok.isNot(tok::r_paren)) {
1525 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1526 << "visibility";
1527 return;
1528 }
1529 } else {
1530 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1531 << "visibility";
1532 return;
1533 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001534 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001535 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001536 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001537 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1538 << "visibility";
1539 return;
1540 }
1541
David Blaikie2eabcc92016-02-09 18:52:09 +00001542 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001543 Toks[0].startToken();
1544 Toks[0].setKind(tok::annot_pragma_vis);
1545 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001546 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001547 Toks[0].setAnnotationValue(
1548 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001549 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001550}
1551
Daniel Dunbar921b9682008-10-04 19:21:03 +00001552// #pragma pack(...) comes in the following delicious flavors:
1553// pack '(' [integer] ')'
1554// pack '(' 'show' ')'
1555// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001556void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1557 PragmaIntroducerKind Introducer,
1558 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001559 SourceLocation PackLoc = PackTok.getLocation();
1560
1561 Token Tok;
1562 PP.Lex(Tok);
1563 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001564 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001565 return;
1566 }
1567
Denis Zobnin10c4f452016-04-29 18:17:40 +00001568 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1569 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001570 Token Alignment;
1571 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001572 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001573 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001574 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001575
1576 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001577
1578 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1579 // the push/pop stack.
1580 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001581 Action =
1582 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001583 } else if (Tok.is(tok::identifier)) {
1584 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001585 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001586 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001587 PP.Lex(Tok);
1588 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001589 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001590 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001591 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001592 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001593 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001594 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001595 return;
Mike Stump11289f42009-09-09 15:08:12 +00001596 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001597 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001598
Daniel Dunbar921b9682008-10-04 19:21:03 +00001599 if (Tok.is(tok::comma)) {
1600 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001601
Daniel Dunbar921b9682008-10-04 19:21:03 +00001602 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001603 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001604 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001605
1606 PP.Lex(Tok);
1607 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001608 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001609 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001610
Daniel Dunbar921b9682008-10-04 19:21:03 +00001611 if (Tok.is(tok::comma)) {
1612 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001613
Daniel Dunbar921b9682008-10-04 19:21:03 +00001614 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001615 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001616 return;
1617 }
Mike Stump11289f42009-09-09 15:08:12 +00001618
Denis Zobnin10c4f452016-04-29 18:17:40 +00001619 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001620 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001621
1622 PP.Lex(Tok);
1623 }
1624 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001625 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001626 return;
1627 }
1628 }
1629 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001630 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001631 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1632 // the push/pop stack.
1633 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001634 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001635 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001636
1637 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001638 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001639 return;
1640 }
1641
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001642 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001643 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001644 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001645 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1646 return;
1647 }
1648
David Blaikie2eabcc92016-02-09 18:52:09 +00001649 PragmaPackInfo *Info =
1650 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001651 Info->Action = Action;
1652 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001653 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001654
David Blaikie2eabcc92016-02-09 18:52:09 +00001655 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1656 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001657 Toks[0].startToken();
1658 Toks[0].setKind(tok::annot_pragma_pack);
1659 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001660 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001661 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001662 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001663}
1664
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001665// #pragma ms_struct on
1666// #pragma ms_struct off
1667void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1668 PragmaIntroducerKind Introducer,
1669 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001670 PragmaMSStructKind Kind = PMSST_OFF;
1671
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001672 Token Tok;
1673 PP.Lex(Tok);
1674 if (Tok.isNot(tok::identifier)) {
1675 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1676 return;
1677 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001678 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001679 const IdentifierInfo *II = Tok.getIdentifierInfo();
1680 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001681 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001682 PP.Lex(Tok);
1683 }
1684 else if (II->isStr("off") || II->isStr("reset"))
1685 PP.Lex(Tok);
1686 else {
1687 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1688 return;
1689 }
1690
1691 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001692 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1693 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001694 return;
1695 }
Eli Friedman68be1642012-10-04 02:36:51 +00001696
David Blaikie2eabcc92016-02-09 18:52:09 +00001697 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1698 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001699 Toks[0].startToken();
1700 Toks[0].setKind(tok::annot_pragma_msstruct);
1701 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001702 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001703 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1704 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001705 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001706}
1707
Javed Absar2a67c9e2017-06-05 10:11:57 +00001708// #pragma clang section bss="abc" data="" rodata="def" text=""
1709void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1710 PragmaIntroducerKind Introducer, Token &FirstToken) {
1711
1712 Token Tok;
1713 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1714
1715 PP.Lex(Tok); // eat 'section'
1716 while (Tok.isNot(tok::eod)) {
1717 if (Tok.isNot(tok::identifier)) {
1718 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1719 return;
1720 }
1721
1722 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1723 if (SecType->isStr("bss"))
1724 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1725 else if (SecType->isStr("data"))
1726 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1727 else if (SecType->isStr("rodata"))
1728 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1729 else if (SecType->isStr("text"))
1730 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1731 else {
1732 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1733 return;
1734 }
1735
1736 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1737 if (Tok.isNot(tok::equal)) {
1738 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1739 return;
1740 }
1741
1742 std::string SecName;
1743 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1744 return;
1745
1746 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1747 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1748 Sema::PragmaClangSectionAction::PCSA_Clear),
1749 SecKind, SecName);
1750 }
1751}
1752
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001753// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1754// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001755static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001756 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001757 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001758
1759 if (IsOptions) {
1760 PP.Lex(Tok);
1761 if (Tok.isNot(tok::identifier) ||
1762 !Tok.getIdentifierInfo()->isStr("align")) {
1763 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1764 return;
1765 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001766 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001767
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001768 PP.Lex(Tok);
1769 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001770 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1771 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001772 return;
1773 }
1774
1775 PP.Lex(Tok);
1776 if (Tok.isNot(tok::identifier)) {
1777 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001778 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001779 return;
1780 }
1781
John McCallfaf5fb42010-08-26 23:41:50 +00001782 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001783 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001784 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001785 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001786 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001787 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001788 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001789 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001790 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001791 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001792 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001793 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001794 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001795 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001796 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001797 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1798 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001799 return;
1800 }
1801
David Majnemera8f2f1d2015-03-19 00:10:23 +00001802 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001803 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001804 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001805 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001806 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001807 return;
1808 }
1809
David Blaikie2eabcc92016-02-09 18:52:09 +00001810 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1811 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001812 Toks[0].startToken();
1813 Toks[0].setKind(tok::annot_pragma_align);
1814 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001815 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001816 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1817 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001818 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001819}
1820
Douglas Gregorc7d65762010-09-09 22:45:38 +00001821void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1822 PragmaIntroducerKind Introducer,
1823 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001824 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001825}
1826
Douglas Gregorc7d65762010-09-09 22:45:38 +00001827void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1828 PragmaIntroducerKind Introducer,
1829 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001830 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001831}
1832
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001833// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001834void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1835 PragmaIntroducerKind Introducer,
1836 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001837 // FIXME: Should we be expanding macros here? My guess is no.
1838 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001839
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001840 // Lex the left '('.
1841 Token Tok;
1842 PP.Lex(Tok);
1843 if (Tok.isNot(tok::l_paren)) {
1844 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1845 return;
1846 }
Mike Stump11289f42009-09-09 15:08:12 +00001847
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001848 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001849 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001850 SourceLocation RParenLoc;
1851 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001852
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001853 while (true) {
1854 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001855
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001856 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001857 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001858 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001859 LexID = false;
1860 continue;
1861 }
1862
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001863 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001864 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1865 return;
1866 }
Mike Stump11289f42009-09-09 15:08:12 +00001867
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001868 // We are execting a ')' or a ','.
1869 if (Tok.is(tok::comma)) {
1870 LexID = true;
1871 continue;
1872 }
Mike Stump11289f42009-09-09 15:08:12 +00001873
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001874 if (Tok.is(tok::r_paren)) {
1875 RParenLoc = Tok.getLocation();
1876 break;
1877 }
Mike Stump11289f42009-09-09 15:08:12 +00001878
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001879 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001880 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001881 return;
1882 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001883
1884 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001885 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001886 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1887 "unused";
1888 return;
1889 }
1890
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001891 // Verify that we have a location for the right parenthesis.
1892 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001893 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001894
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001895 // For each identifier token, insert into the token stream a
1896 // annot_pragma_unused token followed by the identifier token.
1897 // This allows us to cache a "#pragma unused" that occurs inside an inline
1898 // C++ member function.
1899
David Blaikie2eabcc92016-02-09 18:52:09 +00001900 MutableArrayRef<Token> Toks(
1901 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1902 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001903 for (unsigned i=0; i != Identifiers.size(); i++) {
1904 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1905 pragmaUnusedTok.startToken();
1906 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1907 pragmaUnusedTok.setLocation(UnusedLoc);
1908 idTok = Identifiers[i];
1909 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001910 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001911}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001912
1913// #pragma weak identifier
1914// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001915void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1916 PragmaIntroducerKind Introducer,
1917 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001918 SourceLocation WeakLoc = WeakTok.getLocation();
1919
1920 Token Tok;
1921 PP.Lex(Tok);
1922 if (Tok.isNot(tok::identifier)) {
1923 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1924 return;
1925 }
1926
Eli Friedman68be1642012-10-04 02:36:51 +00001927 Token WeakName = Tok;
1928 bool HasAlias = false;
1929 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001930
1931 PP.Lex(Tok);
1932 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001933 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001934 PP.Lex(Tok);
1935 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001936 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001937 << "weak";
1938 return;
1939 }
Eli Friedman68be1642012-10-04 02:36:51 +00001940 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001941 PP.Lex(Tok);
1942 }
1943
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001944 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001945 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1946 return;
1947 }
1948
Eli Friedman68be1642012-10-04 02:36:51 +00001949 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001950 MutableArrayRef<Token> Toks(
1951 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001952 Token &pragmaUnusedTok = Toks[0];
1953 pragmaUnusedTok.startToken();
1954 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1955 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001956 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001957 Toks[1] = WeakName;
1958 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001959 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001960 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001961 MutableArrayRef<Token> Toks(
1962 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001963 Token &pragmaUnusedTok = Toks[0];
1964 pragmaUnusedTok.startToken();
1965 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1966 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001967 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001968 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001969 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001970 }
1971}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001972
David Chisnall0867d9c2012-02-18 16:12:34 +00001973// #pragma redefine_extname identifier identifier
1974void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1975 PragmaIntroducerKind Introducer,
1976 Token &RedefToken) {
1977 SourceLocation RedefLoc = RedefToken.getLocation();
1978
1979 Token Tok;
1980 PP.Lex(Tok);
1981 if (Tok.isNot(tok::identifier)) {
1982 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1983 "redefine_extname";
1984 return;
1985 }
1986
Eli Friedman68be1642012-10-04 02:36:51 +00001987 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001988 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001989
David Chisnall0867d9c2012-02-18 16:12:34 +00001990 if (Tok.isNot(tok::identifier)) {
1991 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1992 << "redefine_extname";
1993 return;
1994 }
Eli Friedman68be1642012-10-04 02:36:51 +00001995
1996 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001997 PP.Lex(Tok);
1998
1999 if (Tok.isNot(tok::eod)) {
2000 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2001 "redefine_extname";
2002 return;
2003 }
2004
David Blaikie2eabcc92016-02-09 18:52:09 +00002005 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2006 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002007 Token &pragmaRedefTok = Toks[0];
2008 pragmaRedefTok.startToken();
2009 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2010 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002011 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002012 Toks[1] = RedefName;
2013 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00002014 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00002015}
2016
2017
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002018void
2019PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2020 PragmaIntroducerKind Introducer,
2021 Token &Tok) {
2022 tok::OnOffSwitch OOS;
2023 if (PP.LexOnOffSwitch(OOS))
2024 return;
2025
David Blaikie2eabcc92016-02-09 18:52:09 +00002026 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2027 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002028 Toks[0].startToken();
2029 Toks[0].setKind(tok::annot_pragma_fp_contract);
2030 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002031 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002032 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2033 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00002034 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002035}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002036
2037void
2038PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2039 PragmaIntroducerKind Introducer,
2040 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002041 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002042 if (Tok.isNot(tok::identifier)) {
2043 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2044 "OPENCL";
2045 return;
2046 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002047 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002048 SourceLocation NameLoc = Tok.getLocation();
2049
2050 PP.Lex(Tok);
2051 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002052 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002053 return;
2054 }
2055
2056 PP.Lex(Tok);
2057 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002058 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002059 return;
2060 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002061 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002062
Yaxun Liu5b746652016-12-18 05:18:55 +00002063 OpenCLExtState State;
2064 if (Pred->isStr("enable")) {
2065 State = Enable;
2066 } else if (Pred->isStr("disable")) {
2067 State = Disable;
2068 } else if (Pred->isStr("begin"))
2069 State = Begin;
2070 else if (Pred->isStr("end"))
2071 State = End;
2072 else {
2073 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2074 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002075 return;
2076 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002077 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002078
Eli Friedman68be1642012-10-04 02:36:51 +00002079 PP.Lex(Tok);
2080 if (Tok.isNot(tok::eod)) {
2081 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2082 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002083 return;
2084 }
Eli Friedman68be1642012-10-04 02:36:51 +00002085
Yaxun Liu5b746652016-12-18 05:18:55 +00002086 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2087 Info->first = Ext;
2088 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002089 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2090 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002091 Toks[0].startToken();
2092 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2093 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002094 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002095 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00002096 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002097
2098 if (PP.getPPCallbacks())
Yaxun Liu5b746652016-12-18 05:18:55 +00002099 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2100 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002101}
2102
Alexey Bataeva769e072013-03-22 06:34:35 +00002103/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
2104///
2105void
2106PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2107 PragmaIntroducerKind Introducer,
2108 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002109 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2110 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002111 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002112 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2113 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002114 }
2115 PP.DiscardUntilEndOfDirective();
2116}
2117
2118/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
2119///
2120void
2121PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2122 PragmaIntroducerKind Introducer,
2123 Token &FirstTok) {
2124 SmallVector<Token, 16> Pragma;
2125 Token Tok;
2126 Tok.startToken();
2127 Tok.setKind(tok::annot_pragma_openmp);
2128 Tok.setLocation(FirstTok.getLocation());
2129
Alexey Bataev96dae812018-02-16 18:36:44 +00002130 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002131 Pragma.push_back(Tok);
2132 PP.Lex(Tok);
Alexey Bataev96dae812018-02-16 18:36:44 +00002133 if (Tok.is(tok::annot_pragma_openmp)) {
2134 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2135 unsigned InnerPragmaCnt = 1;
2136 while (InnerPragmaCnt != 0) {
2137 PP.Lex(Tok);
2138 if (Tok.is(tok::annot_pragma_openmp))
2139 ++InnerPragmaCnt;
2140 else if (Tok.is(tok::annot_pragma_openmp_end))
2141 --InnerPragmaCnt;
2142 }
2143 PP.Lex(Tok);
2144 }
Alexey Bataeva769e072013-03-22 06:34:35 +00002145 }
2146 SourceLocation EodLoc = Tok.getLocation();
2147 Tok.startToken();
2148 Tok.setKind(tok::annot_pragma_openmp_end);
2149 Tok.setLocation(EodLoc);
2150 Pragma.push_back(Tok);
2151
David Blaikie2eabcc92016-02-09 18:52:09 +00002152 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
2153 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2154 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2155 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002156}
Reid Kleckner002562a2013-05-06 21:02:12 +00002157
David Majnemer4bb09802014-02-10 19:50:15 +00002158/// \brief Handle '#pragma pointers_to_members'
2159// The grammar for this pragma is as follows:
2160//
2161// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2162//
2163// #pragma pointers_to_members '(' 'best_case' ')'
2164// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2165// #pragma pointers_to_members '(' inheritance-model ')'
2166void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2167 PragmaIntroducerKind Introducer,
2168 Token &Tok) {
2169 SourceLocation PointersToMembersLoc = Tok.getLocation();
2170 PP.Lex(Tok);
2171 if (Tok.isNot(tok::l_paren)) {
2172 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2173 << "pointers_to_members";
2174 return;
2175 }
2176 PP.Lex(Tok);
2177 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2178 if (!Arg) {
2179 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2180 << "pointers_to_members";
2181 return;
2182 }
2183 PP.Lex(Tok);
2184
David Majnemer86c318f2014-02-11 21:05:00 +00002185 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002186 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002187 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002188 } else {
2189 if (Arg->isStr("full_generality")) {
2190 if (Tok.is(tok::comma)) {
2191 PP.Lex(Tok);
2192
2193 Arg = Tok.getIdentifierInfo();
2194 if (!Arg) {
2195 PP.Diag(Tok.getLocation(),
2196 diag::err_pragma_pointers_to_members_unknown_kind)
2197 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2198 return;
2199 }
2200 PP.Lex(Tok);
2201 } else if (Tok.is(tok::r_paren)) {
2202 // #pragma pointers_to_members(full_generality) implicitly specifies
2203 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002204 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002205 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002206 } else {
2207 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2208 << "full_generality";
2209 return;
2210 }
2211 }
2212
2213 if (Arg) {
2214 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002215 RepresentationMethod =
2216 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002217 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002218 RepresentationMethod =
2219 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002220 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002221 RepresentationMethod =
2222 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002223 } else {
2224 PP.Diag(Tok.getLocation(),
2225 diag::err_pragma_pointers_to_members_unknown_kind)
2226 << Arg << /*HasPointerDeclaration*/ 1;
2227 return;
2228 }
2229 }
2230 }
2231
2232 if (Tok.isNot(tok::r_paren)) {
2233 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2234 << (Arg ? Arg->getName() : "full_generality");
2235 return;
2236 }
2237
David Majnemera8f2f1d2015-03-19 00:10:23 +00002238 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002239 PP.Lex(Tok);
2240 if (Tok.isNot(tok::eod)) {
2241 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2242 << "pointers_to_members";
2243 return;
2244 }
2245
2246 Token AnnotTok;
2247 AnnotTok.startToken();
2248 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2249 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002250 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002251 AnnotTok.setAnnotationValue(
2252 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2253 PP.EnterToken(AnnotTok);
2254}
2255
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002256/// \brief Handle '#pragma vtordisp'
2257// The grammar for this pragma is as follows:
2258//
2259// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2260//
2261// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2262// #pragma vtordisp '(' 'pop' ')'
2263// #pragma vtordisp '(' ')'
2264void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2265 PragmaIntroducerKind Introducer,
2266 Token &Tok) {
2267 SourceLocation VtorDispLoc = Tok.getLocation();
2268 PP.Lex(Tok);
2269 if (Tok.isNot(tok::l_paren)) {
2270 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2271 return;
2272 }
2273 PP.Lex(Tok);
2274
Denis Zobnin2290dac2016-04-29 11:27:00 +00002275 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002276 const IdentifierInfo *II = Tok.getIdentifierInfo();
2277 if (II) {
2278 if (II->isStr("push")) {
2279 // #pragma vtordisp(push, mode)
2280 PP.Lex(Tok);
2281 if (Tok.isNot(tok::comma)) {
2282 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2283 return;
2284 }
2285 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002286 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002287 // not push, could be on/off
2288 } else if (II->isStr("pop")) {
2289 // #pragma vtordisp(pop)
2290 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002291 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002292 }
2293 // not push or pop, could be on/off
2294 } else {
2295 if (Tok.is(tok::r_paren)) {
2296 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002297 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002298 }
2299 }
2300
2301
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002302 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002303 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002304 const IdentifierInfo *II = Tok.getIdentifierInfo();
2305 if (II && II->isStr("off")) {
2306 PP.Lex(Tok);
2307 Value = 0;
2308 } else if (II && II->isStr("on")) {
2309 PP.Lex(Tok);
2310 Value = 1;
2311 } else if (Tok.is(tok::numeric_constant) &&
2312 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2313 if (Value > 2) {
2314 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2315 << 0 << 2 << "vtordisp";
2316 return;
2317 }
2318 } else {
2319 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2320 << "vtordisp";
2321 return;
2322 }
2323 }
2324
2325 // Finish the pragma: ')' $
2326 if (Tok.isNot(tok::r_paren)) {
2327 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2328 return;
2329 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002330 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002331 PP.Lex(Tok);
2332 if (Tok.isNot(tok::eod)) {
2333 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2334 << "vtordisp";
2335 return;
2336 }
2337
2338 // Enter the annotation.
2339 Token AnnotTok;
2340 AnnotTok.startToken();
2341 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2342 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002343 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002344 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002345 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002346 PP.EnterToken(AnnotTok);
2347}
2348
Warren Huntc3b18962014-04-08 22:30:47 +00002349/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
2350/// an annotation token.
2351void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2352 PragmaIntroducerKind Introducer,
2353 Token &Tok) {
2354 Token EoF, AnnotTok;
2355 EoF.startToken();
2356 EoF.setKind(tok::eof);
2357 AnnotTok.startToken();
2358 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2359 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002360 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002361 SmallVector<Token, 8> TokenVector;
2362 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002363 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002364 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002365 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2366 }
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002367 // Add a sentinel EoF token to the end of the list.
Warren Huntc3b18962014-04-08 22:30:47 +00002368 TokenVector.push_back(EoF);
2369 // We must allocate this array with new because EnterTokenStream is going to
2370 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00002371 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
2372 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002373 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002374 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2375 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002376 AnnotTok.setAnnotationValue(Value);
2377 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002378}
2379
Aaron Ballman5d041be2013-06-04 02:07:14 +00002380/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
2381///
2382/// The syntax is:
2383/// \code
2384/// #pragma detect_mismatch("name", "value")
2385/// \endcode
2386/// Where 'name' and 'value' are quoted strings. The values are embedded in
2387/// the object file and passed along to the linker. If the linker detects a
2388/// mismatch in the object file's values for the given name, a LNK2038 error
2389/// is emitted. See MSDN for more details.
2390void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2391 PragmaIntroducerKind Introducer,
2392 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002393 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002394 PP.Lex(Tok);
2395 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002396 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002397 return;
2398 }
2399
2400 // Read the name to embed, which must be a string literal.
2401 std::string NameString;
2402 if (!PP.LexStringLiteral(Tok, NameString,
2403 "pragma detect_mismatch",
2404 /*MacroExpansion=*/true))
2405 return;
2406
2407 // Read the comma followed by a second string literal.
2408 std::string ValueString;
2409 if (Tok.isNot(tok::comma)) {
2410 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2411 return;
2412 }
2413
2414 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2415 /*MacroExpansion=*/true))
2416 return;
2417
2418 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002419 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002420 return;
2421 }
2422 PP.Lex(Tok); // Eat the r_paren.
2423
2424 if (Tok.isNot(tok::eod)) {
2425 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2426 return;
2427 }
2428
Reid Kleckner71966c92014-02-20 23:37:45 +00002429 // If the pragma is lexically sound, notify any interested PPCallbacks.
2430 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002431 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002432 ValueString);
2433
Nico Webercbbaeb12016-03-02 19:28:54 +00002434 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002435}
2436
Reid Kleckner002562a2013-05-06 21:02:12 +00002437/// \brief Handle the microsoft \#pragma comment extension.
2438///
2439/// The syntax is:
2440/// \code
2441/// #pragma comment(linker, "foo")
2442/// \endcode
2443/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2444/// "foo" is a string, which is fully macro expanded, and permits string
2445/// concatenation, embedded escape characters etc. See MSDN for more details.
2446void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2447 PragmaIntroducerKind Introducer,
2448 Token &Tok) {
2449 SourceLocation CommentLoc = Tok.getLocation();
2450 PP.Lex(Tok);
2451 if (Tok.isNot(tok::l_paren)) {
2452 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2453 return;
2454 }
2455
2456 // Read the identifier.
2457 PP.Lex(Tok);
2458 if (Tok.isNot(tok::identifier)) {
2459 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2460 return;
2461 }
2462
2463 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002464 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002465 PragmaMSCommentKind Kind =
2466 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2467 .Case("linker", PCK_Linker)
2468 .Case("lib", PCK_Lib)
2469 .Case("compiler", PCK_Compiler)
2470 .Case("exestr", PCK_ExeStr)
2471 .Case("user", PCK_User)
2472 .Default(PCK_Unknown);
2473 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002474 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2475 return;
2476 }
2477
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +00002478 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2479 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2480 << II->getName();
2481 return;
2482 }
2483
Yunzhong Gao99efc032015-03-23 20:41:42 +00002484 // On PS4, issue a warning about any pragma comments other than
2485 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002486 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002487 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2488 << II->getName();
2489 return;
2490 }
2491
Reid Kleckner002562a2013-05-06 21:02:12 +00002492 // Read the optional string if present.
2493 PP.Lex(Tok);
2494 std::string ArgumentString;
2495 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2496 "pragma comment",
2497 /*MacroExpansion=*/true))
2498 return;
2499
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002500 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002501 // FIXME: If the kind is "compiler" warn if the string is present (it is
2502 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002503 // The MSDN docs say that "lib" and "linker" require a string and have a short
2504 // whitelist of linker options they support, but in practice MSVC doesn't
2505 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002506
2507 if (Tok.isNot(tok::r_paren)) {
2508 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2509 return;
2510 }
2511 PP.Lex(Tok); // eat the r_paren.
2512
2513 if (Tok.isNot(tok::eod)) {
2514 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2515 return;
2516 }
2517
Reid Kleckner71966c92014-02-20 23:37:45 +00002518 // If the pragma is lexically sound, notify any interested PPCallbacks.
2519 if (PP.getPPCallbacks())
2520 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2521
Nico Weber66220292016-03-02 17:28:48 +00002522 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002523}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002524
2525// #pragma clang optimize off
2526// #pragma clang optimize on
2527void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2528 PragmaIntroducerKind Introducer,
2529 Token &FirstToken) {
2530 Token Tok;
2531 PP.Lex(Tok);
2532 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002533 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002534 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002535 return;
2536 }
2537 if (Tok.isNot(tok::identifier)) {
2538 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2539 << PP.getSpelling(Tok);
2540 return;
2541 }
2542 const IdentifierInfo *II = Tok.getIdentifierInfo();
2543 // The only accepted values are 'on' or 'off'.
2544 bool IsOn = false;
2545 if (II->isStr("on")) {
2546 IsOn = true;
2547 } else if (!II->isStr("off")) {
2548 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2549 << PP.getSpelling(Tok);
2550 return;
2551 }
2552 PP.Lex(Tok);
2553
2554 if (Tok.isNot(tok::eod)) {
2555 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2556 << PP.getSpelling(Tok);
2557 return;
2558 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002559
2560 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2561}
2562
Adam Nemet60d32642017-04-04 21:18:36 +00002563namespace {
2564/// Used as the annotation value for tok::annot_pragma_fp.
2565struct TokFPAnnotValue {
2566 enum FlagKinds { Contract };
2567 enum FlagValues { On, Off, Fast };
2568
2569 FlagKinds FlagKind;
2570 FlagValues FlagValue;
2571};
2572} // end anonymous namespace
2573
2574void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2575 PragmaIntroducerKind Introducer,
2576 Token &Tok) {
2577 // fp
2578 Token PragmaName = Tok;
2579 SmallVector<Token, 1> TokenList;
2580
2581 PP.Lex(Tok);
2582 if (Tok.isNot(tok::identifier)) {
2583 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2584 << /*MissingOption=*/true << "";
2585 return;
2586 }
2587
2588 while (Tok.is(tok::identifier)) {
2589 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2590
2591 auto FlagKind =
2592 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2593 OptionInfo->getName())
2594 .Case("contract", TokFPAnnotValue::Contract)
2595 .Default(None);
2596 if (!FlagKind) {
2597 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2598 << /*MissingOption=*/false << OptionInfo;
2599 return;
2600 }
2601 PP.Lex(Tok);
2602
2603 // Read '('
2604 if (Tok.isNot(tok::l_paren)) {
2605 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2606 return;
2607 }
2608 PP.Lex(Tok);
2609
2610 if (Tok.isNot(tok::identifier)) {
2611 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2612 << PP.getSpelling(Tok) << OptionInfo->getName();
2613 return;
2614 }
2615 const IdentifierInfo *II = Tok.getIdentifierInfo();
2616
2617 auto FlagValue =
2618 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2619 II->getName())
2620 .Case("on", TokFPAnnotValue::On)
2621 .Case("off", TokFPAnnotValue::Off)
2622 .Case("fast", TokFPAnnotValue::Fast)
2623 .Default(llvm::None);
2624
2625 if (!FlagValue) {
2626 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2627 << PP.getSpelling(Tok) << OptionInfo->getName();
2628 return;
2629 }
2630 PP.Lex(Tok);
2631
2632 // Read ')'
2633 if (Tok.isNot(tok::r_paren)) {
2634 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2635 return;
2636 }
2637 PP.Lex(Tok);
2638
2639 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2640 TokFPAnnotValue{*FlagKind, *FlagValue};
2641 // Generate the loop hint token.
2642 Token FPTok;
2643 FPTok.startToken();
2644 FPTok.setKind(tok::annot_pragma_fp);
2645 FPTok.setLocation(PragmaName.getLocation());
2646 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2647 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2648 TokenList.push_back(FPTok);
2649 }
2650
2651 if (Tok.isNot(tok::eod)) {
2652 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2653 << "clang fp";
2654 return;
2655 }
2656
2657 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2658 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2659
2660 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2661 /*DisableMacroExpansion=*/false);
2662}
2663
2664void Parser::HandlePragmaFP() {
2665 assert(Tok.is(tok::annot_pragma_fp));
2666 auto *AnnotValue =
2667 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2668
2669 LangOptions::FPContractModeKind FPC;
2670 switch (AnnotValue->FlagValue) {
2671 case TokFPAnnotValue::On:
2672 FPC = LangOptions::FPC_On;
2673 break;
2674 case TokFPAnnotValue::Fast:
2675 FPC = LangOptions::FPC_Fast;
2676 break;
2677 case TokFPAnnotValue::Off:
2678 FPC = LangOptions::FPC_Off;
2679 break;
2680 }
2681
2682 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002683 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002684}
2685
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002686/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002687static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2688 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002689 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002690 SmallVector<Token, 1> ValueList;
2691 int OpenParens = ValueInParens ? 1 : 0;
2692 // Read constant expression.
2693 while (Tok.isNot(tok::eod)) {
2694 if (Tok.is(tok::l_paren))
2695 OpenParens++;
2696 else if (Tok.is(tok::r_paren)) {
2697 OpenParens--;
2698 if (OpenParens == 0 && ValueInParens)
2699 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002700 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002701
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002702 ValueList.push_back(Tok);
2703 PP.Lex(Tok);
2704 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002705
2706 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002707 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002708 if (Tok.isNot(tok::r_paren)) {
2709 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2710 return true;
2711 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002712 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002713 }
2714
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002715 Token EOFTok;
2716 EOFTok.startToken();
2717 EOFTok.setKind(tok::eof);
2718 EOFTok.setLocation(Tok.getLocation());
2719 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2720
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002721 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002722
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002723 Info.PragmaName = PragmaName;
2724 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002725 return false;
2726}
2727
Eli Bendersky06a40422014-06-06 20:31:48 +00002728/// \brief Handle the \#pragma clang loop directive.
2729/// #pragma clang 'loop' loop-hints
2730///
2731/// loop-hints:
2732/// loop-hint loop-hints[opt]
2733///
2734/// loop-hint:
2735/// 'vectorize' '(' loop-hint-keyword ')'
2736/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002737/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002738/// 'vectorize_width' '(' loop-hint-value ')'
2739/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002740/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002741///
2742/// loop-hint-keyword:
2743/// 'enable'
2744/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002745/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002746///
Mark Heffernan450c2382014-07-23 17:31:31 +00002747/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002748/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002749/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002750/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002751///
Eli Bendersky06a40422014-06-06 20:31:48 +00002752/// loop-hint-value:
2753/// constant-expression
2754///
2755/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2756/// try vectorizing the instructions of the loop it precedes. Specifying
2757/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2758/// interleaving multiple iterations of the loop it precedes. The width of the
2759/// vector instructions is specified by vectorize_width() and the number of
2760/// interleaved loop iterations is specified by interleave_count(). Specifying a
2761/// value of 1 effectively disables vectorization/interleaving, even if it is
2762/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2763/// only works on inner loops.
2764///
Eli Bendersky86483b32014-06-11 17:56:26 +00002765/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002766/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2767/// completely if the trip count is known at compile time and unroll partially
2768/// if the trip count is not known. Specifying unroll(full) is similar to
2769/// unroll(enable) but will unroll the loop only if the trip count is known at
2770/// compile time. Specifying unroll(disable) disables unrolling for the
2771/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2772/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002773void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2774 PragmaIntroducerKind Introducer,
2775 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002776 // Incoming token is "loop" from "#pragma clang loop".
2777 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002778 SmallVector<Token, 1> TokenList;
2779
2780 // Lex the optimization option and verify it is an identifier.
2781 PP.Lex(Tok);
2782 if (Tok.isNot(tok::identifier)) {
2783 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2784 << /*MissingOption=*/true << "";
2785 return;
2786 }
2787
2788 while (Tok.is(tok::identifier)) {
2789 Token Option = Tok;
2790 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2791
Eli Bendersky86483b32014-06-11 17:56:26 +00002792 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002793 .Case("vectorize", true)
2794 .Case("interleave", true)
2795 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002796 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002797 .Case("vectorize_width", true)
2798 .Case("interleave_count", true)
2799 .Case("unroll_count", true)
2800 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002801 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002802 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2803 << /*MissingOption=*/false << OptionInfo;
2804 return;
2805 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002806 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002807
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002808 // Read '('
2809 if (Tok.isNot(tok::l_paren)) {
2810 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002811 return;
2812 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002813 PP.Lex(Tok);
2814
2815 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2816 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2817 *Info))
2818 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002819
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002820 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002821 Token LoopHintTok;
2822 LoopHintTok.startToken();
2823 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002824 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002825 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002826 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2827 TokenList.push_back(LoopHintTok);
2828 }
2829
2830 if (Tok.isNot(tok::eod)) {
2831 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2832 << "clang loop";
2833 return;
2834 }
2835
David Blaikie2eabcc92016-02-09 18:52:09 +00002836 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2837 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002838
David Blaikie2eabcc92016-02-09 18:52:09 +00002839 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2840 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002841}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002842
2843/// \brief Handle the loop unroll optimization pragmas.
2844/// #pragma unroll
2845/// #pragma unroll unroll-hint-value
2846/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002847/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002848///
2849/// unroll-hint-value:
2850/// constant-expression
2851///
Mark Heffernanc888e412014-07-24 18:09:38 +00002852/// Loop unrolling hints can be specified with '#pragma unroll' or
2853/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2854/// contained in parentheses. With no argument the directive instructs llvm to
2855/// try to unroll the loop completely. A positive integer argument can be
2856/// specified to indicate the number of times the loop should be unrolled. To
2857/// maximize compatibility with other compilers the unroll count argument can be
2858/// specified with or without parentheses. Specifying, '#pragma nounroll'
2859/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002860void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2861 PragmaIntroducerKind Introducer,
2862 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002863 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2864 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002865 Token PragmaName = Tok;
2866 PP.Lex(Tok);
2867 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2868 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002869 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002870 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002871 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002872 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2873 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2874 << "nounroll";
2875 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002876 } else {
2877 // Unroll pragma with an argument: "#pragma unroll N" or
2878 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002879 // Read '(' if it exists.
2880 bool ValueInParens = Tok.is(tok::l_paren);
2881 if (ValueInParens)
2882 PP.Lex(Tok);
2883
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002884 Token Option;
2885 Option.startToken();
2886 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002887 return;
2888
2889 // In CUDA, the argument to '#pragma unroll' should not be contained in
2890 // parentheses.
2891 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002892 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002893 diag::warn_pragma_unroll_cuda_value_in_parens);
2894
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002895 if (Tok.isNot(tok::eod)) {
2896 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2897 << "unroll";
2898 return;
2899 }
2900 }
2901
2902 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002903 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002904 TokenArray[0].startToken();
2905 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2906 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002907 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002908 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002909 PP.EnterTokenStream(std::move(TokenArray), 1,
2910 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002911}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002912
2913/// \brief Handle the Microsoft \#pragma intrinsic extension.
2914///
2915/// The syntax is:
2916/// \code
2917/// #pragma intrinsic(memset)
2918/// #pragma intrinsic(strlen, memcpy)
2919/// \endcode
2920///
2921/// Pragma intrisic tells the compiler to use a builtin version of the
2922/// function. Clang does it anyway, so the pragma doesn't really do anything.
2923/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2924/// isn't an intrinsic in clang and suggest to include intrin.h.
2925void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2926 PragmaIntroducerKind Introducer,
2927 Token &Tok) {
2928 PP.Lex(Tok);
2929
2930 if (Tok.isNot(tok::l_paren)) {
2931 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2932 << "intrinsic";
2933 return;
2934 }
2935 PP.Lex(Tok);
2936
2937 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2938
2939 while (Tok.is(tok::identifier)) {
2940 IdentifierInfo *II = Tok.getIdentifierInfo();
2941 if (!II->getBuiltinID())
2942 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2943 << II << SuggestIntrinH;
2944
2945 PP.Lex(Tok);
2946 if (Tok.isNot(tok::comma))
2947 break;
2948 PP.Lex(Tok);
2949 }
2950
2951 if (Tok.isNot(tok::r_paren)) {
2952 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2953 << "intrinsic";
2954 return;
2955 }
2956 PP.Lex(Tok);
2957
2958 if (Tok.isNot(tok::eod))
2959 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2960 << "intrinsic";
2961}
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00002962
2963// #pragma optimize("gsty", on|off)
2964void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
2965 PragmaIntroducerKind Introducer,
2966 Token &Tok) {
2967 SourceLocation StartLoc = Tok.getLocation();
2968 PP.Lex(Tok);
2969
2970 if (Tok.isNot(tok::l_paren)) {
2971 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
2972 return;
2973 }
2974 PP.Lex(Tok);
2975
2976 if (Tok.isNot(tok::string_literal)) {
2977 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
2978 return;
2979 }
2980 // We could syntax check the string but it's probably not worth the effort.
2981 PP.Lex(Tok);
2982
2983 if (Tok.isNot(tok::comma)) {
2984 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
2985 return;
2986 }
2987 PP.Lex(Tok);
2988
2989 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
2990 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
2991 << "optimize" << /*Expected=*/true << "'on' or 'off'";
2992 return;
2993 }
2994 IdentifierInfo *II = Tok.getIdentifierInfo();
2995 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
2996 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
2997 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
2998 << "'on' or 'off'";
2999 return;
3000 }
3001 PP.Lex(Tok);
3002
3003 if (Tok.isNot(tok::r_paren)) {
3004 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3005 return;
3006 }
3007 PP.Lex(Tok);
3008
3009 if (Tok.isNot(tok::eod)) {
3010 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3011 << "optimize";
3012 return;
3013 }
3014 PP.Diag(StartLoc, diag::warn_pragma_optimize);
3015}
3016
Justin Lebar67a78a62016-10-08 22:15:58 +00003017void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3018 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
3019 Token FirstTok = Tok;
3020
3021 PP.Lex(Tok);
3022 IdentifierInfo *Info = Tok.getIdentifierInfo();
3023 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3024 PP.Diag(FirstTok.getLocation(),
3025 diag::warn_pragma_force_cuda_host_device_bad_arg);
3026 return;
3027 }
3028
3029 if (Info->isStr("begin"))
3030 Actions.PushForceCUDAHostDevice();
3031 else if (!Actions.PopForceCUDAHostDevice())
3032 PP.Diag(FirstTok.getLocation(),
3033 diag::err_pragma_cannot_end_force_cuda_host_device);
3034
3035 PP.Lex(Tok);
3036 if (!Tok.is(tok::eod))
3037 PP.Diag(FirstTok.getLocation(),
3038 diag::warn_pragma_force_cuda_host_device_bad_arg);
3039}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003040
3041/// \brief Handle the #pragma clang attribute directive.
3042///
3043/// The syntax is:
3044/// \code
3045/// #pragma clang attribute push(attribute, subject-set)
3046/// #pragma clang attribute pop
3047/// \endcode
3048///
3049/// The subject-set clause defines the set of declarations which receive the
3050/// attribute. Its exact syntax is described in the LanguageExtensions document
3051/// in Clang's documentation.
3052///
3053/// This directive instructs the compiler to begin/finish applying the specified
3054/// attribute to the set of attribute-specific declarations in the active range
3055/// of the pragma.
3056void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3057 PragmaIntroducerKind Introducer,
3058 Token &FirstToken) {
3059 Token Tok;
3060 PP.Lex(Tok);
3061 auto *Info = new (PP.getPreprocessorAllocator())
3062 PragmaAttributeInfo(AttributesForPragmaAttribute);
3063
3064 // Parse the 'push' or 'pop'.
3065 if (Tok.isNot(tok::identifier)) {
3066 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
3067 return;
3068 }
3069 const auto *II = Tok.getIdentifierInfo();
3070 if (II->isStr("push"))
3071 Info->Action = PragmaAttributeInfo::Push;
3072 else if (II->isStr("pop"))
3073 Info->Action = PragmaAttributeInfo::Pop;
3074 else {
3075 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3076 << PP.getSpelling(Tok);
3077 return;
3078 }
3079 PP.Lex(Tok);
3080
3081 // Parse the actual attribute.
3082 if (Info->Action == PragmaAttributeInfo::Push) {
3083 if (Tok.isNot(tok::l_paren)) {
3084 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3085 return;
3086 }
3087 PP.Lex(Tok);
3088
3089 // Lex the attribute tokens.
3090 SmallVector<Token, 16> AttributeTokens;
3091 int OpenParens = 1;
3092 while (Tok.isNot(tok::eod)) {
3093 if (Tok.is(tok::l_paren))
3094 OpenParens++;
3095 else if (Tok.is(tok::r_paren)) {
3096 OpenParens--;
3097 if (OpenParens == 0)
3098 break;
3099 }
3100
3101 AttributeTokens.push_back(Tok);
3102 PP.Lex(Tok);
3103 }
3104
3105 if (AttributeTokens.empty()) {
3106 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3107 return;
3108 }
3109 if (Tok.isNot(tok::r_paren)) {
3110 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3111 return;
3112 }
3113 SourceLocation EndLoc = Tok.getLocation();
3114 PP.Lex(Tok);
3115
3116 // Terminate the attribute for parsing.
3117 Token EOFTok;
3118 EOFTok.startToken();
3119 EOFTok.setKind(tok::eof);
3120 EOFTok.setLocation(EndLoc);
3121 AttributeTokens.push_back(EOFTok);
3122
3123 Info->Tokens =
3124 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3125 }
3126
3127 if (Tok.isNot(tok::eod))
3128 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3129 << "clang attribute";
3130
3131 // Generate the annotated pragma token.
3132 auto TokenArray = llvm::make_unique<Token[]>(1);
3133 TokenArray[0].startToken();
3134 TokenArray[0].setKind(tok::annot_pragma_attribute);
3135 TokenArray[0].setLocation(FirstToken.getLocation());
3136 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3137 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3138 PP.EnterTokenStream(std::move(TokenArray), 1,
3139 /*DisableMacroExpansion=*/false);
3140}