blob: d6539c9610b5bf46c85b5a6f0ddecfd47f61e8ac [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
Warren Huntc3b18962014-04-08 22:30:47 +000014#include "RAIIObjectsForParser.h"
Hans Wennborg899ded92014-10-16 20:52:46 +000015#include "clang/AST/ASTContext.h"
Nico Weber66220292016-03-02 17:28:48 +000016#include "clang/Basic/PragmaKinds.h"
David Majnemerad2986e2014-08-14 06:35:08 +000017#include "clang/Basic/TargetInfo.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000018#include "clang/Lex/Preprocessor.h"
19#include "clang/Parse/ParseDiagnostic.h"
20#include "clang/Parse/Parser.h"
21#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 {
489 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
490}
491
492void Parser::HandlePragmaOpenCLExtension() {
493 assert(Tok.is(tok::annot_pragma_opencl_extension));
494 OpenCLExtData data =
495 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
496 unsigned state = data.getInt();
497 IdentifierInfo *ename = data.getPointer();
498 SourceLocation NameLoc = Tok.getLocation();
499 ConsumeToken(); // The annotation token.
500
501 OpenCLOptions &f = Actions.getOpenCLOptions();
Yaxun Liu39cf40f2016-05-16 17:06:34 +0000502 auto CLVer = getLangOpts().OpenCLVersion;
503 auto &Supp = getTargetInfo().getSupportedOpenCLOpts();
Eli Friedman68be1642012-10-04 02:36:51 +0000504 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
505 // overriding all previously issued extension directives, but only if the
506 // behavior is set to disable."
507 if (state == 0 && ename->isStr("all")) {
Yaxun Liu39cf40f2016-05-16 17:06:34 +0000508#define OPENCLEXT(nm) \
509 if (Supp.is_##nm##_supported_extension(CLVer)) \
510 f.nm = 0;
Eli Friedman68be1642012-10-04 02:36:51 +0000511#include "clang/Basic/OpenCLExtensions.def"
512 }
Yaxun Liu39cf40f2016-05-16 17:06:34 +0000513#define OPENCLEXT(nm) else if (ename->isStr(#nm)) \
514 if (Supp.is_##nm##_supported_extension(CLVer)) \
515 f.nm = state; \
516 else if (Supp.is_##nm##_supported_core(CLVer)) \
517 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << ename; \
518 else \
519 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << ename;
Eli Friedman68be1642012-10-04 02:36:51 +0000520#include "clang/Basic/OpenCLExtensions.def"
521 else {
522 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
523 return;
524 }
525}
526
David Majnemer4bb09802014-02-10 19:50:15 +0000527void Parser::HandlePragmaMSPointersToMembers() {
528 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000529 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
530 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000531 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
532 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
533 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
534}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000535
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000536void Parser::HandlePragmaMSVtorDisp() {
537 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
538 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000539 Sema::PragmaMsStackAction Action =
540 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000541 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
542 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
Denis Zobnin2290dac2016-04-29 11:27:00 +0000543 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000544}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000545
Warren Huntc3b18962014-04-08 22:30:47 +0000546void Parser::HandlePragmaMSPragma() {
547 assert(Tok.is(tok::annot_pragma_ms_pragma));
548 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000549 auto TheTokens =
550 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
551 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Warren Huntc3b18962014-04-08 22:30:47 +0000552 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
553 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000554 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000555 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000556
Warren Huntc3b18962014-04-08 22:30:47 +0000557 // Figure out which #pragma we're dealing with. The switch has no default
558 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000559 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000560 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
561 .Case("data_seg", &Parser::HandlePragmaMSSegment)
562 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
563 .Case("const_seg", &Parser::HandlePragmaMSSegment)
564 .Case("code_seg", &Parser::HandlePragmaMSSegment)
565 .Case("section", &Parser::HandlePragmaMSSection)
566 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000567
568 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
569 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
570 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000571 while (Tok.isNot(tok::eof))
572 PP.Lex(Tok);
573 PP.Lex(Tok);
574 }
575}
576
Reid Kleckner722b1df2014-07-18 00:13:16 +0000577bool Parser::HandlePragmaMSSection(StringRef PragmaName,
578 SourceLocation PragmaLocation) {
579 if (Tok.isNot(tok::l_paren)) {
580 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
581 return false;
582 }
Warren Huntc3b18962014-04-08 22:30:47 +0000583 PP.Lex(Tok); // (
584 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000585 if (Tok.isNot(tok::string_literal)) {
586 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
587 << PragmaName;
588 return false;
589 }
590 ExprResult StringResult = ParseStringLiteralExpression();
591 if (StringResult.isInvalid())
592 return false; // Already diagnosed.
593 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
594 if (SegmentName->getCharByteWidth() != 1) {
595 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
596 << PragmaName;
597 return false;
598 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000599 int SectionFlags = ASTContext::PSF_Read;
600 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000601 while (Tok.is(tok::comma)) {
602 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000603 // Ignore "long" and "short".
604 // They are undocumented, but widely used, section attributes which appear
605 // to do nothing.
606 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
607 PP.Lex(Tok); // long/short
608 continue;
609 }
610
Reid Kleckner722b1df2014-07-18 00:13:16 +0000611 if (!Tok.isAnyIdentifier()) {
612 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
613 << PragmaName;
614 return false;
615 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000616 ASTContext::PragmaSectionFlag Flag =
617 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000618 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000619 .Case("read", ASTContext::PSF_Read)
620 .Case("write", ASTContext::PSF_Write)
621 .Case("execute", ASTContext::PSF_Execute)
622 .Case("shared", ASTContext::PSF_Invalid)
623 .Case("nopage", ASTContext::PSF_Invalid)
624 .Case("nocache", ASTContext::PSF_Invalid)
625 .Case("discard", ASTContext::PSF_Invalid)
626 .Case("remove", ASTContext::PSF_Invalid)
627 .Default(ASTContext::PSF_None);
628 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
629 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000630 ? diag::warn_pragma_invalid_specific_action
631 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000632 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000633 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000634 }
635 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000636 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000637 PP.Lex(Tok); // Identifier
638 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000639 // If no section attributes are specified, the section will be marked as
640 // read/write.
641 if (SectionFlagsAreDefault)
642 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000643 if (Tok.isNot(tok::r_paren)) {
644 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
645 return false;
646 }
Warren Huntc3b18962014-04-08 22:30:47 +0000647 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000648 if (Tok.isNot(tok::eof)) {
649 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
650 << PragmaName;
651 return false;
652 }
Warren Huntc3b18962014-04-08 22:30:47 +0000653 PP.Lex(Tok); // eof
654 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000655 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000656}
657
Reid Kleckner722b1df2014-07-18 00:13:16 +0000658bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
659 SourceLocation PragmaLocation) {
660 if (Tok.isNot(tok::l_paren)) {
661 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
662 return false;
663 }
Warren Huntc3b18962014-04-08 22:30:47 +0000664 PP.Lex(Tok); // (
665 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000666 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000667 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000668 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000669 if (PushPop == "push")
670 Action = Sema::PSK_Push;
671 else if (PushPop == "pop")
672 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000673 else {
674 PP.Diag(PragmaLocation,
675 diag::warn_pragma_expected_section_push_pop_or_name)
676 << PragmaName;
677 return false;
678 }
Warren Huntc3b18962014-04-08 22:30:47 +0000679 if (Action != Sema::PSK_Reset) {
680 PP.Lex(Tok); // push | pop
681 if (Tok.is(tok::comma)) {
682 PP.Lex(Tok); // ,
683 // If we've got a comma, we either need a label or a string.
684 if (Tok.isAnyIdentifier()) {
685 SlotLabel = Tok.getIdentifierInfo()->getName();
686 PP.Lex(Tok); // identifier
687 if (Tok.is(tok::comma))
688 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000689 else if (Tok.isNot(tok::r_paren)) {
690 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
691 << PragmaName;
692 return false;
693 }
Warren Huntc3b18962014-04-08 22:30:47 +0000694 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000695 } else if (Tok.isNot(tok::r_paren)) {
696 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
697 return false;
698 }
Warren Huntc3b18962014-04-08 22:30:47 +0000699 }
700 }
701 // Grab the string literal for our section name.
702 StringLiteral *SegmentName = nullptr;
703 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000704 if (Tok.isNot(tok::string_literal)) {
705 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000706 diag::warn_pragma_expected_section_name :
707 diag::warn_pragma_expected_section_label_or_name :
708 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000709 PP.Diag(PragmaLocation, DiagID) << PragmaName;
710 return false;
711 }
712 ExprResult StringResult = ParseStringLiteralExpression();
713 if (StringResult.isInvalid())
714 return false; // Already diagnosed.
715 SegmentName = cast<StringLiteral>(StringResult.get());
716 if (SegmentName->getCharByteWidth() != 1) {
717 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
718 << PragmaName;
719 return false;
720 }
Warren Huntc3b18962014-04-08 22:30:47 +0000721 // Setting section "" has no effect
722 if (SegmentName->getLength())
723 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
724 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000725 if (Tok.isNot(tok::r_paren)) {
726 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
727 return false;
728 }
Warren Huntc3b18962014-04-08 22:30:47 +0000729 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000730 if (Tok.isNot(tok::eof)) {
731 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
732 << PragmaName;
733 return false;
734 }
Warren Huntc3b18962014-04-08 22:30:47 +0000735 PP.Lex(Tok); // eof
736 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
737 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000738 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000739}
740
Reid Kleckner1a711b12014-07-22 00:53:05 +0000741// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000742bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
743 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000744 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
745 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
746 return false;
747 }
748
Reid Kleckner1a711b12014-07-22 00:53:05 +0000749 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
750 PragmaName))
751 return false;
752
753 // Parse either the known section names or the string section name.
754 StringLiteral *SegmentName = nullptr;
755 if (Tok.isAnyIdentifier()) {
756 auto *II = Tok.getIdentifierInfo();
757 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
758 .Case("compiler", "\".CRT$XCC\"")
759 .Case("lib", "\".CRT$XCL\"")
760 .Case("user", "\".CRT$XCU\"")
761 .Default("");
762
763 if (!Section.empty()) {
764 // Pretend the user wrote the appropriate string literal here.
765 Token Toks[1];
766 Toks[0].startToken();
767 Toks[0].setKind(tok::string_literal);
768 Toks[0].setLocation(Tok.getLocation());
769 Toks[0].setLiteralData(Section.data());
770 Toks[0].setLength(Section.size());
771 SegmentName =
772 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
773 PP.Lex(Tok);
774 }
775 } else if (Tok.is(tok::string_literal)) {
776 ExprResult StringResult = ParseStringLiteralExpression();
777 if (StringResult.isInvalid())
778 return false;
779 SegmentName = cast<StringLiteral>(StringResult.get());
780 if (SegmentName->getCharByteWidth() != 1) {
781 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
782 << PragmaName;
783 return false;
784 }
785 // FIXME: Add support for the '[, func-name]' part of the pragma.
786 }
787
788 if (!SegmentName) {
789 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
790 return false;
791 }
792
793 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
794 PragmaName) ||
795 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
796 PragmaName))
797 return false;
798
799 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
800 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000801}
802
Benjamin Kramere003ca22015-10-28 13:54:16 +0000803namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000804struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000805 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000806 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000807 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000808};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000809} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000810
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000811static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
812 std::string PragmaString;
813 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
814 PragmaString = "clang loop ";
815 PragmaString += Option.getIdentifierInfo()->getName();
816 } else {
817 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
818 "Unexpected pragma name");
819 PragmaString = "unroll";
820 }
821 return PragmaString;
822}
823
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000824bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000825 assert(Tok.is(tok::annot_pragma_loop_hint));
826 PragmaLoopHintInfo *Info =
827 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
828
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000829 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
830 Hint.PragmaNameLoc = IdentifierLoc::create(
831 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000832
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000833 // It is possible that the loop hint has no option identifier, such as
834 // #pragma unroll(4).
835 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
836 ? Info->Option.getIdentifierInfo()
837 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000838 Hint.OptionLoc = IdentifierLoc::create(
839 Actions.Context, Info->Option.getLocation(), OptionInfo);
840
David Blaikie2eabcc92016-02-09 18:52:09 +0000841 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000842
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000843 // Return a valid hint if pragma unroll or nounroll were specified
844 // without an argument.
845 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
846 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000847 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000848 ConsumeToken(); // The annotation token.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000849 Hint.Range = Info->PragmaName.getLocation();
850 return true;
851 }
852
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000853 // The constant expression is always followed by an eof token, which increases
854 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000855 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000856 "PragmaLoopHintInfo::Toks must contain at least one token.");
857
858 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +0000859 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +0000860 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000861 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +0000862 if (OptionInfo) { // Pragma Unroll does not specify an option.
863 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +0000864 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000865 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
866 .Case("vectorize", true)
867 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +0000868 .Default(false) ||
869 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000870 }
871
Adam Nemet2de463e2016-06-14 12:04:26 +0000872 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000873 // Verify loop hint has an argument.
874 if (Toks[0].is(tok::eof)) {
875 ConsumeToken(); // The annotation token.
876 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +0000877 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
878 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000879 return false;
880 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000881
882 // Validate the argument.
883 if (StateOption) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000884 ConsumeToken(); // The annotation token.
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000885 SourceLocation StateLoc = Toks[0].getLocation();
886 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +0000887
888 bool Valid = StateInfo &&
889 llvm::StringSwitch<bool>(StateInfo->getName())
890 .Cases("enable", "disable", true)
891 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +0000892 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +0000893 .Default(false);
894 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000895 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +0000896 << /*FullKeyword=*/OptionUnroll
897 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000898 return false;
899 }
David Blaikie2eabcc92016-02-09 18:52:09 +0000900 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000901 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
902 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000903 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
904 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000905 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000906 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000907 ConsumeToken(); // The annotation token.
908
909 ExprResult R = ParseConstantExpression();
910
911 // Tokens following an error in an ill-formed constant expression will
912 // remain in the token stream and must be removed.
913 if (Tok.isNot(tok::eof)) {
914 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
915 << PragmaLoopHintString(Info->PragmaName, Info->Option);
916 while (Tok.isNot(tok::eof))
917 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000918 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000919
920 ConsumeToken(); // Consume the constant expression eof terminator.
921
922 if (R.isInvalid() ||
923 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
924 return false;
925
926 // Argument is a constant expression with an integer type.
927 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000928 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000929
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000930 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +0000931 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000932 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000933}
934
935// #pragma GCC visibility comes in two variants:
936// 'push' '(' [visibility] ')'
937// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000938void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
939 PragmaIntroducerKind Introducer,
940 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000941 SourceLocation VisLoc = VisTok.getLocation();
942
943 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000944 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000945
946 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
947
Eli Friedman570024a2010-08-05 06:57:20 +0000948 const IdentifierInfo *VisType;
949 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +0000950 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +0000951 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000952 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000953 if (Tok.isNot(tok::l_paren)) {
954 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
955 << "visibility";
956 return;
957 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000958 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000959 VisType = Tok.getIdentifierInfo();
960 if (!VisType) {
961 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
962 << "visibility";
963 return;
964 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000965 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000966 if (Tok.isNot(tok::r_paren)) {
967 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
968 << "visibility";
969 return;
970 }
971 } else {
972 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
973 << "visibility";
974 return;
975 }
David Majnemera8f2f1d2015-03-19 00:10:23 +0000976 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000977 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000978 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000979 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
980 << "visibility";
981 return;
982 }
983
David Blaikie2eabcc92016-02-09 18:52:09 +0000984 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +0000985 Toks[0].startToken();
986 Toks[0].setKind(tok::annot_pragma_vis);
987 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +0000988 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +0000989 Toks[0].setAnnotationValue(
990 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +0000991 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000992}
993
Daniel Dunbar921b9682008-10-04 19:21:03 +0000994// #pragma pack(...) comes in the following delicious flavors:
995// pack '(' [integer] ')'
996// pack '(' 'show' ')'
997// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000998void PragmaPackHandler::HandlePragma(Preprocessor &PP,
999 PragmaIntroducerKind Introducer,
1000 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001001 SourceLocation PackLoc = PackTok.getLocation();
1002
1003 Token Tok;
1004 PP.Lex(Tok);
1005 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001006 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001007 return;
1008 }
1009
Denis Zobnin10c4f452016-04-29 18:17:40 +00001010 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1011 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001012 Token Alignment;
1013 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001014 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001015 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001016 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001017
1018 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001019
1020 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1021 // the push/pop stack.
1022 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001023 Action =
1024 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001025 } else if (Tok.is(tok::identifier)) {
1026 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001027 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001028 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001029 PP.Lex(Tok);
1030 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001031 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001032 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001033 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001034 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001035 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001036 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001037 return;
Mike Stump11289f42009-09-09 15:08:12 +00001038 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001039 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001040
Daniel Dunbar921b9682008-10-04 19:21:03 +00001041 if (Tok.is(tok::comma)) {
1042 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001043
Daniel Dunbar921b9682008-10-04 19:21:03 +00001044 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001045 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001046 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001047
1048 PP.Lex(Tok);
1049 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001050 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001051 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001052
Daniel Dunbar921b9682008-10-04 19:21:03 +00001053 if (Tok.is(tok::comma)) {
1054 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001055
Daniel Dunbar921b9682008-10-04 19:21:03 +00001056 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001057 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001058 return;
1059 }
Mike Stump11289f42009-09-09 15:08:12 +00001060
Denis Zobnin10c4f452016-04-29 18:17:40 +00001061 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001062 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001063
1064 PP.Lex(Tok);
1065 }
1066 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001067 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001068 return;
1069 }
1070 }
1071 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001072 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001073 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1074 // the push/pop stack.
1075 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001076 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001077 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001078
1079 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001080 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001081 return;
1082 }
1083
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001084 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001085 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001086 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001087 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1088 return;
1089 }
1090
David Blaikie2eabcc92016-02-09 18:52:09 +00001091 PragmaPackInfo *Info =
1092 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001093 Info->Action = Action;
1094 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001095 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001096
David Blaikie2eabcc92016-02-09 18:52:09 +00001097 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1098 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001099 Toks[0].startToken();
1100 Toks[0].setKind(tok::annot_pragma_pack);
1101 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001102 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001103 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001104 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001105}
1106
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001107// #pragma ms_struct on
1108// #pragma ms_struct off
1109void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1110 PragmaIntroducerKind Introducer,
1111 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001112 PragmaMSStructKind Kind = PMSST_OFF;
1113
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001114 Token Tok;
1115 PP.Lex(Tok);
1116 if (Tok.isNot(tok::identifier)) {
1117 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1118 return;
1119 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001120 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001121 const IdentifierInfo *II = Tok.getIdentifierInfo();
1122 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001123 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001124 PP.Lex(Tok);
1125 }
1126 else if (II->isStr("off") || II->isStr("reset"))
1127 PP.Lex(Tok);
1128 else {
1129 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1130 return;
1131 }
1132
1133 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001134 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1135 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001136 return;
1137 }
Eli Friedman68be1642012-10-04 02:36:51 +00001138
David Blaikie2eabcc92016-02-09 18:52:09 +00001139 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1140 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001141 Toks[0].startToken();
1142 Toks[0].setKind(tok::annot_pragma_msstruct);
1143 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001144 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001145 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1146 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001147 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001148}
1149
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001150// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1151// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001152static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001153 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001154 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001155
1156 if (IsOptions) {
1157 PP.Lex(Tok);
1158 if (Tok.isNot(tok::identifier) ||
1159 !Tok.getIdentifierInfo()->isStr("align")) {
1160 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1161 return;
1162 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001163 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001164
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001165 PP.Lex(Tok);
1166 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001167 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1168 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001169 return;
1170 }
1171
1172 PP.Lex(Tok);
1173 if (Tok.isNot(tok::identifier)) {
1174 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001175 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001176 return;
1177 }
1178
John McCallfaf5fb42010-08-26 23:41:50 +00001179 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001180 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001181 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001182 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001183 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001184 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001185 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001186 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001187 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001188 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001189 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001190 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001191 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001192 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001193 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001194 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1195 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001196 return;
1197 }
1198
David Majnemera8f2f1d2015-03-19 00:10:23 +00001199 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001200 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001201 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001202 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001203 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001204 return;
1205 }
1206
David Blaikie2eabcc92016-02-09 18:52:09 +00001207 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1208 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001209 Toks[0].startToken();
1210 Toks[0].setKind(tok::annot_pragma_align);
1211 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001212 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001213 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1214 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001215 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001216}
1217
Douglas Gregorc7d65762010-09-09 22:45:38 +00001218void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1219 PragmaIntroducerKind Introducer,
1220 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001221 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001222}
1223
Douglas Gregorc7d65762010-09-09 22:45:38 +00001224void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1225 PragmaIntroducerKind Introducer,
1226 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001227 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001228}
1229
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001230// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001231void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1232 PragmaIntroducerKind Introducer,
1233 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001234 // FIXME: Should we be expanding macros here? My guess is no.
1235 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001236
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001237 // Lex the left '('.
1238 Token Tok;
1239 PP.Lex(Tok);
1240 if (Tok.isNot(tok::l_paren)) {
1241 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1242 return;
1243 }
Mike Stump11289f42009-09-09 15:08:12 +00001244
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001245 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001246 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001247 SourceLocation RParenLoc;
1248 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001249
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001250 while (true) {
1251 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001252
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001253 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001254 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001255 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001256 LexID = false;
1257 continue;
1258 }
1259
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001260 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001261 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1262 return;
1263 }
Mike Stump11289f42009-09-09 15:08:12 +00001264
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001265 // We are execting a ')' or a ','.
1266 if (Tok.is(tok::comma)) {
1267 LexID = true;
1268 continue;
1269 }
Mike Stump11289f42009-09-09 15:08:12 +00001270
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001271 if (Tok.is(tok::r_paren)) {
1272 RParenLoc = Tok.getLocation();
1273 break;
1274 }
Mike Stump11289f42009-09-09 15:08:12 +00001275
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001276 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001277 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001278 return;
1279 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001280
1281 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001282 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001283 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1284 "unused";
1285 return;
1286 }
1287
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001288 // Verify that we have a location for the right parenthesis.
1289 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001290 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001291
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001292 // For each identifier token, insert into the token stream a
1293 // annot_pragma_unused token followed by the identifier token.
1294 // This allows us to cache a "#pragma unused" that occurs inside an inline
1295 // C++ member function.
1296
David Blaikie2eabcc92016-02-09 18:52:09 +00001297 MutableArrayRef<Token> Toks(
1298 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1299 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001300 for (unsigned i=0; i != Identifiers.size(); i++) {
1301 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1302 pragmaUnusedTok.startToken();
1303 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1304 pragmaUnusedTok.setLocation(UnusedLoc);
1305 idTok = Identifiers[i];
1306 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001307 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001308}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001309
1310// #pragma weak identifier
1311// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001312void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1313 PragmaIntroducerKind Introducer,
1314 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001315 SourceLocation WeakLoc = WeakTok.getLocation();
1316
1317 Token Tok;
1318 PP.Lex(Tok);
1319 if (Tok.isNot(tok::identifier)) {
1320 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1321 return;
1322 }
1323
Eli Friedman68be1642012-10-04 02:36:51 +00001324 Token WeakName = Tok;
1325 bool HasAlias = false;
1326 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001327
1328 PP.Lex(Tok);
1329 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001330 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001331 PP.Lex(Tok);
1332 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001333 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001334 << "weak";
1335 return;
1336 }
Eli Friedman68be1642012-10-04 02:36:51 +00001337 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001338 PP.Lex(Tok);
1339 }
1340
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001341 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001342 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1343 return;
1344 }
1345
Eli Friedman68be1642012-10-04 02:36:51 +00001346 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001347 MutableArrayRef<Token> Toks(
1348 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001349 Token &pragmaUnusedTok = Toks[0];
1350 pragmaUnusedTok.startToken();
1351 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1352 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001353 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001354 Toks[1] = WeakName;
1355 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001356 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001357 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001358 MutableArrayRef<Token> Toks(
1359 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001360 Token &pragmaUnusedTok = Toks[0];
1361 pragmaUnusedTok.startToken();
1362 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1363 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001364 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001365 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001366 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001367 }
1368}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001369
David Chisnall0867d9c2012-02-18 16:12:34 +00001370// #pragma redefine_extname identifier identifier
1371void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1372 PragmaIntroducerKind Introducer,
1373 Token &RedefToken) {
1374 SourceLocation RedefLoc = RedefToken.getLocation();
1375
1376 Token Tok;
1377 PP.Lex(Tok);
1378 if (Tok.isNot(tok::identifier)) {
1379 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1380 "redefine_extname";
1381 return;
1382 }
1383
Eli Friedman68be1642012-10-04 02:36:51 +00001384 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001385 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001386
David Chisnall0867d9c2012-02-18 16:12:34 +00001387 if (Tok.isNot(tok::identifier)) {
1388 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1389 << "redefine_extname";
1390 return;
1391 }
Eli Friedman68be1642012-10-04 02:36:51 +00001392
1393 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001394 PP.Lex(Tok);
1395
1396 if (Tok.isNot(tok::eod)) {
1397 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1398 "redefine_extname";
1399 return;
1400 }
1401
David Blaikie2eabcc92016-02-09 18:52:09 +00001402 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1403 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001404 Token &pragmaRedefTok = Toks[0];
1405 pragmaRedefTok.startToken();
1406 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1407 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001408 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001409 Toks[1] = RedefName;
1410 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001411 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00001412}
1413
1414
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001415void
1416PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1417 PragmaIntroducerKind Introducer,
1418 Token &Tok) {
1419 tok::OnOffSwitch OOS;
1420 if (PP.LexOnOffSwitch(OOS))
1421 return;
1422
David Blaikie2eabcc92016-02-09 18:52:09 +00001423 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1424 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001425 Toks[0].startToken();
1426 Toks[0].setKind(tok::annot_pragma_fp_contract);
1427 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001428 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001429 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1430 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001431 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001432}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001433
1434void
1435PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1436 PragmaIntroducerKind Introducer,
1437 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001438 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001439 if (Tok.isNot(tok::identifier)) {
1440 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1441 "OPENCL";
1442 return;
1443 }
1444 IdentifierInfo *ename = Tok.getIdentifierInfo();
1445 SourceLocation NameLoc = Tok.getLocation();
1446
1447 PP.Lex(Tok);
1448 if (Tok.isNot(tok::colon)) {
1449 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1450 return;
1451 }
1452
1453 PP.Lex(Tok);
1454 if (Tok.isNot(tok::identifier)) {
1455 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1456 return;
1457 }
1458 IdentifierInfo *op = Tok.getIdentifierInfo();
1459
1460 unsigned state;
1461 if (op->isStr("enable")) {
1462 state = 1;
1463 } else if (op->isStr("disable")) {
1464 state = 0;
1465 } else {
1466 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1467 return;
1468 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001469 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001470
Eli Friedman68be1642012-10-04 02:36:51 +00001471 PP.Lex(Tok);
1472 if (Tok.isNot(tok::eod)) {
1473 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1474 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001475 return;
1476 }
Eli Friedman68be1642012-10-04 02:36:51 +00001477
1478 OpenCLExtData data(ename, state);
David Blaikie2eabcc92016-02-09 18:52:09 +00001479 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1480 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001481 Toks[0].startToken();
1482 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1483 Toks[0].setLocation(NameLoc);
1484 Toks[0].setAnnotationValue(data.getOpaqueValue());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001485 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00001486 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001487
1488 if (PP.getPPCallbacks())
1489 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1490 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001491}
1492
Alexey Bataeva769e072013-03-22 06:34:35 +00001493/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1494///
1495void
1496PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1497 PragmaIntroducerKind Introducer,
1498 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00001499 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1500 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00001501 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00001502 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1503 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00001504 }
1505 PP.DiscardUntilEndOfDirective();
1506}
1507
1508/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1509///
1510void
1511PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1512 PragmaIntroducerKind Introducer,
1513 Token &FirstTok) {
1514 SmallVector<Token, 16> Pragma;
1515 Token Tok;
1516 Tok.startToken();
1517 Tok.setKind(tok::annot_pragma_openmp);
1518 Tok.setLocation(FirstTok.getLocation());
1519
1520 while (Tok.isNot(tok::eod)) {
1521 Pragma.push_back(Tok);
1522 PP.Lex(Tok);
1523 }
1524 SourceLocation EodLoc = Tok.getLocation();
1525 Tok.startToken();
1526 Tok.setKind(tok::annot_pragma_openmp_end);
1527 Tok.setLocation(EodLoc);
1528 Pragma.push_back(Tok);
1529
David Blaikie2eabcc92016-02-09 18:52:09 +00001530 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
1531 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
1532 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
1533 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00001534}
Reid Kleckner002562a2013-05-06 21:02:12 +00001535
David Majnemer4bb09802014-02-10 19:50:15 +00001536/// \brief Handle '#pragma pointers_to_members'
1537// The grammar for this pragma is as follows:
1538//
1539// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1540//
1541// #pragma pointers_to_members '(' 'best_case' ')'
1542// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1543// #pragma pointers_to_members '(' inheritance-model ')'
1544void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1545 PragmaIntroducerKind Introducer,
1546 Token &Tok) {
1547 SourceLocation PointersToMembersLoc = Tok.getLocation();
1548 PP.Lex(Tok);
1549 if (Tok.isNot(tok::l_paren)) {
1550 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1551 << "pointers_to_members";
1552 return;
1553 }
1554 PP.Lex(Tok);
1555 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1556 if (!Arg) {
1557 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1558 << "pointers_to_members";
1559 return;
1560 }
1561 PP.Lex(Tok);
1562
David Majnemer86c318f2014-02-11 21:05:00 +00001563 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001564 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001565 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001566 } else {
1567 if (Arg->isStr("full_generality")) {
1568 if (Tok.is(tok::comma)) {
1569 PP.Lex(Tok);
1570
1571 Arg = Tok.getIdentifierInfo();
1572 if (!Arg) {
1573 PP.Diag(Tok.getLocation(),
1574 diag::err_pragma_pointers_to_members_unknown_kind)
1575 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1576 return;
1577 }
1578 PP.Lex(Tok);
1579 } else if (Tok.is(tok::r_paren)) {
1580 // #pragma pointers_to_members(full_generality) implicitly specifies
1581 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00001582 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00001583 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001584 } else {
1585 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1586 << "full_generality";
1587 return;
1588 }
1589 }
1590
1591 if (Arg) {
1592 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001593 RepresentationMethod =
1594 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001595 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001596 RepresentationMethod =
1597 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001598 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001599 RepresentationMethod =
1600 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001601 } else {
1602 PP.Diag(Tok.getLocation(),
1603 diag::err_pragma_pointers_to_members_unknown_kind)
1604 << Arg << /*HasPointerDeclaration*/ 1;
1605 return;
1606 }
1607 }
1608 }
1609
1610 if (Tok.isNot(tok::r_paren)) {
1611 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1612 << (Arg ? Arg->getName() : "full_generality");
1613 return;
1614 }
1615
David Majnemera8f2f1d2015-03-19 00:10:23 +00001616 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00001617 PP.Lex(Tok);
1618 if (Tok.isNot(tok::eod)) {
1619 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1620 << "pointers_to_members";
1621 return;
1622 }
1623
1624 Token AnnotTok;
1625 AnnotTok.startToken();
1626 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1627 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001628 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00001629 AnnotTok.setAnnotationValue(
1630 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1631 PP.EnterToken(AnnotTok);
1632}
1633
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001634/// \brief Handle '#pragma vtordisp'
1635// The grammar for this pragma is as follows:
1636//
1637// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1638//
1639// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1640// #pragma vtordisp '(' 'pop' ')'
1641// #pragma vtordisp '(' ')'
1642void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1643 PragmaIntroducerKind Introducer,
1644 Token &Tok) {
1645 SourceLocation VtorDispLoc = Tok.getLocation();
1646 PP.Lex(Tok);
1647 if (Tok.isNot(tok::l_paren)) {
1648 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1649 return;
1650 }
1651 PP.Lex(Tok);
1652
Denis Zobnin2290dac2016-04-29 11:27:00 +00001653 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001654 const IdentifierInfo *II = Tok.getIdentifierInfo();
1655 if (II) {
1656 if (II->isStr("push")) {
1657 // #pragma vtordisp(push, mode)
1658 PP.Lex(Tok);
1659 if (Tok.isNot(tok::comma)) {
1660 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1661 return;
1662 }
1663 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00001664 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001665 // not push, could be on/off
1666 } else if (II->isStr("pop")) {
1667 // #pragma vtordisp(pop)
1668 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00001669 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001670 }
1671 // not push or pop, could be on/off
1672 } else {
1673 if (Tok.is(tok::r_paren)) {
1674 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00001675 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001676 }
1677 }
1678
1679
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001680 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00001681 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001682 const IdentifierInfo *II = Tok.getIdentifierInfo();
1683 if (II && II->isStr("off")) {
1684 PP.Lex(Tok);
1685 Value = 0;
1686 } else if (II && II->isStr("on")) {
1687 PP.Lex(Tok);
1688 Value = 1;
1689 } else if (Tok.is(tok::numeric_constant) &&
1690 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1691 if (Value > 2) {
1692 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1693 << 0 << 2 << "vtordisp";
1694 return;
1695 }
1696 } else {
1697 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1698 << "vtordisp";
1699 return;
1700 }
1701 }
1702
1703 // Finish the pragma: ')' $
1704 if (Tok.isNot(tok::r_paren)) {
1705 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1706 return;
1707 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001708 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001709 PP.Lex(Tok);
1710 if (Tok.isNot(tok::eod)) {
1711 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1712 << "vtordisp";
1713 return;
1714 }
1715
1716 // Enter the annotation.
1717 Token AnnotTok;
1718 AnnotTok.startToken();
1719 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1720 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001721 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001722 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00001723 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001724 PP.EnterToken(AnnotTok);
1725}
1726
Warren Huntc3b18962014-04-08 22:30:47 +00001727/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1728/// an annotation token.
1729void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1730 PragmaIntroducerKind Introducer,
1731 Token &Tok) {
1732 Token EoF, AnnotTok;
1733 EoF.startToken();
1734 EoF.setKind(tok::eof);
1735 AnnotTok.startToken();
1736 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1737 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001738 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00001739 SmallVector<Token, 8> TokenVector;
1740 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00001741 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00001742 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001743 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
1744 }
Warren Huntc3b18962014-04-08 22:30:47 +00001745 // Add a sentinal EoF token to the end of the list.
1746 TokenVector.push_back(EoF);
1747 // We must allocate this array with new because EnterTokenStream is going to
1748 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00001749 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
1750 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00001751 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00001752 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
1753 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00001754 AnnotTok.setAnnotationValue(Value);
1755 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001756}
1757
Aaron Ballman5d041be2013-06-04 02:07:14 +00001758/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1759///
1760/// The syntax is:
1761/// \code
1762/// #pragma detect_mismatch("name", "value")
1763/// \endcode
1764/// Where 'name' and 'value' are quoted strings. The values are embedded in
1765/// the object file and passed along to the linker. If the linker detects a
1766/// mismatch in the object file's values for the given name, a LNK2038 error
1767/// is emitted. See MSDN for more details.
1768void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1769 PragmaIntroducerKind Introducer,
1770 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00001771 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00001772 PP.Lex(Tok);
1773 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00001774 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001775 return;
1776 }
1777
1778 // Read the name to embed, which must be a string literal.
1779 std::string NameString;
1780 if (!PP.LexStringLiteral(Tok, NameString,
1781 "pragma detect_mismatch",
1782 /*MacroExpansion=*/true))
1783 return;
1784
1785 // Read the comma followed by a second string literal.
1786 std::string ValueString;
1787 if (Tok.isNot(tok::comma)) {
1788 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1789 return;
1790 }
1791
1792 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1793 /*MacroExpansion=*/true))
1794 return;
1795
1796 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001797 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001798 return;
1799 }
1800 PP.Lex(Tok); // Eat the r_paren.
1801
1802 if (Tok.isNot(tok::eod)) {
1803 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1804 return;
1805 }
1806
Reid Kleckner71966c92014-02-20 23:37:45 +00001807 // If the pragma is lexically sound, notify any interested PPCallbacks.
1808 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00001809 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00001810 ValueString);
1811
Nico Webercbbaeb12016-03-02 19:28:54 +00001812 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00001813}
1814
Reid Kleckner002562a2013-05-06 21:02:12 +00001815/// \brief Handle the microsoft \#pragma comment extension.
1816///
1817/// The syntax is:
1818/// \code
1819/// #pragma comment(linker, "foo")
1820/// \endcode
1821/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1822/// "foo" is a string, which is fully macro expanded, and permits string
1823/// concatenation, embedded escape characters etc. See MSDN for more details.
1824void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1825 PragmaIntroducerKind Introducer,
1826 Token &Tok) {
1827 SourceLocation CommentLoc = Tok.getLocation();
1828 PP.Lex(Tok);
1829 if (Tok.isNot(tok::l_paren)) {
1830 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1831 return;
1832 }
1833
1834 // Read the identifier.
1835 PP.Lex(Tok);
1836 if (Tok.isNot(tok::identifier)) {
1837 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1838 return;
1839 }
1840
1841 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001842 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00001843 PragmaMSCommentKind Kind =
1844 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
1845 .Case("linker", PCK_Linker)
1846 .Case("lib", PCK_Lib)
1847 .Case("compiler", PCK_Compiler)
1848 .Case("exestr", PCK_ExeStr)
1849 .Case("user", PCK_User)
1850 .Default(PCK_Unknown);
1851 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001852 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1853 return;
1854 }
1855
Yunzhong Gao99efc032015-03-23 20:41:42 +00001856 // On PS4, issue a warning about any pragma comments other than
1857 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00001858 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00001859 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
1860 << II->getName();
1861 return;
1862 }
1863
Reid Kleckner002562a2013-05-06 21:02:12 +00001864 // Read the optional string if present.
1865 PP.Lex(Tok);
1866 std::string ArgumentString;
1867 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1868 "pragma comment",
1869 /*MacroExpansion=*/true))
1870 return;
1871
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001872 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001873 // FIXME: If the kind is "compiler" warn if the string is present (it is
1874 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001875 // The MSDN docs say that "lib" and "linker" require a string and have a short
1876 // whitelist of linker options they support, but in practice MSVC doesn't
1877 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001878
1879 if (Tok.isNot(tok::r_paren)) {
1880 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1881 return;
1882 }
1883 PP.Lex(Tok); // eat the r_paren.
1884
1885 if (Tok.isNot(tok::eod)) {
1886 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1887 return;
1888 }
1889
Reid Kleckner71966c92014-02-20 23:37:45 +00001890 // If the pragma is lexically sound, notify any interested PPCallbacks.
1891 if (PP.getPPCallbacks())
1892 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1893
Nico Weber66220292016-03-02 17:28:48 +00001894 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001895}
Dario Domizioli13a0a382014-05-23 12:13:25 +00001896
1897// #pragma clang optimize off
1898// #pragma clang optimize on
1899void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1900 PragmaIntroducerKind Introducer,
1901 Token &FirstToken) {
1902 Token Tok;
1903 PP.Lex(Tok);
1904 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001905 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00001906 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00001907 return;
1908 }
1909 if (Tok.isNot(tok::identifier)) {
1910 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1911 << PP.getSpelling(Tok);
1912 return;
1913 }
1914 const IdentifierInfo *II = Tok.getIdentifierInfo();
1915 // The only accepted values are 'on' or 'off'.
1916 bool IsOn = false;
1917 if (II->isStr("on")) {
1918 IsOn = true;
1919 } else if (!II->isStr("off")) {
1920 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1921 << PP.getSpelling(Tok);
1922 return;
1923 }
1924 PP.Lex(Tok);
1925
1926 if (Tok.isNot(tok::eod)) {
1927 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1928 << PP.getSpelling(Tok);
1929 return;
1930 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001931
1932 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1933}
1934
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001935/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001936static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1937 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001938 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001939 SmallVector<Token, 1> ValueList;
1940 int OpenParens = ValueInParens ? 1 : 0;
1941 // Read constant expression.
1942 while (Tok.isNot(tok::eod)) {
1943 if (Tok.is(tok::l_paren))
1944 OpenParens++;
1945 else if (Tok.is(tok::r_paren)) {
1946 OpenParens--;
1947 if (OpenParens == 0 && ValueInParens)
1948 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001949 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001950
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001951 ValueList.push_back(Tok);
1952 PP.Lex(Tok);
1953 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001954
1955 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001956 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001957 if (Tok.isNot(tok::r_paren)) {
1958 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1959 return true;
1960 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001961 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001962 }
1963
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001964 Token EOFTok;
1965 EOFTok.startToken();
1966 EOFTok.setKind(tok::eof);
1967 EOFTok.setLocation(Tok.getLocation());
1968 ValueList.push_back(EOFTok); // Terminates expression for parsing.
1969
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00001970 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001971
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001972 Info.PragmaName = PragmaName;
1973 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001974 return false;
1975}
1976
Eli Bendersky06a40422014-06-06 20:31:48 +00001977/// \brief Handle the \#pragma clang loop directive.
1978/// #pragma clang 'loop' loop-hints
1979///
1980/// loop-hints:
1981/// loop-hint loop-hints[opt]
1982///
1983/// loop-hint:
1984/// 'vectorize' '(' loop-hint-keyword ')'
1985/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00001986/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001987/// 'vectorize_width' '(' loop-hint-value ')'
1988/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00001989/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001990///
1991/// loop-hint-keyword:
1992/// 'enable'
1993/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00001994/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00001995///
Mark Heffernan450c2382014-07-23 17:31:31 +00001996/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00001997/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00001998/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00001999/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002000///
Eli Bendersky06a40422014-06-06 20:31:48 +00002001/// loop-hint-value:
2002/// constant-expression
2003///
2004/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2005/// try vectorizing the instructions of the loop it precedes. Specifying
2006/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2007/// interleaving multiple iterations of the loop it precedes. The width of the
2008/// vector instructions is specified by vectorize_width() and the number of
2009/// interleaved loop iterations is specified by interleave_count(). Specifying a
2010/// value of 1 effectively disables vectorization/interleaving, even if it is
2011/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2012/// only works on inner loops.
2013///
Eli Bendersky86483b32014-06-11 17:56:26 +00002014/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002015/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2016/// completely if the trip count is known at compile time and unroll partially
2017/// if the trip count is not known. Specifying unroll(full) is similar to
2018/// unroll(enable) but will unroll the loop only if the trip count is known at
2019/// compile time. Specifying unroll(disable) disables unrolling for the
2020/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2021/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002022void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2023 PragmaIntroducerKind Introducer,
2024 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002025 // Incoming token is "loop" from "#pragma clang loop".
2026 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002027 SmallVector<Token, 1> TokenList;
2028
2029 // Lex the optimization option and verify it is an identifier.
2030 PP.Lex(Tok);
2031 if (Tok.isNot(tok::identifier)) {
2032 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2033 << /*MissingOption=*/true << "";
2034 return;
2035 }
2036
2037 while (Tok.is(tok::identifier)) {
2038 Token Option = Tok;
2039 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2040
Eli Bendersky86483b32014-06-11 17:56:26 +00002041 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002042 .Case("vectorize", true)
2043 .Case("interleave", true)
2044 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002045 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002046 .Case("vectorize_width", true)
2047 .Case("interleave_count", true)
2048 .Case("unroll_count", true)
2049 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002050 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002051 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2052 << /*MissingOption=*/false << OptionInfo;
2053 return;
2054 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002055 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002056
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002057 // Read '('
2058 if (Tok.isNot(tok::l_paren)) {
2059 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002060 return;
2061 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002062 PP.Lex(Tok);
2063
2064 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2065 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2066 *Info))
2067 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002068
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002069 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002070 Token LoopHintTok;
2071 LoopHintTok.startToken();
2072 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002073 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002074 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002075 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2076 TokenList.push_back(LoopHintTok);
2077 }
2078
2079 if (Tok.isNot(tok::eod)) {
2080 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2081 << "clang loop";
2082 return;
2083 }
2084
David Blaikie2eabcc92016-02-09 18:52:09 +00002085 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2086 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002087
David Blaikie2eabcc92016-02-09 18:52:09 +00002088 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2089 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002090}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002091
2092/// \brief Handle the loop unroll optimization pragmas.
2093/// #pragma unroll
2094/// #pragma unroll unroll-hint-value
2095/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002096/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002097///
2098/// unroll-hint-value:
2099/// constant-expression
2100///
Mark Heffernanc888e412014-07-24 18:09:38 +00002101/// Loop unrolling hints can be specified with '#pragma unroll' or
2102/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2103/// contained in parentheses. With no argument the directive instructs llvm to
2104/// try to unroll the loop completely. A positive integer argument can be
2105/// specified to indicate the number of times the loop should be unrolled. To
2106/// maximize compatibility with other compilers the unroll count argument can be
2107/// specified with or without parentheses. Specifying, '#pragma nounroll'
2108/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002109void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2110 PragmaIntroducerKind Introducer,
2111 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002112 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2113 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002114 Token PragmaName = Tok;
2115 PP.Lex(Tok);
2116 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2117 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002118 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002119 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002120 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002121 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2122 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2123 << "nounroll";
2124 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002125 } else {
2126 // Unroll pragma with an argument: "#pragma unroll N" or
2127 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002128 // Read '(' if it exists.
2129 bool ValueInParens = Tok.is(tok::l_paren);
2130 if (ValueInParens)
2131 PP.Lex(Tok);
2132
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002133 Token Option;
2134 Option.startToken();
2135 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002136 return;
2137
2138 // In CUDA, the argument to '#pragma unroll' should not be contained in
2139 // parentheses.
2140 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002141 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002142 diag::warn_pragma_unroll_cuda_value_in_parens);
2143
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002144 if (Tok.isNot(tok::eod)) {
2145 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2146 << "unroll";
2147 return;
2148 }
2149 }
2150
2151 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002152 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002153 TokenArray[0].startToken();
2154 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2155 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002156 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002157 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002158 PP.EnterTokenStream(std::move(TokenArray), 1,
2159 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002160}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002161
2162/// \brief Handle the Microsoft \#pragma intrinsic extension.
2163///
2164/// The syntax is:
2165/// \code
2166/// #pragma intrinsic(memset)
2167/// #pragma intrinsic(strlen, memcpy)
2168/// \endcode
2169///
2170/// Pragma intrisic tells the compiler to use a builtin version of the
2171/// function. Clang does it anyway, so the pragma doesn't really do anything.
2172/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2173/// isn't an intrinsic in clang and suggest to include intrin.h.
2174void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2175 PragmaIntroducerKind Introducer,
2176 Token &Tok) {
2177 PP.Lex(Tok);
2178
2179 if (Tok.isNot(tok::l_paren)) {
2180 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2181 << "intrinsic";
2182 return;
2183 }
2184 PP.Lex(Tok);
2185
2186 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2187
2188 while (Tok.is(tok::identifier)) {
2189 IdentifierInfo *II = Tok.getIdentifierInfo();
2190 if (!II->getBuiltinID())
2191 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2192 << II << SuggestIntrinH;
2193
2194 PP.Lex(Tok);
2195 if (Tok.isNot(tok::comma))
2196 break;
2197 PP.Lex(Tok);
2198 }
2199
2200 if (Tok.isNot(tok::r_paren)) {
2201 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2202 << "intrinsic";
2203 return;
2204 }
2205 PP.Lex(Tok);
2206
2207 if (Tok.isNot(tok::eod))
2208 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2209 << "intrinsic";
2210}
Justin Lebar67a78a62016-10-08 22:15:58 +00002211void PragmaForceCUDAHostDeviceHandler::HandlePragma(
2212 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
2213 Token FirstTok = Tok;
2214
2215 PP.Lex(Tok);
2216 IdentifierInfo *Info = Tok.getIdentifierInfo();
2217 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
2218 PP.Diag(FirstTok.getLocation(),
2219 diag::warn_pragma_force_cuda_host_device_bad_arg);
2220 return;
2221 }
2222
2223 if (Info->isStr("begin"))
2224 Actions.PushForceCUDAHostDevice();
2225 else if (!Actions.PopForceCUDAHostDevice())
2226 PP.Diag(FirstTok.getLocation(),
2227 diag::err_pragma_cannot_end_force_cuda_host_device);
2228
2229 PP.Lex(Tok);
2230 if (!Tok.is(tok::eod))
2231 PP.Diag(FirstTok.getLocation(),
2232 diag::warn_pragma_force_cuda_host_device_bad_arg);
2233}