blob: c97df85ae17c1b32d994ba4019b9a39ce8d88a65 [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
52struct PragmaMSStructHandler : public PragmaHandler {
53 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000054 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
55 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000056};
57
58struct PragmaUnusedHandler : public PragmaHandler {
59 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000060 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
61 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000062};
63
64struct PragmaWeakHandler : public PragmaHandler {
65 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000066 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
67 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000068};
69
70struct PragmaRedefineExtnameHandler : public PragmaHandler {
71 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000072 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
73 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000074};
75
76struct PragmaOpenCLExtensionHandler : public PragmaHandler {
77 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000078 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
79 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000080};
81
82
83struct PragmaFPContractHandler : public PragmaHandler {
84 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000085 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
86 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000087};
88
89struct PragmaNoOpenMPHandler : public PragmaHandler {
90 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000091 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
92 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000093};
94
95struct PragmaOpenMPHandler : public PragmaHandler {
96 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000097 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
98 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000099};
100
101/// PragmaCommentHandler - "\#pragma comment ...".
102struct PragmaCommentHandler : public PragmaHandler {
103 PragmaCommentHandler(Sema &Actions)
104 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000105 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
106 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000107private:
108 Sema &Actions;
109};
110
111struct PragmaDetectMismatchHandler : public PragmaHandler {
112 PragmaDetectMismatchHandler(Sema &Actions)
113 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000114 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
115 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000116private:
117 Sema &Actions;
118};
119
120struct PragmaMSPointersToMembers : public PragmaHandler {
121 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000122 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
123 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000124};
125
126struct PragmaMSVtorDisp : public PragmaHandler {
127 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000128 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
129 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000130};
131
Warren Huntc3b18962014-04-08 22:30:47 +0000132struct PragmaMSPragma : public PragmaHandler {
133 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000134 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
135 Token &FirstToken) override;
136};
137
Dario Domizioli13a0a382014-05-23 12:13:25 +0000138/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
139struct PragmaOptimizeHandler : public PragmaHandler {
140 PragmaOptimizeHandler(Sema &S)
141 : PragmaHandler("optimize"), Actions(S) {}
142 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
143 Token &FirstToken) override;
144private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000145 Sema &Actions;
146};
147
148struct PragmaLoopHintHandler : public PragmaHandler {
149 PragmaLoopHintHandler() : PragmaHandler("loop") {}
150 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
151 Token &FirstToken) override;
152};
153
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000154struct PragmaUnrollHintHandler : public PragmaHandler {
155 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
156 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
157 Token &FirstToken) override;
158};
159
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000160struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
161 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
162};
163
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000164struct PragmaMSIntrinsicHandler : public PragmaHandler {
165 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
166 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
167 Token &FirstToken) override;
168};
169
Justin Lebar67a78a62016-10-08 22:15:58 +0000170struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
171 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
172 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
173 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
174 Token &FirstToken) override;
175
176private:
177 Sema &Actions;
178};
179
Eli Bendersky06a40422014-06-06 20:31:48 +0000180} // end namespace
181
182void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000183 AlignHandler.reset(new PragmaAlignHandler());
184 PP.AddPragmaHandler(AlignHandler.get());
185
186 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
187 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
188
189 OptionsHandler.reset(new PragmaOptionsHandler());
190 PP.AddPragmaHandler(OptionsHandler.get());
191
192 PackHandler.reset(new PragmaPackHandler());
193 PP.AddPragmaHandler(PackHandler.get());
194
195 MSStructHandler.reset(new PragmaMSStructHandler());
196 PP.AddPragmaHandler(MSStructHandler.get());
197
198 UnusedHandler.reset(new PragmaUnusedHandler());
199 PP.AddPragmaHandler(UnusedHandler.get());
200
201 WeakHandler.reset(new PragmaWeakHandler());
202 PP.AddPragmaHandler(WeakHandler.get());
203
204 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
205 PP.AddPragmaHandler(RedefineExtnameHandler.get());
206
207 FPContractHandler.reset(new PragmaFPContractHandler());
208 PP.AddPragmaHandler("STDC", FPContractHandler.get());
209
210 if (getLangOpts().OpenCL) {
211 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
212 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
213
214 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
215 }
216 if (getLangOpts().OpenMP)
217 OpenMPHandler.reset(new PragmaOpenMPHandler());
218 else
219 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
220 PP.AddPragmaHandler(OpenMPHandler.get());
221
Yunzhong Gao99efc032015-03-23 20:41:42 +0000222 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000223 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
224 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000225 }
226
227 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000228 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
229 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
230 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
231 PP.AddPragmaHandler(MSPointersToMembers.get());
232 MSVtorDisp.reset(new PragmaMSVtorDisp());
233 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000234 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000235 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000236 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
237 PP.AddPragmaHandler(MSDataSeg.get());
238 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
239 PP.AddPragmaHandler(MSBSSSeg.get());
240 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
241 PP.AddPragmaHandler(MSConstSeg.get());
242 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
243 PP.AddPragmaHandler(MSCodeSeg.get());
244 MSSection.reset(new PragmaMSPragma("section"));
245 PP.AddPragmaHandler(MSSection.get());
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000246 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
247 PP.AddPragmaHandler(MSRuntimeChecks.get());
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000248 MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
249 PP.AddPragmaHandler(MSIntrinsic.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000250 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000251
Justin Lebar67a78a62016-10-08 22:15:58 +0000252 if (getLangOpts().CUDA) {
253 CUDAForceHostDeviceHandler.reset(
254 new PragmaForceCUDAHostDeviceHandler(Actions));
255 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
256 }
257
Eli Bendersky06a40422014-06-06 20:31:48 +0000258 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
259 PP.AddPragmaHandler("clang", OptimizeHandler.get());
260
261 LoopHintHandler.reset(new PragmaLoopHintHandler());
262 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000263
264 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
265 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000266
267 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
268 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000269}
270
271void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000272 // Remove the pragma handlers we installed.
273 PP.RemovePragmaHandler(AlignHandler.get());
274 AlignHandler.reset();
275 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
276 GCCVisibilityHandler.reset();
277 PP.RemovePragmaHandler(OptionsHandler.get());
278 OptionsHandler.reset();
279 PP.RemovePragmaHandler(PackHandler.get());
280 PackHandler.reset();
281 PP.RemovePragmaHandler(MSStructHandler.get());
282 MSStructHandler.reset();
283 PP.RemovePragmaHandler(UnusedHandler.get());
284 UnusedHandler.reset();
285 PP.RemovePragmaHandler(WeakHandler.get());
286 WeakHandler.reset();
287 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
288 RedefineExtnameHandler.reset();
289
290 if (getLangOpts().OpenCL) {
291 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
292 OpenCLExtensionHandler.reset();
293 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
294 }
295 PP.RemovePragmaHandler(OpenMPHandler.get());
296 OpenMPHandler.reset();
297
Yunzhong Gao99efc032015-03-23 20:41:42 +0000298 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000299 PP.RemovePragmaHandler(MSCommentHandler.get());
300 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000301 }
302
303 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000304 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
305 MSDetectMismatchHandler.reset();
306 PP.RemovePragmaHandler(MSPointersToMembers.get());
307 MSPointersToMembers.reset();
308 PP.RemovePragmaHandler(MSVtorDisp.get());
309 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000310 PP.RemovePragmaHandler(MSInitSeg.get());
311 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000312 PP.RemovePragmaHandler(MSDataSeg.get());
313 MSDataSeg.reset();
314 PP.RemovePragmaHandler(MSBSSSeg.get());
315 MSBSSSeg.reset();
316 PP.RemovePragmaHandler(MSConstSeg.get());
317 MSConstSeg.reset();
318 PP.RemovePragmaHandler(MSCodeSeg.get());
319 MSCodeSeg.reset();
320 PP.RemovePragmaHandler(MSSection.get());
321 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000322 PP.RemovePragmaHandler(MSRuntimeChecks.get());
323 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000324 PP.RemovePragmaHandler(MSIntrinsic.get());
325 MSIntrinsic.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000326 }
327
Justin Lebar67a78a62016-10-08 22:15:58 +0000328 if (getLangOpts().CUDA) {
329 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
330 CUDAForceHostDeviceHandler.reset();
331 }
332
Reid Kleckner5b086462014-02-20 22:52:09 +0000333 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
334 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000335
336 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
337 OptimizeHandler.reset();
338
339 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
340 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000341
342 PP.RemovePragmaHandler(UnrollHintHandler.get());
343 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000344
345 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
346 NoUnrollHintHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000347}
348
349/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000350///
351/// Each annot_pragma_unused is followed by the argument token so e.g.
352/// "#pragma unused(x,y)" becomes:
353/// annot_pragma_unused 'x' annot_pragma_unused 'y'
354void Parser::HandlePragmaUnused() {
355 assert(Tok.is(tok::annot_pragma_unused));
356 SourceLocation UnusedLoc = ConsumeToken();
357 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
358 ConsumeToken(); // The argument token.
359}
Eli Friedman570024a2010-08-05 06:57:20 +0000360
Rafael Espindola273fd772012-01-26 02:02:57 +0000361void Parser::HandlePragmaVisibility() {
362 assert(Tok.is(tok::annot_pragma_vis));
363 const IdentifierInfo *VisType =
364 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
365 SourceLocation VisLoc = ConsumeToken();
366 Actions.ActOnPragmaVisibility(VisType, VisLoc);
367}
368
Benjamin Kramere003ca22015-10-28 13:54:16 +0000369namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000370struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000371 Sema::PragmaMsStackAction Action;
372 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000373 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000374};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000375} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000376
377void Parser::HandlePragmaPack() {
378 assert(Tok.is(tok::annot_pragma_pack));
379 PragmaPackInfo *Info =
380 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
381 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000382 ExprResult Alignment;
383 if (Info->Alignment.is(tok::numeric_constant)) {
384 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
385 if (Alignment.isInvalid())
386 return;
387 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000388 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
389 Alignment.get());
Eli Friedmanec52f922012-02-23 23:47:16 +0000390}
391
Eli Friedman68be1642012-10-04 02:36:51 +0000392void Parser::HandlePragmaMSStruct() {
393 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000394 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
395 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000396 Actions.ActOnPragmaMSStruct(Kind);
397 ConsumeToken(); // The annotation token.
398}
399
400void Parser::HandlePragmaAlign() {
401 assert(Tok.is(tok::annot_pragma_align));
402 Sema::PragmaOptionsAlignKind Kind =
403 static_cast<Sema::PragmaOptionsAlignKind>(
404 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
405 SourceLocation PragmaLoc = ConsumeToken();
406 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
407}
408
Richard Smithba3a4f92016-01-12 21:59:26 +0000409void Parser::HandlePragmaDump() {
410 assert(Tok.is(tok::annot_pragma_dump));
411 IdentifierInfo *II =
412 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
413 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
414 ConsumeToken();
415}
416
Eli Friedman68be1642012-10-04 02:36:51 +0000417void Parser::HandlePragmaWeak() {
418 assert(Tok.is(tok::annot_pragma_weak));
419 SourceLocation PragmaLoc = ConsumeToken();
420 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
421 Tok.getLocation());
422 ConsumeToken(); // The weak name.
423}
424
425void Parser::HandlePragmaWeakAlias() {
426 assert(Tok.is(tok::annot_pragma_weakalias));
427 SourceLocation PragmaLoc = ConsumeToken();
428 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
429 SourceLocation WeakNameLoc = Tok.getLocation();
430 ConsumeToken();
431 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
432 SourceLocation AliasNameLoc = Tok.getLocation();
433 ConsumeToken();
434 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
435 WeakNameLoc, AliasNameLoc);
436
437}
438
439void Parser::HandlePragmaRedefineExtname() {
440 assert(Tok.is(tok::annot_pragma_redefine_extname));
441 SourceLocation RedefLoc = ConsumeToken();
442 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
443 SourceLocation RedefNameLoc = Tok.getLocation();
444 ConsumeToken();
445 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
446 SourceLocation AliasNameLoc = Tok.getLocation();
447 ConsumeToken();
448 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
449 RedefNameLoc, AliasNameLoc);
450}
451
452void Parser::HandlePragmaFPContract() {
453 assert(Tok.is(tok::annot_pragma_fp_contract));
454 tok::OnOffSwitch OOS =
455 static_cast<tok::OnOffSwitch>(
456 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
457 Actions.ActOnPragmaFPContract(OOS);
458 ConsumeToken(); // The annotation token.
459}
460
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000461StmtResult Parser::HandlePragmaCaptured()
462{
463 assert(Tok.is(tok::annot_pragma_captured));
464 ConsumeToken();
465
466 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000467 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000468 return StmtError();
469 }
470
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000471 SourceLocation Loc = Tok.getLocation();
472
473 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000474 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
475 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000476
477 StmtResult R = ParseCompoundStatement();
478 CapturedRegionScope.Exit();
479
480 if (R.isInvalid()) {
481 Actions.ActOnCapturedRegionError();
482 return StmtError();
483 }
484
485 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000486}
487
Eli Friedman68be1642012-10-04 02:36:51 +0000488namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000489 enum OpenCLExtState : char {
490 Disable, Enable, Begin, End
491 };
492 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000493}
494
495void Parser::HandlePragmaOpenCLExtension() {
496 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000497 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
498 auto State = Data->second;
499 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000500 SourceLocation NameLoc = Tok.getLocation();
501 ConsumeToken(); // The annotation token.
502
Yaxun Liu5b746652016-12-18 05:18:55 +0000503 auto &Opt = Actions.getOpenCLOptions();
504 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000505 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
506 // overriding all previously issued extension directives, but only if the
507 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000508 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000509 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000510 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000511 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
512 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000513 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000514 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000515 } else if (State == Begin) {
516 if (!Opt.isKnown(Name) ||
517 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
518 Opt.support(Name);
519 }
520 Actions.setCurrentOpenCLExtension(Name);
521 } else if (State == End) {
522 if (Name != Actions.getCurrentOpenCLExtension())
523 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
524 Actions.setCurrentOpenCLExtension("");
525 } else if (!Opt.isKnown(Name))
526 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
527 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
528 Opt.enable(Name, State == Enable);
529 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
530 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
531 else
532 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000533}
534
David Majnemer4bb09802014-02-10 19:50:15 +0000535void Parser::HandlePragmaMSPointersToMembers() {
536 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000537 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
538 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000539 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
540 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
541 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
542}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000543
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000544void Parser::HandlePragmaMSVtorDisp() {
545 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
546 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000547 Sema::PragmaMsStackAction Action =
548 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000549 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
550 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
Denis Zobnin2290dac2016-04-29 11:27:00 +0000551 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000552}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000553
Warren Huntc3b18962014-04-08 22:30:47 +0000554void Parser::HandlePragmaMSPragma() {
555 assert(Tok.is(tok::annot_pragma_ms_pragma));
556 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000557 auto TheTokens =
558 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
559 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Warren Huntc3b18962014-04-08 22:30:47 +0000560 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
561 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000562 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000563 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000564
Warren Huntc3b18962014-04-08 22:30:47 +0000565 // Figure out which #pragma we're dealing with. The switch has no default
566 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000567 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000568 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
569 .Case("data_seg", &Parser::HandlePragmaMSSegment)
570 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
571 .Case("const_seg", &Parser::HandlePragmaMSSegment)
572 .Case("code_seg", &Parser::HandlePragmaMSSegment)
573 .Case("section", &Parser::HandlePragmaMSSection)
574 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000575
576 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
577 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
578 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000579 while (Tok.isNot(tok::eof))
580 PP.Lex(Tok);
581 PP.Lex(Tok);
582 }
583}
584
Reid Kleckner722b1df2014-07-18 00:13:16 +0000585bool Parser::HandlePragmaMSSection(StringRef PragmaName,
586 SourceLocation PragmaLocation) {
587 if (Tok.isNot(tok::l_paren)) {
588 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
589 return false;
590 }
Warren Huntc3b18962014-04-08 22:30:47 +0000591 PP.Lex(Tok); // (
592 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000593 if (Tok.isNot(tok::string_literal)) {
594 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
595 << PragmaName;
596 return false;
597 }
598 ExprResult StringResult = ParseStringLiteralExpression();
599 if (StringResult.isInvalid())
600 return false; // Already diagnosed.
601 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
602 if (SegmentName->getCharByteWidth() != 1) {
603 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
604 << PragmaName;
605 return false;
606 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000607 int SectionFlags = ASTContext::PSF_Read;
608 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000609 while (Tok.is(tok::comma)) {
610 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000611 // Ignore "long" and "short".
612 // They are undocumented, but widely used, section attributes which appear
613 // to do nothing.
614 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
615 PP.Lex(Tok); // long/short
616 continue;
617 }
618
Reid Kleckner722b1df2014-07-18 00:13:16 +0000619 if (!Tok.isAnyIdentifier()) {
620 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
621 << PragmaName;
622 return false;
623 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000624 ASTContext::PragmaSectionFlag Flag =
625 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000626 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000627 .Case("read", ASTContext::PSF_Read)
628 .Case("write", ASTContext::PSF_Write)
629 .Case("execute", ASTContext::PSF_Execute)
630 .Case("shared", ASTContext::PSF_Invalid)
631 .Case("nopage", ASTContext::PSF_Invalid)
632 .Case("nocache", ASTContext::PSF_Invalid)
633 .Case("discard", ASTContext::PSF_Invalid)
634 .Case("remove", ASTContext::PSF_Invalid)
635 .Default(ASTContext::PSF_None);
636 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
637 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000638 ? diag::warn_pragma_invalid_specific_action
639 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000640 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000641 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000642 }
643 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000644 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000645 PP.Lex(Tok); // Identifier
646 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000647 // If no section attributes are specified, the section will be marked as
648 // read/write.
649 if (SectionFlagsAreDefault)
650 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000651 if (Tok.isNot(tok::r_paren)) {
652 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
653 return false;
654 }
Warren Huntc3b18962014-04-08 22:30:47 +0000655 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000656 if (Tok.isNot(tok::eof)) {
657 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
658 << PragmaName;
659 return false;
660 }
Warren Huntc3b18962014-04-08 22:30:47 +0000661 PP.Lex(Tok); // eof
662 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000663 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000664}
665
Reid Kleckner722b1df2014-07-18 00:13:16 +0000666bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
667 SourceLocation PragmaLocation) {
668 if (Tok.isNot(tok::l_paren)) {
669 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
670 return false;
671 }
Warren Huntc3b18962014-04-08 22:30:47 +0000672 PP.Lex(Tok); // (
673 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000674 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000675 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000676 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000677 if (PushPop == "push")
678 Action = Sema::PSK_Push;
679 else if (PushPop == "pop")
680 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000681 else {
682 PP.Diag(PragmaLocation,
683 diag::warn_pragma_expected_section_push_pop_or_name)
684 << PragmaName;
685 return false;
686 }
Warren Huntc3b18962014-04-08 22:30:47 +0000687 if (Action != Sema::PSK_Reset) {
688 PP.Lex(Tok); // push | pop
689 if (Tok.is(tok::comma)) {
690 PP.Lex(Tok); // ,
691 // If we've got a comma, we either need a label or a string.
692 if (Tok.isAnyIdentifier()) {
693 SlotLabel = Tok.getIdentifierInfo()->getName();
694 PP.Lex(Tok); // identifier
695 if (Tok.is(tok::comma))
696 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000697 else if (Tok.isNot(tok::r_paren)) {
698 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
699 << PragmaName;
700 return false;
701 }
Warren Huntc3b18962014-04-08 22:30:47 +0000702 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000703 } else if (Tok.isNot(tok::r_paren)) {
704 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
705 return false;
706 }
Warren Huntc3b18962014-04-08 22:30:47 +0000707 }
708 }
709 // Grab the string literal for our section name.
710 StringLiteral *SegmentName = nullptr;
711 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000712 if (Tok.isNot(tok::string_literal)) {
713 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000714 diag::warn_pragma_expected_section_name :
715 diag::warn_pragma_expected_section_label_or_name :
716 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000717 PP.Diag(PragmaLocation, DiagID) << PragmaName;
718 return false;
719 }
720 ExprResult StringResult = ParseStringLiteralExpression();
721 if (StringResult.isInvalid())
722 return false; // Already diagnosed.
723 SegmentName = cast<StringLiteral>(StringResult.get());
724 if (SegmentName->getCharByteWidth() != 1) {
725 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
726 << PragmaName;
727 return false;
728 }
Warren Huntc3b18962014-04-08 22:30:47 +0000729 // Setting section "" has no effect
730 if (SegmentName->getLength())
731 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
732 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000733 if (Tok.isNot(tok::r_paren)) {
734 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
735 return false;
736 }
Warren Huntc3b18962014-04-08 22:30:47 +0000737 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000738 if (Tok.isNot(tok::eof)) {
739 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
740 << PragmaName;
741 return false;
742 }
Warren Huntc3b18962014-04-08 22:30:47 +0000743 PP.Lex(Tok); // eof
744 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
745 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000746 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000747}
748
Reid Kleckner1a711b12014-07-22 00:53:05 +0000749// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000750bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
751 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000752 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
753 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
754 return false;
755 }
756
Reid Kleckner1a711b12014-07-22 00:53:05 +0000757 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
758 PragmaName))
759 return false;
760
761 // Parse either the known section names or the string section name.
762 StringLiteral *SegmentName = nullptr;
763 if (Tok.isAnyIdentifier()) {
764 auto *II = Tok.getIdentifierInfo();
765 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
766 .Case("compiler", "\".CRT$XCC\"")
767 .Case("lib", "\".CRT$XCL\"")
768 .Case("user", "\".CRT$XCU\"")
769 .Default("");
770
771 if (!Section.empty()) {
772 // Pretend the user wrote the appropriate string literal here.
773 Token Toks[1];
774 Toks[0].startToken();
775 Toks[0].setKind(tok::string_literal);
776 Toks[0].setLocation(Tok.getLocation());
777 Toks[0].setLiteralData(Section.data());
778 Toks[0].setLength(Section.size());
779 SegmentName =
780 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
781 PP.Lex(Tok);
782 }
783 } else if (Tok.is(tok::string_literal)) {
784 ExprResult StringResult = ParseStringLiteralExpression();
785 if (StringResult.isInvalid())
786 return false;
787 SegmentName = cast<StringLiteral>(StringResult.get());
788 if (SegmentName->getCharByteWidth() != 1) {
789 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
790 << PragmaName;
791 return false;
792 }
793 // FIXME: Add support for the '[, func-name]' part of the pragma.
794 }
795
796 if (!SegmentName) {
797 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
798 return false;
799 }
800
801 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
802 PragmaName) ||
803 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
804 PragmaName))
805 return false;
806
807 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
808 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000809}
810
Benjamin Kramere003ca22015-10-28 13:54:16 +0000811namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000812struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000813 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000814 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000815 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000816};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000817} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000818
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000819static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
820 std::string PragmaString;
821 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
822 PragmaString = "clang loop ";
823 PragmaString += Option.getIdentifierInfo()->getName();
824 } else {
825 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
826 "Unexpected pragma name");
827 PragmaString = "unroll";
828 }
829 return PragmaString;
830}
831
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000832bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000833 assert(Tok.is(tok::annot_pragma_loop_hint));
834 PragmaLoopHintInfo *Info =
835 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
836
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000837 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
838 Hint.PragmaNameLoc = IdentifierLoc::create(
839 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000840
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000841 // It is possible that the loop hint has no option identifier, such as
842 // #pragma unroll(4).
843 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
844 ? Info->Option.getIdentifierInfo()
845 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000846 Hint.OptionLoc = IdentifierLoc::create(
847 Actions.Context, Info->Option.getLocation(), OptionInfo);
848
David Blaikie2eabcc92016-02-09 18:52:09 +0000849 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000850
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000851 // Return a valid hint if pragma unroll or nounroll were specified
852 // without an argument.
853 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
854 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000855 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000856 ConsumeToken(); // The annotation token.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000857 Hint.Range = Info->PragmaName.getLocation();
858 return true;
859 }
860
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000861 // The constant expression is always followed by an eof token, which increases
862 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000863 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000864 "PragmaLoopHintInfo::Toks must contain at least one token.");
865
866 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +0000867 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +0000868 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000869 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +0000870 if (OptionInfo) { // Pragma Unroll does not specify an option.
871 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +0000872 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000873 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
874 .Case("vectorize", true)
875 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +0000876 .Default(false) ||
877 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000878 }
879
Adam Nemet2de463e2016-06-14 12:04:26 +0000880 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000881 // Verify loop hint has an argument.
882 if (Toks[0].is(tok::eof)) {
883 ConsumeToken(); // The annotation token.
884 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +0000885 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
886 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000887 return false;
888 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000889
890 // Validate the argument.
891 if (StateOption) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000892 ConsumeToken(); // The annotation token.
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000893 SourceLocation StateLoc = Toks[0].getLocation();
894 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +0000895
896 bool Valid = StateInfo &&
897 llvm::StringSwitch<bool>(StateInfo->getName())
898 .Cases("enable", "disable", true)
899 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +0000900 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +0000901 .Default(false);
902 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000903 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +0000904 << /*FullKeyword=*/OptionUnroll
905 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000906 return false;
907 }
David Blaikie2eabcc92016-02-09 18:52:09 +0000908 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000909 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
910 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000911 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
912 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000913 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000914 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000915 ConsumeToken(); // The annotation token.
916
917 ExprResult R = ParseConstantExpression();
918
919 // Tokens following an error in an ill-formed constant expression will
920 // remain in the token stream and must be removed.
921 if (Tok.isNot(tok::eof)) {
922 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
923 << PragmaLoopHintString(Info->PragmaName, Info->Option);
924 while (Tok.isNot(tok::eof))
925 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000926 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000927
928 ConsumeToken(); // Consume the constant expression eof terminator.
929
930 if (R.isInvalid() ||
931 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
932 return false;
933
934 // Argument is a constant expression with an integer type.
935 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000936 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000937
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000938 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +0000939 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000940 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000941}
942
943// #pragma GCC visibility comes in two variants:
944// 'push' '(' [visibility] ')'
945// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000946void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
947 PragmaIntroducerKind Introducer,
948 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000949 SourceLocation VisLoc = VisTok.getLocation();
950
951 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000952 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000953
954 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
955
Eli Friedman570024a2010-08-05 06:57:20 +0000956 const IdentifierInfo *VisType;
957 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +0000958 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +0000959 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000960 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000961 if (Tok.isNot(tok::l_paren)) {
962 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
963 << "visibility";
964 return;
965 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000966 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000967 VisType = Tok.getIdentifierInfo();
968 if (!VisType) {
969 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
970 << "visibility";
971 return;
972 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000973 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000974 if (Tok.isNot(tok::r_paren)) {
975 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
976 << "visibility";
977 return;
978 }
979 } else {
980 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
981 << "visibility";
982 return;
983 }
David Majnemera8f2f1d2015-03-19 00:10:23 +0000984 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000985 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000986 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000987 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
988 << "visibility";
989 return;
990 }
991
David Blaikie2eabcc92016-02-09 18:52:09 +0000992 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +0000993 Toks[0].startToken();
994 Toks[0].setKind(tok::annot_pragma_vis);
995 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +0000996 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +0000997 Toks[0].setAnnotationValue(
998 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +0000999 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001000}
1001
Daniel Dunbar921b9682008-10-04 19:21:03 +00001002// #pragma pack(...) comes in the following delicious flavors:
1003// pack '(' [integer] ')'
1004// pack '(' 'show' ')'
1005// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001006void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1007 PragmaIntroducerKind Introducer,
1008 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001009 SourceLocation PackLoc = PackTok.getLocation();
1010
1011 Token Tok;
1012 PP.Lex(Tok);
1013 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001014 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001015 return;
1016 }
1017
Denis Zobnin10c4f452016-04-29 18:17:40 +00001018 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1019 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001020 Token Alignment;
1021 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001022 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001023 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001024 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001025
1026 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001027
1028 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1029 // the push/pop stack.
1030 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001031 Action =
1032 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001033 } else if (Tok.is(tok::identifier)) {
1034 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001035 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001036 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001037 PP.Lex(Tok);
1038 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001039 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001040 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001041 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001042 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001043 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001044 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001045 return;
Mike Stump11289f42009-09-09 15:08:12 +00001046 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001047 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001048
Daniel Dunbar921b9682008-10-04 19:21:03 +00001049 if (Tok.is(tok::comma)) {
1050 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001051
Daniel Dunbar921b9682008-10-04 19:21:03 +00001052 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001053 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001054 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001055
1056 PP.Lex(Tok);
1057 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001058 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001059 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001060
Daniel Dunbar921b9682008-10-04 19:21:03 +00001061 if (Tok.is(tok::comma)) {
1062 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001063
Daniel Dunbar921b9682008-10-04 19:21:03 +00001064 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001065 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001066 return;
1067 }
Mike Stump11289f42009-09-09 15:08:12 +00001068
Denis Zobnin10c4f452016-04-29 18:17:40 +00001069 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001070 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001071
1072 PP.Lex(Tok);
1073 }
1074 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001075 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001076 return;
1077 }
1078 }
1079 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001080 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001081 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1082 // the push/pop stack.
1083 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001084 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001085 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001086
1087 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001088 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001089 return;
1090 }
1091
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001092 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001093 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001094 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001095 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1096 return;
1097 }
1098
David Blaikie2eabcc92016-02-09 18:52:09 +00001099 PragmaPackInfo *Info =
1100 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001101 Info->Action = Action;
1102 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001103 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001104
David Blaikie2eabcc92016-02-09 18:52:09 +00001105 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1106 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001107 Toks[0].startToken();
1108 Toks[0].setKind(tok::annot_pragma_pack);
1109 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001110 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001111 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001112 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001113}
1114
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001115// #pragma ms_struct on
1116// #pragma ms_struct off
1117void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1118 PragmaIntroducerKind Introducer,
1119 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001120 PragmaMSStructKind Kind = PMSST_OFF;
1121
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001122 Token Tok;
1123 PP.Lex(Tok);
1124 if (Tok.isNot(tok::identifier)) {
1125 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1126 return;
1127 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001128 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001129 const IdentifierInfo *II = Tok.getIdentifierInfo();
1130 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001131 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001132 PP.Lex(Tok);
1133 }
1134 else if (II->isStr("off") || II->isStr("reset"))
1135 PP.Lex(Tok);
1136 else {
1137 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1138 return;
1139 }
1140
1141 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001142 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1143 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001144 return;
1145 }
Eli Friedman68be1642012-10-04 02:36:51 +00001146
David Blaikie2eabcc92016-02-09 18:52:09 +00001147 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1148 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001149 Toks[0].startToken();
1150 Toks[0].setKind(tok::annot_pragma_msstruct);
1151 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001152 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001153 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1154 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001155 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001156}
1157
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001158// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1159// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001160static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001161 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001162 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001163
1164 if (IsOptions) {
1165 PP.Lex(Tok);
1166 if (Tok.isNot(tok::identifier) ||
1167 !Tok.getIdentifierInfo()->isStr("align")) {
1168 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1169 return;
1170 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001171 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001172
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001173 PP.Lex(Tok);
1174 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001175 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1176 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001177 return;
1178 }
1179
1180 PP.Lex(Tok);
1181 if (Tok.isNot(tok::identifier)) {
1182 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001183 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001184 return;
1185 }
1186
John McCallfaf5fb42010-08-26 23:41:50 +00001187 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001188 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001189 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001190 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001191 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001192 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001193 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001194 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001195 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001196 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001197 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001198 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001199 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001200 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001201 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001202 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1203 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001204 return;
1205 }
1206
David Majnemera8f2f1d2015-03-19 00:10:23 +00001207 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001208 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001209 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001210 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001211 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001212 return;
1213 }
1214
David Blaikie2eabcc92016-02-09 18:52:09 +00001215 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1216 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001217 Toks[0].startToken();
1218 Toks[0].setKind(tok::annot_pragma_align);
1219 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001220 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001221 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1222 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001223 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001224}
1225
Douglas Gregorc7d65762010-09-09 22:45:38 +00001226void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1227 PragmaIntroducerKind Introducer,
1228 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001229 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001230}
1231
Douglas Gregorc7d65762010-09-09 22:45:38 +00001232void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1233 PragmaIntroducerKind Introducer,
1234 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001235 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001236}
1237
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001238// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001239void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1240 PragmaIntroducerKind Introducer,
1241 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001242 // FIXME: Should we be expanding macros here? My guess is no.
1243 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001244
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001245 // Lex the left '('.
1246 Token Tok;
1247 PP.Lex(Tok);
1248 if (Tok.isNot(tok::l_paren)) {
1249 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1250 return;
1251 }
Mike Stump11289f42009-09-09 15:08:12 +00001252
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001253 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001254 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001255 SourceLocation RParenLoc;
1256 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001257
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001258 while (true) {
1259 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001260
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001261 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001262 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001263 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001264 LexID = false;
1265 continue;
1266 }
1267
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001268 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001269 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1270 return;
1271 }
Mike Stump11289f42009-09-09 15:08:12 +00001272
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001273 // We are execting a ')' or a ','.
1274 if (Tok.is(tok::comma)) {
1275 LexID = true;
1276 continue;
1277 }
Mike Stump11289f42009-09-09 15:08:12 +00001278
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001279 if (Tok.is(tok::r_paren)) {
1280 RParenLoc = Tok.getLocation();
1281 break;
1282 }
Mike Stump11289f42009-09-09 15:08:12 +00001283
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001284 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001285 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001286 return;
1287 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001288
1289 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001290 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001291 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1292 "unused";
1293 return;
1294 }
1295
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001296 // Verify that we have a location for the right parenthesis.
1297 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001298 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001299
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001300 // For each identifier token, insert into the token stream a
1301 // annot_pragma_unused token followed by the identifier token.
1302 // This allows us to cache a "#pragma unused" that occurs inside an inline
1303 // C++ member function.
1304
David Blaikie2eabcc92016-02-09 18:52:09 +00001305 MutableArrayRef<Token> Toks(
1306 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1307 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001308 for (unsigned i=0; i != Identifiers.size(); i++) {
1309 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1310 pragmaUnusedTok.startToken();
1311 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1312 pragmaUnusedTok.setLocation(UnusedLoc);
1313 idTok = Identifiers[i];
1314 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001315 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001316}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001317
1318// #pragma weak identifier
1319// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001320void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1321 PragmaIntroducerKind Introducer,
1322 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001323 SourceLocation WeakLoc = WeakTok.getLocation();
1324
1325 Token Tok;
1326 PP.Lex(Tok);
1327 if (Tok.isNot(tok::identifier)) {
1328 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1329 return;
1330 }
1331
Eli Friedman68be1642012-10-04 02:36:51 +00001332 Token WeakName = Tok;
1333 bool HasAlias = false;
1334 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001335
1336 PP.Lex(Tok);
1337 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001338 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001339 PP.Lex(Tok);
1340 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001341 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001342 << "weak";
1343 return;
1344 }
Eli Friedman68be1642012-10-04 02:36:51 +00001345 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001346 PP.Lex(Tok);
1347 }
1348
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001349 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001350 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1351 return;
1352 }
1353
Eli Friedman68be1642012-10-04 02:36:51 +00001354 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001355 MutableArrayRef<Token> Toks(
1356 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001357 Token &pragmaUnusedTok = Toks[0];
1358 pragmaUnusedTok.startToken();
1359 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1360 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001361 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001362 Toks[1] = WeakName;
1363 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001364 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001365 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001366 MutableArrayRef<Token> Toks(
1367 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001368 Token &pragmaUnusedTok = Toks[0];
1369 pragmaUnusedTok.startToken();
1370 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1371 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001372 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001373 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001374 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001375 }
1376}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001377
David Chisnall0867d9c2012-02-18 16:12:34 +00001378// #pragma redefine_extname identifier identifier
1379void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1380 PragmaIntroducerKind Introducer,
1381 Token &RedefToken) {
1382 SourceLocation RedefLoc = RedefToken.getLocation();
1383
1384 Token Tok;
1385 PP.Lex(Tok);
1386 if (Tok.isNot(tok::identifier)) {
1387 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1388 "redefine_extname";
1389 return;
1390 }
1391
Eli Friedman68be1642012-10-04 02:36:51 +00001392 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001393 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001394
David Chisnall0867d9c2012-02-18 16:12:34 +00001395 if (Tok.isNot(tok::identifier)) {
1396 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1397 << "redefine_extname";
1398 return;
1399 }
Eli Friedman68be1642012-10-04 02:36:51 +00001400
1401 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001402 PP.Lex(Tok);
1403
1404 if (Tok.isNot(tok::eod)) {
1405 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1406 "redefine_extname";
1407 return;
1408 }
1409
David Blaikie2eabcc92016-02-09 18:52:09 +00001410 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1411 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001412 Token &pragmaRedefTok = Toks[0];
1413 pragmaRedefTok.startToken();
1414 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1415 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001416 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001417 Toks[1] = RedefName;
1418 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001419 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00001420}
1421
1422
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001423void
1424PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1425 PragmaIntroducerKind Introducer,
1426 Token &Tok) {
1427 tok::OnOffSwitch OOS;
1428 if (PP.LexOnOffSwitch(OOS))
1429 return;
1430
David Blaikie2eabcc92016-02-09 18:52:09 +00001431 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1432 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001433 Toks[0].startToken();
1434 Toks[0].setKind(tok::annot_pragma_fp_contract);
1435 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001436 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001437 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1438 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001439 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001440}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001441
1442void
1443PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1444 PragmaIntroducerKind Introducer,
1445 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001446 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001447 if (Tok.isNot(tok::identifier)) {
1448 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1449 "OPENCL";
1450 return;
1451 }
Yaxun Liu5b746652016-12-18 05:18:55 +00001452 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001453 SourceLocation NameLoc = Tok.getLocation();
1454
1455 PP.Lex(Tok);
1456 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00001457 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001458 return;
1459 }
1460
1461 PP.Lex(Tok);
1462 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00001463 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001464 return;
1465 }
Yaxun Liu5b746652016-12-18 05:18:55 +00001466 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001467
Yaxun Liu5b746652016-12-18 05:18:55 +00001468 OpenCLExtState State;
1469 if (Pred->isStr("enable")) {
1470 State = Enable;
1471 } else if (Pred->isStr("disable")) {
1472 State = Disable;
1473 } else if (Pred->isStr("begin"))
1474 State = Begin;
1475 else if (Pred->isStr("end"))
1476 State = End;
1477 else {
1478 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
1479 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001480 return;
1481 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001482 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001483
Eli Friedman68be1642012-10-04 02:36:51 +00001484 PP.Lex(Tok);
1485 if (Tok.isNot(tok::eod)) {
1486 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1487 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001488 return;
1489 }
Eli Friedman68be1642012-10-04 02:36:51 +00001490
Yaxun Liu5b746652016-12-18 05:18:55 +00001491 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
1492 Info->first = Ext;
1493 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00001494 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1495 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001496 Toks[0].startToken();
1497 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1498 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00001499 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00001500 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00001501 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001502
1503 if (PP.getPPCallbacks())
Yaxun Liu5b746652016-12-18 05:18:55 +00001504 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
1505 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001506}
1507
Alexey Bataeva769e072013-03-22 06:34:35 +00001508/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1509///
1510void
1511PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1512 PragmaIntroducerKind Introducer,
1513 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00001514 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1515 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00001516 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00001517 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1518 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00001519 }
1520 PP.DiscardUntilEndOfDirective();
1521}
1522
1523/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1524///
1525void
1526PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1527 PragmaIntroducerKind Introducer,
1528 Token &FirstTok) {
1529 SmallVector<Token, 16> Pragma;
1530 Token Tok;
1531 Tok.startToken();
1532 Tok.setKind(tok::annot_pragma_openmp);
1533 Tok.setLocation(FirstTok.getLocation());
1534
1535 while (Tok.isNot(tok::eod)) {
1536 Pragma.push_back(Tok);
1537 PP.Lex(Tok);
1538 }
1539 SourceLocation EodLoc = Tok.getLocation();
1540 Tok.startToken();
1541 Tok.setKind(tok::annot_pragma_openmp_end);
1542 Tok.setLocation(EodLoc);
1543 Pragma.push_back(Tok);
1544
David Blaikie2eabcc92016-02-09 18:52:09 +00001545 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
1546 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
1547 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
1548 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00001549}
Reid Kleckner002562a2013-05-06 21:02:12 +00001550
David Majnemer4bb09802014-02-10 19:50:15 +00001551/// \brief Handle '#pragma pointers_to_members'
1552// The grammar for this pragma is as follows:
1553//
1554// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1555//
1556// #pragma pointers_to_members '(' 'best_case' ')'
1557// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1558// #pragma pointers_to_members '(' inheritance-model ')'
1559void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1560 PragmaIntroducerKind Introducer,
1561 Token &Tok) {
1562 SourceLocation PointersToMembersLoc = Tok.getLocation();
1563 PP.Lex(Tok);
1564 if (Tok.isNot(tok::l_paren)) {
1565 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1566 << "pointers_to_members";
1567 return;
1568 }
1569 PP.Lex(Tok);
1570 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1571 if (!Arg) {
1572 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1573 << "pointers_to_members";
1574 return;
1575 }
1576 PP.Lex(Tok);
1577
David Majnemer86c318f2014-02-11 21:05:00 +00001578 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001579 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001580 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001581 } else {
1582 if (Arg->isStr("full_generality")) {
1583 if (Tok.is(tok::comma)) {
1584 PP.Lex(Tok);
1585
1586 Arg = Tok.getIdentifierInfo();
1587 if (!Arg) {
1588 PP.Diag(Tok.getLocation(),
1589 diag::err_pragma_pointers_to_members_unknown_kind)
1590 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1591 return;
1592 }
1593 PP.Lex(Tok);
1594 } else if (Tok.is(tok::r_paren)) {
1595 // #pragma pointers_to_members(full_generality) implicitly specifies
1596 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00001597 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00001598 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001599 } else {
1600 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1601 << "full_generality";
1602 return;
1603 }
1604 }
1605
1606 if (Arg) {
1607 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001608 RepresentationMethod =
1609 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001610 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001611 RepresentationMethod =
1612 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001613 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001614 RepresentationMethod =
1615 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001616 } else {
1617 PP.Diag(Tok.getLocation(),
1618 diag::err_pragma_pointers_to_members_unknown_kind)
1619 << Arg << /*HasPointerDeclaration*/ 1;
1620 return;
1621 }
1622 }
1623 }
1624
1625 if (Tok.isNot(tok::r_paren)) {
1626 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1627 << (Arg ? Arg->getName() : "full_generality");
1628 return;
1629 }
1630
David Majnemera8f2f1d2015-03-19 00:10:23 +00001631 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00001632 PP.Lex(Tok);
1633 if (Tok.isNot(tok::eod)) {
1634 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1635 << "pointers_to_members";
1636 return;
1637 }
1638
1639 Token AnnotTok;
1640 AnnotTok.startToken();
1641 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1642 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001643 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00001644 AnnotTok.setAnnotationValue(
1645 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1646 PP.EnterToken(AnnotTok);
1647}
1648
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001649/// \brief Handle '#pragma vtordisp'
1650// The grammar for this pragma is as follows:
1651//
1652// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1653//
1654// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1655// #pragma vtordisp '(' 'pop' ')'
1656// #pragma vtordisp '(' ')'
1657void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1658 PragmaIntroducerKind Introducer,
1659 Token &Tok) {
1660 SourceLocation VtorDispLoc = Tok.getLocation();
1661 PP.Lex(Tok);
1662 if (Tok.isNot(tok::l_paren)) {
1663 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1664 return;
1665 }
1666 PP.Lex(Tok);
1667
Denis Zobnin2290dac2016-04-29 11:27:00 +00001668 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001669 const IdentifierInfo *II = Tok.getIdentifierInfo();
1670 if (II) {
1671 if (II->isStr("push")) {
1672 // #pragma vtordisp(push, mode)
1673 PP.Lex(Tok);
1674 if (Tok.isNot(tok::comma)) {
1675 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1676 return;
1677 }
1678 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00001679 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001680 // not push, could be on/off
1681 } else if (II->isStr("pop")) {
1682 // #pragma vtordisp(pop)
1683 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00001684 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001685 }
1686 // not push or pop, could be on/off
1687 } else {
1688 if (Tok.is(tok::r_paren)) {
1689 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00001690 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001691 }
1692 }
1693
1694
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001695 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00001696 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001697 const IdentifierInfo *II = Tok.getIdentifierInfo();
1698 if (II && II->isStr("off")) {
1699 PP.Lex(Tok);
1700 Value = 0;
1701 } else if (II && II->isStr("on")) {
1702 PP.Lex(Tok);
1703 Value = 1;
1704 } else if (Tok.is(tok::numeric_constant) &&
1705 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1706 if (Value > 2) {
1707 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1708 << 0 << 2 << "vtordisp";
1709 return;
1710 }
1711 } else {
1712 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1713 << "vtordisp";
1714 return;
1715 }
1716 }
1717
1718 // Finish the pragma: ')' $
1719 if (Tok.isNot(tok::r_paren)) {
1720 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1721 return;
1722 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001723 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001724 PP.Lex(Tok);
1725 if (Tok.isNot(tok::eod)) {
1726 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1727 << "vtordisp";
1728 return;
1729 }
1730
1731 // Enter the annotation.
1732 Token AnnotTok;
1733 AnnotTok.startToken();
1734 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1735 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001736 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001737 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00001738 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001739 PP.EnterToken(AnnotTok);
1740}
1741
Warren Huntc3b18962014-04-08 22:30:47 +00001742/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1743/// an annotation token.
1744void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1745 PragmaIntroducerKind Introducer,
1746 Token &Tok) {
1747 Token EoF, AnnotTok;
1748 EoF.startToken();
1749 EoF.setKind(tok::eof);
1750 AnnotTok.startToken();
1751 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1752 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001753 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00001754 SmallVector<Token, 8> TokenVector;
1755 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00001756 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00001757 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001758 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1759 }
Warren Huntc3b18962014-04-08 22:30:47 +00001760 // Add a sentinal EoF token to the end of the list.
1761 TokenVector.push_back(EoF);
1762 // We must allocate this array with new because EnterTokenStream is going to
1763 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00001764 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
1765 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00001766 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00001767 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
1768 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00001769 AnnotTok.setAnnotationValue(Value);
1770 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001771}
1772
Aaron Ballman5d041be2013-06-04 02:07:14 +00001773/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1774///
1775/// The syntax is:
1776/// \code
1777/// #pragma detect_mismatch("name", "value")
1778/// \endcode
1779/// Where 'name' and 'value' are quoted strings. The values are embedded in
1780/// the object file and passed along to the linker. If the linker detects a
1781/// mismatch in the object file's values for the given name, a LNK2038 error
1782/// is emitted. See MSDN for more details.
1783void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1784 PragmaIntroducerKind Introducer,
1785 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00001786 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00001787 PP.Lex(Tok);
1788 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00001789 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001790 return;
1791 }
1792
1793 // Read the name to embed, which must be a string literal.
1794 std::string NameString;
1795 if (!PP.LexStringLiteral(Tok, NameString,
1796 "pragma detect_mismatch",
1797 /*MacroExpansion=*/true))
1798 return;
1799
1800 // Read the comma followed by a second string literal.
1801 std::string ValueString;
1802 if (Tok.isNot(tok::comma)) {
1803 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1804 return;
1805 }
1806
1807 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1808 /*MacroExpansion=*/true))
1809 return;
1810
1811 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001812 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001813 return;
1814 }
1815 PP.Lex(Tok); // Eat the r_paren.
1816
1817 if (Tok.isNot(tok::eod)) {
1818 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1819 return;
1820 }
1821
Reid Kleckner71966c92014-02-20 23:37:45 +00001822 // If the pragma is lexically sound, notify any interested PPCallbacks.
1823 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00001824 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00001825 ValueString);
1826
Nico Webercbbaeb12016-03-02 19:28:54 +00001827 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00001828}
1829
Reid Kleckner002562a2013-05-06 21:02:12 +00001830/// \brief Handle the microsoft \#pragma comment extension.
1831///
1832/// The syntax is:
1833/// \code
1834/// #pragma comment(linker, "foo")
1835/// \endcode
1836/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1837/// "foo" is a string, which is fully macro expanded, and permits string
1838/// concatenation, embedded escape characters etc. See MSDN for more details.
1839void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1840 PragmaIntroducerKind Introducer,
1841 Token &Tok) {
1842 SourceLocation CommentLoc = Tok.getLocation();
1843 PP.Lex(Tok);
1844 if (Tok.isNot(tok::l_paren)) {
1845 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1846 return;
1847 }
1848
1849 // Read the identifier.
1850 PP.Lex(Tok);
1851 if (Tok.isNot(tok::identifier)) {
1852 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1853 return;
1854 }
1855
1856 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001857 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00001858 PragmaMSCommentKind Kind =
1859 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
1860 .Case("linker", PCK_Linker)
1861 .Case("lib", PCK_Lib)
1862 .Case("compiler", PCK_Compiler)
1863 .Case("exestr", PCK_ExeStr)
1864 .Case("user", PCK_User)
1865 .Default(PCK_Unknown);
1866 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001867 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1868 return;
1869 }
1870
Yunzhong Gao99efc032015-03-23 20:41:42 +00001871 // On PS4, issue a warning about any pragma comments other than
1872 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00001873 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00001874 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
1875 << II->getName();
1876 return;
1877 }
1878
Reid Kleckner002562a2013-05-06 21:02:12 +00001879 // Read the optional string if present.
1880 PP.Lex(Tok);
1881 std::string ArgumentString;
1882 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1883 "pragma comment",
1884 /*MacroExpansion=*/true))
1885 return;
1886
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001887 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001888 // FIXME: If the kind is "compiler" warn if the string is present (it is
1889 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001890 // The MSDN docs say that "lib" and "linker" require a string and have a short
1891 // whitelist of linker options they support, but in practice MSVC doesn't
1892 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001893
1894 if (Tok.isNot(tok::r_paren)) {
1895 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1896 return;
1897 }
1898 PP.Lex(Tok); // eat the r_paren.
1899
1900 if (Tok.isNot(tok::eod)) {
1901 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1902 return;
1903 }
1904
Reid Kleckner71966c92014-02-20 23:37:45 +00001905 // If the pragma is lexically sound, notify any interested PPCallbacks.
1906 if (PP.getPPCallbacks())
1907 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1908
Nico Weber66220292016-03-02 17:28:48 +00001909 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001910}
Dario Domizioli13a0a382014-05-23 12:13:25 +00001911
1912// #pragma clang optimize off
1913// #pragma clang optimize on
1914void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1915 PragmaIntroducerKind Introducer,
1916 Token &FirstToken) {
1917 Token Tok;
1918 PP.Lex(Tok);
1919 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001920 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00001921 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00001922 return;
1923 }
1924 if (Tok.isNot(tok::identifier)) {
1925 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1926 << PP.getSpelling(Tok);
1927 return;
1928 }
1929 const IdentifierInfo *II = Tok.getIdentifierInfo();
1930 // The only accepted values are 'on' or 'off'.
1931 bool IsOn = false;
1932 if (II->isStr("on")) {
1933 IsOn = true;
1934 } else if (!II->isStr("off")) {
1935 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1936 << PP.getSpelling(Tok);
1937 return;
1938 }
1939 PP.Lex(Tok);
1940
1941 if (Tok.isNot(tok::eod)) {
1942 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1943 << PP.getSpelling(Tok);
1944 return;
1945 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001946
1947 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1948}
1949
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001950/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001951static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1952 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001953 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001954 SmallVector<Token, 1> ValueList;
1955 int OpenParens = ValueInParens ? 1 : 0;
1956 // Read constant expression.
1957 while (Tok.isNot(tok::eod)) {
1958 if (Tok.is(tok::l_paren))
1959 OpenParens++;
1960 else if (Tok.is(tok::r_paren)) {
1961 OpenParens--;
1962 if (OpenParens == 0 && ValueInParens)
1963 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001964 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001965
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001966 ValueList.push_back(Tok);
1967 PP.Lex(Tok);
1968 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001969
1970 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001971 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001972 if (Tok.isNot(tok::r_paren)) {
1973 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1974 return true;
1975 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001976 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001977 }
1978
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001979 Token EOFTok;
1980 EOFTok.startToken();
1981 EOFTok.setKind(tok::eof);
1982 EOFTok.setLocation(Tok.getLocation());
1983 ValueList.push_back(EOFTok); // Terminates expression for parsing.
1984
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00001985 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001986
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001987 Info.PragmaName = PragmaName;
1988 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001989 return false;
1990}
1991
Eli Bendersky06a40422014-06-06 20:31:48 +00001992/// \brief Handle the \#pragma clang loop directive.
1993/// #pragma clang 'loop' loop-hints
1994///
1995/// loop-hints:
1996/// loop-hint loop-hints[opt]
1997///
1998/// loop-hint:
1999/// 'vectorize' '(' loop-hint-keyword ')'
2000/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002001/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002002/// 'vectorize_width' '(' loop-hint-value ')'
2003/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002004/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002005///
2006/// loop-hint-keyword:
2007/// 'enable'
2008/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002009/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002010///
Mark Heffernan450c2382014-07-23 17:31:31 +00002011/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002012/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002013/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002014/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002015///
Eli Bendersky06a40422014-06-06 20:31:48 +00002016/// loop-hint-value:
2017/// constant-expression
2018///
2019/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2020/// try vectorizing the instructions of the loop it precedes. Specifying
2021/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2022/// interleaving multiple iterations of the loop it precedes. The width of the
2023/// vector instructions is specified by vectorize_width() and the number of
2024/// interleaved loop iterations is specified by interleave_count(). Specifying a
2025/// value of 1 effectively disables vectorization/interleaving, even if it is
2026/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2027/// only works on inner loops.
2028///
Eli Bendersky86483b32014-06-11 17:56:26 +00002029/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002030/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2031/// completely if the trip count is known at compile time and unroll partially
2032/// if the trip count is not known. Specifying unroll(full) is similar to
2033/// unroll(enable) but will unroll the loop only if the trip count is known at
2034/// compile time. Specifying unroll(disable) disables unrolling for the
2035/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2036/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002037void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2038 PragmaIntroducerKind Introducer,
2039 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002040 // Incoming token is "loop" from "#pragma clang loop".
2041 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002042 SmallVector<Token, 1> TokenList;
2043
2044 // Lex the optimization option and verify it is an identifier.
2045 PP.Lex(Tok);
2046 if (Tok.isNot(tok::identifier)) {
2047 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2048 << /*MissingOption=*/true << "";
2049 return;
2050 }
2051
2052 while (Tok.is(tok::identifier)) {
2053 Token Option = Tok;
2054 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2055
Eli Bendersky86483b32014-06-11 17:56:26 +00002056 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002057 .Case("vectorize", true)
2058 .Case("interleave", true)
2059 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002060 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002061 .Case("vectorize_width", true)
2062 .Case("interleave_count", true)
2063 .Case("unroll_count", true)
2064 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002065 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002066 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2067 << /*MissingOption=*/false << OptionInfo;
2068 return;
2069 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002070 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002071
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002072 // Read '('
2073 if (Tok.isNot(tok::l_paren)) {
2074 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002075 return;
2076 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002077 PP.Lex(Tok);
2078
2079 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2080 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2081 *Info))
2082 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002083
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002084 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002085 Token LoopHintTok;
2086 LoopHintTok.startToken();
2087 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002088 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002089 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002090 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2091 TokenList.push_back(LoopHintTok);
2092 }
2093
2094 if (Tok.isNot(tok::eod)) {
2095 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2096 << "clang loop";
2097 return;
2098 }
2099
David Blaikie2eabcc92016-02-09 18:52:09 +00002100 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2101 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002102
David Blaikie2eabcc92016-02-09 18:52:09 +00002103 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2104 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002105}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002106
2107/// \brief Handle the loop unroll optimization pragmas.
2108/// #pragma unroll
2109/// #pragma unroll unroll-hint-value
2110/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002111/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002112///
2113/// unroll-hint-value:
2114/// constant-expression
2115///
Mark Heffernanc888e412014-07-24 18:09:38 +00002116/// Loop unrolling hints can be specified with '#pragma unroll' or
2117/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2118/// contained in parentheses. With no argument the directive instructs llvm to
2119/// try to unroll the loop completely. A positive integer argument can be
2120/// specified to indicate the number of times the loop should be unrolled. To
2121/// maximize compatibility with other compilers the unroll count argument can be
2122/// specified with or without parentheses. Specifying, '#pragma nounroll'
2123/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002124void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2125 PragmaIntroducerKind Introducer,
2126 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002127 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2128 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002129 Token PragmaName = Tok;
2130 PP.Lex(Tok);
2131 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2132 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002133 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002134 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002135 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002136 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2137 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2138 << "nounroll";
2139 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002140 } else {
2141 // Unroll pragma with an argument: "#pragma unroll N" or
2142 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002143 // Read '(' if it exists.
2144 bool ValueInParens = Tok.is(tok::l_paren);
2145 if (ValueInParens)
2146 PP.Lex(Tok);
2147
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002148 Token Option;
2149 Option.startToken();
2150 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002151 return;
2152
2153 // In CUDA, the argument to '#pragma unroll' should not be contained in
2154 // parentheses.
2155 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002156 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002157 diag::warn_pragma_unroll_cuda_value_in_parens);
2158
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002159 if (Tok.isNot(tok::eod)) {
2160 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2161 << "unroll";
2162 return;
2163 }
2164 }
2165
2166 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002167 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002168 TokenArray[0].startToken();
2169 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2170 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002171 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002172 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002173 PP.EnterTokenStream(std::move(TokenArray), 1,
2174 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002175}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002176
2177/// \brief Handle the Microsoft \#pragma intrinsic extension.
2178///
2179/// The syntax is:
2180/// \code
2181/// #pragma intrinsic(memset)
2182/// #pragma intrinsic(strlen, memcpy)
2183/// \endcode
2184///
2185/// Pragma intrisic tells the compiler to use a builtin version of the
2186/// function. Clang does it anyway, so the pragma doesn't really do anything.
2187/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2188/// isn't an intrinsic in clang and suggest to include intrin.h.
2189void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2190 PragmaIntroducerKind Introducer,
2191 Token &Tok) {
2192 PP.Lex(Tok);
2193
2194 if (Tok.isNot(tok::l_paren)) {
2195 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2196 << "intrinsic";
2197 return;
2198 }
2199 PP.Lex(Tok);
2200
2201 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2202
2203 while (Tok.is(tok::identifier)) {
2204 IdentifierInfo *II = Tok.getIdentifierInfo();
2205 if (!II->getBuiltinID())
2206 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2207 << II << SuggestIntrinH;
2208
2209 PP.Lex(Tok);
2210 if (Tok.isNot(tok::comma))
2211 break;
2212 PP.Lex(Tok);
2213 }
2214
2215 if (Tok.isNot(tok::r_paren)) {
2216 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2217 << "intrinsic";
2218 return;
2219 }
2220 PP.Lex(Tok);
2221
2222 if (Tok.isNot(tok::eod))
2223 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2224 << "intrinsic";
2225}
Justin Lebar67a78a62016-10-08 22:15:58 +00002226void PragmaForceCUDAHostDeviceHandler::HandlePragma(
2227 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
2228 Token FirstTok = Tok;
2229
2230 PP.Lex(Tok);
2231 IdentifierInfo *Info = Tok.getIdentifierInfo();
2232 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
2233 PP.Diag(FirstTok.getLocation(),
2234 diag::warn_pragma_force_cuda_host_device_bad_arg);
2235 return;
2236 }
2237
2238 if (Info->isStr("begin"))
2239 Actions.PushForceCUDAHostDevice();
2240 else if (!Actions.PopForceCUDAHostDevice())
2241 PP.Diag(FirstTok.getLocation(),
2242 diag::err_pragma_cannot_end_force_cuda_host_device);
2243
2244 PP.Lex(Tok);
2245 if (!Tok.is(tok::eod))
2246 PP.Diag(FirstTok.getLocation(),
2247 diag::warn_pragma_force_cuda_host_device_bad_arg);
2248}