blob: 262743756a6b8d3bf434dedd2c6de6dda1d42699 [file] [log] [blame]
Daniel Dunbar921b9682008-10-04 19:21:03 +00001//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the language specific #pragma handlers.
11//
12//===----------------------------------------------------------------------===//
13
Hans Wennborg899ded92014-10-16 20:52:46 +000014#include "clang/AST/ASTContext.h"
Nico Weber66220292016-03-02 17:28:48 +000015#include "clang/Basic/PragmaKinds.h"
David Majnemerad2986e2014-08-14 06:35:08 +000016#include "clang/Basic/TargetInfo.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000017#include "clang/Lex/Preprocessor.h"
18#include "clang/Parse/ParseDiagnostic.h"
19#include "clang/Parse/Parser.h"
Vassil Vassilev11ad3392017-03-23 15:11:07 +000020#include "clang/Parse/RAIIObjectsForParser.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000021#include "clang/Sema/LoopHint.h"
22#include "clang/Sema/Scope.h"
23#include "llvm/ADT/StringSwitch.h"
24using namespace clang;
Daniel Dunbar921b9682008-10-04 19:21:03 +000025
Reid Kleckner5b086462014-02-20 22:52:09 +000026namespace {
27
28struct PragmaAlignHandler : public PragmaHandler {
29 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000030 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
31 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000032};
33
34struct PragmaGCCVisibilityHandler : public PragmaHandler {
35 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000036 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
37 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000038};
39
40struct PragmaOptionsHandler : public PragmaHandler {
41 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000042 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
43 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000044};
45
46struct PragmaPackHandler : public PragmaHandler {
47 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000048 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
49 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000050};
51
Javed Absar2a67c9e2017-06-05 10:11:57 +000052struct PragmaClangSectionHandler : public PragmaHandler {
53 explicit PragmaClangSectionHandler(Sema &S)
54 : PragmaHandler("section"), Actions(S) {}
55 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
56 Token &FirstToken) override;
57private:
58 Sema &Actions;
59};
60
Reid Kleckner5b086462014-02-20 22:52:09 +000061struct PragmaMSStructHandler : public PragmaHandler {
62 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000063 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
64 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000065};
66
67struct PragmaUnusedHandler : public PragmaHandler {
68 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000069 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
70 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000071};
72
73struct PragmaWeakHandler : public PragmaHandler {
74 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000075 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
76 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000077};
78
79struct PragmaRedefineExtnameHandler : public PragmaHandler {
80 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000081 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
82 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000083};
84
85struct PragmaOpenCLExtensionHandler : public PragmaHandler {
86 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000087 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
88 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000089};
90
91
92struct PragmaFPContractHandler : public PragmaHandler {
93 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000094 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
95 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000096};
97
Adam Nemet60d32642017-04-04 21:18:36 +000098struct PragmaFPHandler : public PragmaHandler {
99 PragmaFPHandler() : PragmaHandler("fp") {}
100 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
101 Token &FirstToken) override;
102};
103
Reid Kleckner5b086462014-02-20 22:52:09 +0000104struct PragmaNoOpenMPHandler : public PragmaHandler {
105 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +0000106 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
107 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000108};
109
110struct PragmaOpenMPHandler : public PragmaHandler {
111 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +0000112 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
113 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000114};
115
116/// PragmaCommentHandler - "\#pragma comment ...".
117struct PragmaCommentHandler : public PragmaHandler {
118 PragmaCommentHandler(Sema &Actions)
119 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000120 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
121 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000122private:
123 Sema &Actions;
124};
125
126struct PragmaDetectMismatchHandler : public PragmaHandler {
127 PragmaDetectMismatchHandler(Sema &Actions)
128 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000129 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
130 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000131private:
132 Sema &Actions;
133};
134
135struct PragmaMSPointersToMembers : public PragmaHandler {
136 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000137 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
138 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000139};
140
141struct PragmaMSVtorDisp : public PragmaHandler {
142 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000143 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
144 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000145};
146
Warren Huntc3b18962014-04-08 22:30:47 +0000147struct PragmaMSPragma : public PragmaHandler {
148 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000149 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
150 Token &FirstToken) override;
151};
152
Dario Domizioli13a0a382014-05-23 12:13:25 +0000153/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
154struct PragmaOptimizeHandler : public PragmaHandler {
155 PragmaOptimizeHandler(Sema &S)
156 : PragmaHandler("optimize"), Actions(S) {}
157 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
158 Token &FirstToken) override;
159private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000160 Sema &Actions;
161};
162
163struct PragmaLoopHintHandler : public PragmaHandler {
164 PragmaLoopHintHandler() : PragmaHandler("loop") {}
165 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
166 Token &FirstToken) override;
167};
168
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000169struct PragmaUnrollHintHandler : public PragmaHandler {
170 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
171 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
172 Token &FirstToken) override;
173};
174
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000175struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
176 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
177};
178
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000179struct PragmaMSIntrinsicHandler : public PragmaHandler {
180 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
181 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
182 Token &FirstToken) override;
183};
184
Justin Lebar67a78a62016-10-08 22:15:58 +0000185struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
186 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
187 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
188 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
189 Token &FirstToken) override;
190
191private:
192 Sema &Actions;
193};
194
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000195/// PragmaAttributeHandler - "\#pragma clang attribute ...".
196struct PragmaAttributeHandler : public PragmaHandler {
197 PragmaAttributeHandler(AttributeFactory &AttrFactory)
198 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
199 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
200 Token &FirstToken) override;
201
202 /// A pool of attributes that were parsed in \#pragma clang attribute.
203 ParsedAttributes AttributesForPragmaAttribute;
204};
205
Eli Bendersky06a40422014-06-06 20:31:48 +0000206} // end namespace
207
208void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000209 AlignHandler.reset(new PragmaAlignHandler());
210 PP.AddPragmaHandler(AlignHandler.get());
211
212 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
213 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
214
215 OptionsHandler.reset(new PragmaOptionsHandler());
216 PP.AddPragmaHandler(OptionsHandler.get());
217
218 PackHandler.reset(new PragmaPackHandler());
219 PP.AddPragmaHandler(PackHandler.get());
220
221 MSStructHandler.reset(new PragmaMSStructHandler());
222 PP.AddPragmaHandler(MSStructHandler.get());
223
224 UnusedHandler.reset(new PragmaUnusedHandler());
225 PP.AddPragmaHandler(UnusedHandler.get());
226
227 WeakHandler.reset(new PragmaWeakHandler());
228 PP.AddPragmaHandler(WeakHandler.get());
229
230 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
231 PP.AddPragmaHandler(RedefineExtnameHandler.get());
232
233 FPContractHandler.reset(new PragmaFPContractHandler());
234 PP.AddPragmaHandler("STDC", FPContractHandler.get());
235
Javed Absar2a67c9e2017-06-05 10:11:57 +0000236 PCSectionHandler.reset(new PragmaClangSectionHandler(Actions));
237 PP.AddPragmaHandler("clang", PCSectionHandler.get());
238
Reid Kleckner5b086462014-02-20 22:52:09 +0000239 if (getLangOpts().OpenCL) {
240 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
241 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
242
243 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
244 }
245 if (getLangOpts().OpenMP)
246 OpenMPHandler.reset(new PragmaOpenMPHandler());
247 else
248 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
249 PP.AddPragmaHandler(OpenMPHandler.get());
250
Yunzhong Gao99efc032015-03-23 20:41:42 +0000251 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000252 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
253 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000254 }
255
256 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000257 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
258 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
259 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
260 PP.AddPragmaHandler(MSPointersToMembers.get());
261 MSVtorDisp.reset(new PragmaMSVtorDisp());
262 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000263 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000264 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000265 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
266 PP.AddPragmaHandler(MSDataSeg.get());
267 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
268 PP.AddPragmaHandler(MSBSSSeg.get());
269 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
270 PP.AddPragmaHandler(MSConstSeg.get());
271 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
272 PP.AddPragmaHandler(MSCodeSeg.get());
273 MSSection.reset(new PragmaMSPragma("section"));
274 PP.AddPragmaHandler(MSSection.get());
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000275 MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler());
276 PP.AddPragmaHandler(MSRuntimeChecks.get());
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000277 MSIntrinsic.reset(new PragmaMSIntrinsicHandler());
278 PP.AddPragmaHandler(MSIntrinsic.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000279 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000280
Justin Lebar67a78a62016-10-08 22:15:58 +0000281 if (getLangOpts().CUDA) {
282 CUDAForceHostDeviceHandler.reset(
283 new PragmaForceCUDAHostDeviceHandler(Actions));
284 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
285 }
286
Eli Bendersky06a40422014-06-06 20:31:48 +0000287 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
288 PP.AddPragmaHandler("clang", OptimizeHandler.get());
289
290 LoopHintHandler.reset(new PragmaLoopHintHandler());
291 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000292
293 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
294 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000295
296 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
297 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000298
299 FPHandler.reset(new PragmaFPHandler());
300 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000301
302 AttributePragmaHandler.reset(new PragmaAttributeHandler(AttrFactory));
303 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000304}
305
306void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000307 // Remove the pragma handlers we installed.
308 PP.RemovePragmaHandler(AlignHandler.get());
309 AlignHandler.reset();
310 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
311 GCCVisibilityHandler.reset();
312 PP.RemovePragmaHandler(OptionsHandler.get());
313 OptionsHandler.reset();
314 PP.RemovePragmaHandler(PackHandler.get());
315 PackHandler.reset();
316 PP.RemovePragmaHandler(MSStructHandler.get());
317 MSStructHandler.reset();
318 PP.RemovePragmaHandler(UnusedHandler.get());
319 UnusedHandler.reset();
320 PP.RemovePragmaHandler(WeakHandler.get());
321 WeakHandler.reset();
322 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
323 RedefineExtnameHandler.reset();
324
325 if (getLangOpts().OpenCL) {
326 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
327 OpenCLExtensionHandler.reset();
328 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
329 }
330 PP.RemovePragmaHandler(OpenMPHandler.get());
331 OpenMPHandler.reset();
332
Yunzhong Gao99efc032015-03-23 20:41:42 +0000333 if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000334 PP.RemovePragmaHandler(MSCommentHandler.get());
335 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000336 }
337
Javed Absar2a67c9e2017-06-05 10:11:57 +0000338 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
339 PCSectionHandler.reset();
340
Yunzhong Gao99efc032015-03-23 20:41:42 +0000341 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000342 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
343 MSDetectMismatchHandler.reset();
344 PP.RemovePragmaHandler(MSPointersToMembers.get());
345 MSPointersToMembers.reset();
346 PP.RemovePragmaHandler(MSVtorDisp.get());
347 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000348 PP.RemovePragmaHandler(MSInitSeg.get());
349 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000350 PP.RemovePragmaHandler(MSDataSeg.get());
351 MSDataSeg.reset();
352 PP.RemovePragmaHandler(MSBSSSeg.get());
353 MSBSSSeg.reset();
354 PP.RemovePragmaHandler(MSConstSeg.get());
355 MSConstSeg.reset();
356 PP.RemovePragmaHandler(MSCodeSeg.get());
357 MSCodeSeg.reset();
358 PP.RemovePragmaHandler(MSSection.get());
359 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000360 PP.RemovePragmaHandler(MSRuntimeChecks.get());
361 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000362 PP.RemovePragmaHandler(MSIntrinsic.get());
363 MSIntrinsic.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000364 }
365
Justin Lebar67a78a62016-10-08 22:15:58 +0000366 if (getLangOpts().CUDA) {
367 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
368 CUDAForceHostDeviceHandler.reset();
369 }
370
Reid Kleckner5b086462014-02-20 22:52:09 +0000371 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
372 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000373
374 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
375 OptimizeHandler.reset();
376
377 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
378 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000379
380 PP.RemovePragmaHandler(UnrollHintHandler.get());
381 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000382
383 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
384 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000385
386 PP.RemovePragmaHandler("clang", FPHandler.get());
387 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000388
389 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
390 AttributePragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000391}
392
393/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000394///
395/// Each annot_pragma_unused is followed by the argument token so e.g.
396/// "#pragma unused(x,y)" becomes:
397/// annot_pragma_unused 'x' annot_pragma_unused 'y'
398void Parser::HandlePragmaUnused() {
399 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000400 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000401 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
402 ConsumeToken(); // The argument token.
403}
Eli Friedman570024a2010-08-05 06:57:20 +0000404
Rafael Espindola273fd772012-01-26 02:02:57 +0000405void Parser::HandlePragmaVisibility() {
406 assert(Tok.is(tok::annot_pragma_vis));
407 const IdentifierInfo *VisType =
408 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000409 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000410 Actions.ActOnPragmaVisibility(VisType, VisLoc);
411}
412
Benjamin Kramere003ca22015-10-28 13:54:16 +0000413namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000414struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000415 Sema::PragmaMsStackAction Action;
416 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000417 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000418};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000419} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000420
421void Parser::HandlePragmaPack() {
422 assert(Tok.is(tok::annot_pragma_pack));
423 PragmaPackInfo *Info =
424 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Hans Wennborgb4ece982017-07-26 21:29:24 +0000425 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000426 ExprResult Alignment;
427 if (Info->Alignment.is(tok::numeric_constant)) {
428 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Hans Wennborgb4ece982017-07-26 21:29:24 +0000429 if (Alignment.isInvalid())
Eli Friedman68be1642012-10-04 02:36:51 +0000430 return;
431 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000432 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
433 Alignment.get());
Eli Friedmanec52f922012-02-23 23:47:16 +0000434}
435
Eli Friedman68be1642012-10-04 02:36:51 +0000436void Parser::HandlePragmaMSStruct() {
437 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000438 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
439 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000440 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000441 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000442}
443
444void Parser::HandlePragmaAlign() {
445 assert(Tok.is(tok::annot_pragma_align));
446 Sema::PragmaOptionsAlignKind Kind =
447 static_cast<Sema::PragmaOptionsAlignKind>(
448 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000449 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000450 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
451}
452
Richard Smithba3a4f92016-01-12 21:59:26 +0000453void Parser::HandlePragmaDump() {
454 assert(Tok.is(tok::annot_pragma_dump));
455 IdentifierInfo *II =
456 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
457 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000458 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000459}
460
Eli Friedman68be1642012-10-04 02:36:51 +0000461void Parser::HandlePragmaWeak() {
462 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000463 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000464 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
465 Tok.getLocation());
466 ConsumeToken(); // The weak name.
467}
468
469void Parser::HandlePragmaWeakAlias() {
470 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000471 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000472 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
473 SourceLocation WeakNameLoc = Tok.getLocation();
474 ConsumeToken();
475 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
476 SourceLocation AliasNameLoc = Tok.getLocation();
477 ConsumeToken();
478 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
479 WeakNameLoc, AliasNameLoc);
480
481}
482
483void Parser::HandlePragmaRedefineExtname() {
484 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000485 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000486 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
487 SourceLocation RedefNameLoc = Tok.getLocation();
488 ConsumeToken();
489 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
490 SourceLocation AliasNameLoc = Tok.getLocation();
491 ConsumeToken();
492 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
493 RedefNameLoc, AliasNameLoc);
494}
495
496void Parser::HandlePragmaFPContract() {
497 assert(Tok.is(tok::annot_pragma_fp_contract));
498 tok::OnOffSwitch OOS =
499 static_cast<tok::OnOffSwitch>(
500 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000501
502 LangOptions::FPContractModeKind FPC;
503 switch (OOS) {
504 case tok::OOS_ON:
505 FPC = LangOptions::FPC_On;
506 break;
507 case tok::OOS_OFF:
508 FPC = LangOptions::FPC_Off;
509 break;
510 case tok::OOS_DEFAULT:
511 FPC = getLangOpts().getDefaultFPContractMode();
512 break;
513 }
514
515 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000516 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000517}
518
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000519StmtResult Parser::HandlePragmaCaptured()
520{
521 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000522 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000523
524 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000525 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000526 return StmtError();
527 }
528
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000529 SourceLocation Loc = Tok.getLocation();
530
531 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000532 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
533 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000534
535 StmtResult R = ParseCompoundStatement();
536 CapturedRegionScope.Exit();
537
538 if (R.isInvalid()) {
539 Actions.ActOnCapturedRegionError();
540 return StmtError();
541 }
542
543 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000544}
545
Eli Friedman68be1642012-10-04 02:36:51 +0000546namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000547 enum OpenCLExtState : char {
548 Disable, Enable, Begin, End
549 };
550 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000551}
552
553void Parser::HandlePragmaOpenCLExtension() {
554 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000555 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
556 auto State = Data->second;
557 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000558 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000559 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000560
Yaxun Liu5b746652016-12-18 05:18:55 +0000561 auto &Opt = Actions.getOpenCLOptions();
562 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000563 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
564 // overriding all previously issued extension directives, but only if the
565 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000566 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000567 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000568 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000569 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
570 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000571 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000572 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000573 } else if (State == Begin) {
574 if (!Opt.isKnown(Name) ||
575 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
576 Opt.support(Name);
577 }
578 Actions.setCurrentOpenCLExtension(Name);
579 } else if (State == End) {
580 if (Name != Actions.getCurrentOpenCLExtension())
581 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
582 Actions.setCurrentOpenCLExtension("");
583 } else if (!Opt.isKnown(Name))
584 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
585 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
586 Opt.enable(Name, State == Enable);
587 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
588 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
589 else
590 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000591}
592
David Majnemer4bb09802014-02-10 19:50:15 +0000593void Parser::HandlePragmaMSPointersToMembers() {
594 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000595 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
596 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000597 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000598 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000599 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
600}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000601
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000602void Parser::HandlePragmaMSVtorDisp() {
603 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
604 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000605 Sema::PragmaMsStackAction Action =
606 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000607 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000608 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000609 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000610}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000611
Warren Huntc3b18962014-04-08 22:30:47 +0000612void Parser::HandlePragmaMSPragma() {
613 assert(Tok.is(tok::annot_pragma_ms_pragma));
614 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000615 auto TheTokens =
616 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
617 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000618 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000619 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000620 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000621 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000622
Warren Huntc3b18962014-04-08 22:30:47 +0000623 // Figure out which #pragma we're dealing with. The switch has no default
624 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000625 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000626 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
627 .Case("data_seg", &Parser::HandlePragmaMSSegment)
628 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
629 .Case("const_seg", &Parser::HandlePragmaMSSegment)
630 .Case("code_seg", &Parser::HandlePragmaMSSegment)
631 .Case("section", &Parser::HandlePragmaMSSection)
632 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000633
634 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
635 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
636 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000637 while (Tok.isNot(tok::eof))
638 PP.Lex(Tok);
639 PP.Lex(Tok);
640 }
641}
642
Reid Kleckner722b1df2014-07-18 00:13:16 +0000643bool Parser::HandlePragmaMSSection(StringRef PragmaName,
644 SourceLocation PragmaLocation) {
645 if (Tok.isNot(tok::l_paren)) {
646 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
647 return false;
648 }
Warren Huntc3b18962014-04-08 22:30:47 +0000649 PP.Lex(Tok); // (
650 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000651 if (Tok.isNot(tok::string_literal)) {
652 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
653 << PragmaName;
654 return false;
655 }
656 ExprResult StringResult = ParseStringLiteralExpression();
657 if (StringResult.isInvalid())
658 return false; // Already diagnosed.
659 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
660 if (SegmentName->getCharByteWidth() != 1) {
661 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
662 << PragmaName;
663 return false;
664 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000665 int SectionFlags = ASTContext::PSF_Read;
666 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000667 while (Tok.is(tok::comma)) {
668 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000669 // Ignore "long" and "short".
670 // They are undocumented, but widely used, section attributes which appear
671 // to do nothing.
672 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
673 PP.Lex(Tok); // long/short
674 continue;
675 }
676
Reid Kleckner722b1df2014-07-18 00:13:16 +0000677 if (!Tok.isAnyIdentifier()) {
678 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
679 << PragmaName;
680 return false;
681 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000682 ASTContext::PragmaSectionFlag Flag =
683 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000684 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000685 .Case("read", ASTContext::PSF_Read)
686 .Case("write", ASTContext::PSF_Write)
687 .Case("execute", ASTContext::PSF_Execute)
688 .Case("shared", ASTContext::PSF_Invalid)
689 .Case("nopage", ASTContext::PSF_Invalid)
690 .Case("nocache", ASTContext::PSF_Invalid)
691 .Case("discard", ASTContext::PSF_Invalid)
692 .Case("remove", ASTContext::PSF_Invalid)
693 .Default(ASTContext::PSF_None);
694 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
695 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000696 ? diag::warn_pragma_invalid_specific_action
697 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000698 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000699 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000700 }
701 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000702 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000703 PP.Lex(Tok); // Identifier
704 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000705 // If no section attributes are specified, the section will be marked as
706 // read/write.
707 if (SectionFlagsAreDefault)
708 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000709 if (Tok.isNot(tok::r_paren)) {
710 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
711 return false;
712 }
Warren Huntc3b18962014-04-08 22:30:47 +0000713 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000714 if (Tok.isNot(tok::eof)) {
715 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
716 << PragmaName;
717 return false;
718 }
Warren Huntc3b18962014-04-08 22:30:47 +0000719 PP.Lex(Tok); // eof
720 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000721 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000722}
723
Reid Kleckner722b1df2014-07-18 00:13:16 +0000724bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
725 SourceLocation PragmaLocation) {
726 if (Tok.isNot(tok::l_paren)) {
727 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
728 return false;
729 }
Warren Huntc3b18962014-04-08 22:30:47 +0000730 PP.Lex(Tok); // (
731 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000732 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000733 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000734 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000735 if (PushPop == "push")
736 Action = Sema::PSK_Push;
737 else if (PushPop == "pop")
738 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000739 else {
740 PP.Diag(PragmaLocation,
741 diag::warn_pragma_expected_section_push_pop_or_name)
742 << PragmaName;
743 return false;
744 }
Warren Huntc3b18962014-04-08 22:30:47 +0000745 if (Action != Sema::PSK_Reset) {
746 PP.Lex(Tok); // push | pop
747 if (Tok.is(tok::comma)) {
748 PP.Lex(Tok); // ,
749 // If we've got a comma, we either need a label or a string.
750 if (Tok.isAnyIdentifier()) {
751 SlotLabel = Tok.getIdentifierInfo()->getName();
752 PP.Lex(Tok); // identifier
753 if (Tok.is(tok::comma))
754 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000755 else if (Tok.isNot(tok::r_paren)) {
756 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
757 << PragmaName;
758 return false;
759 }
Warren Huntc3b18962014-04-08 22:30:47 +0000760 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000761 } else if (Tok.isNot(tok::r_paren)) {
762 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
763 return false;
764 }
Warren Huntc3b18962014-04-08 22:30:47 +0000765 }
766 }
767 // Grab the string literal for our section name.
768 StringLiteral *SegmentName = nullptr;
769 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000770 if (Tok.isNot(tok::string_literal)) {
771 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000772 diag::warn_pragma_expected_section_name :
773 diag::warn_pragma_expected_section_label_or_name :
774 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000775 PP.Diag(PragmaLocation, DiagID) << PragmaName;
776 return false;
777 }
778 ExprResult StringResult = ParseStringLiteralExpression();
779 if (StringResult.isInvalid())
780 return false; // Already diagnosed.
781 SegmentName = cast<StringLiteral>(StringResult.get());
782 if (SegmentName->getCharByteWidth() != 1) {
783 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
784 << PragmaName;
785 return false;
786 }
Warren Huntc3b18962014-04-08 22:30:47 +0000787 // Setting section "" has no effect
788 if (SegmentName->getLength())
789 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
790 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000791 if (Tok.isNot(tok::r_paren)) {
792 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
793 return false;
794 }
Warren Huntc3b18962014-04-08 22:30:47 +0000795 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000796 if (Tok.isNot(tok::eof)) {
797 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
798 << PragmaName;
799 return false;
800 }
Warren Huntc3b18962014-04-08 22:30:47 +0000801 PP.Lex(Tok); // eof
802 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
803 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000804 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000805}
806
Reid Kleckner1a711b12014-07-22 00:53:05 +0000807// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000808bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
809 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000810 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
811 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
812 return false;
813 }
814
Reid Kleckner1a711b12014-07-22 00:53:05 +0000815 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
816 PragmaName))
817 return false;
818
819 // Parse either the known section names or the string section name.
820 StringLiteral *SegmentName = nullptr;
821 if (Tok.isAnyIdentifier()) {
822 auto *II = Tok.getIdentifierInfo();
823 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
824 .Case("compiler", "\".CRT$XCC\"")
825 .Case("lib", "\".CRT$XCL\"")
826 .Case("user", "\".CRT$XCU\"")
827 .Default("");
828
829 if (!Section.empty()) {
830 // Pretend the user wrote the appropriate string literal here.
831 Token Toks[1];
832 Toks[0].startToken();
833 Toks[0].setKind(tok::string_literal);
834 Toks[0].setLocation(Tok.getLocation());
835 Toks[0].setLiteralData(Section.data());
836 Toks[0].setLength(Section.size());
837 SegmentName =
838 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
839 PP.Lex(Tok);
840 }
841 } else if (Tok.is(tok::string_literal)) {
842 ExprResult StringResult = ParseStringLiteralExpression();
843 if (StringResult.isInvalid())
844 return false;
845 SegmentName = cast<StringLiteral>(StringResult.get());
846 if (SegmentName->getCharByteWidth() != 1) {
847 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
848 << PragmaName;
849 return false;
850 }
851 // FIXME: Add support for the '[, func-name]' part of the pragma.
852 }
853
854 if (!SegmentName) {
855 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
856 return false;
857 }
858
859 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
860 PragmaName) ||
861 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
862 PragmaName))
863 return false;
864
865 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
866 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000867}
868
Benjamin Kramere003ca22015-10-28 13:54:16 +0000869namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000870struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000871 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000872 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000873 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000874};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000875} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000876
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000877static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
878 std::string PragmaString;
879 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
880 PragmaString = "clang loop ";
881 PragmaString += Option.getIdentifierInfo()->getName();
882 } else {
883 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
884 "Unexpected pragma name");
885 PragmaString = "unroll";
886 }
887 return PragmaString;
888}
889
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000890bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000891 assert(Tok.is(tok::annot_pragma_loop_hint));
892 PragmaLoopHintInfo *Info =
893 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
894
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000895 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
896 Hint.PragmaNameLoc = IdentifierLoc::create(
897 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000898
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000899 // It is possible that the loop hint has no option identifier, such as
900 // #pragma unroll(4).
901 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
902 ? Info->Option.getIdentifierInfo()
903 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000904 Hint.OptionLoc = IdentifierLoc::create(
905 Actions.Context, Info->Option.getLocation(), OptionInfo);
906
David Blaikie2eabcc92016-02-09 18:52:09 +0000907 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000908
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000909 // Return a valid hint if pragma unroll or nounroll were specified
910 // without an argument.
911 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
912 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000913 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000914 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000915 Hint.Range = Info->PragmaName.getLocation();
916 return true;
917 }
918
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000919 // The constant expression is always followed by an eof token, which increases
920 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000921 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000922 "PragmaLoopHintInfo::Toks must contain at least one token.");
923
924 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +0000925 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +0000926 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000927 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +0000928 if (OptionInfo) { // Pragma Unroll does not specify an option.
929 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +0000930 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000931 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
932 .Case("vectorize", true)
933 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +0000934 .Default(false) ||
935 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000936 }
937
Adam Nemet2de463e2016-06-14 12:04:26 +0000938 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000939 // Verify loop hint has an argument.
940 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000941 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000942 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +0000943 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
944 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000945 return false;
946 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000947
948 // Validate the argument.
949 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000950 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000951 SourceLocation StateLoc = Toks[0].getLocation();
952 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +0000953
954 bool Valid = StateInfo &&
955 llvm::StringSwitch<bool>(StateInfo->getName())
956 .Cases("enable", "disable", true)
957 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +0000958 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +0000959 .Default(false);
960 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000961 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +0000962 << /*FullKeyword=*/OptionUnroll
963 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000964 return false;
965 }
David Blaikie2eabcc92016-02-09 18:52:09 +0000966 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000967 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
968 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000969 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
970 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000971 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000972 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +0000973 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000974
975 ExprResult R = ParseConstantExpression();
976
977 // Tokens following an error in an ill-formed constant expression will
978 // remain in the token stream and must be removed.
979 if (Tok.isNot(tok::eof)) {
980 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
981 << PragmaLoopHintString(Info->PragmaName, Info->Option);
982 while (Tok.isNot(tok::eof))
983 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000984 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000985
986 ConsumeToken(); // Consume the constant expression eof terminator.
987
988 if (R.isInvalid() ||
989 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
990 return false;
991
992 // Argument is a constant expression with an integer type.
993 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000994 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000995
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000996 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +0000997 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000998 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000999}
1000
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001001namespace {
1002struct PragmaAttributeInfo {
1003 enum ActionType { Push, Pop };
1004 ParsedAttributes &Attributes;
1005 ActionType Action;
1006 ArrayRef<Token> Tokens;
1007
1008 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1009};
1010
1011#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1012
1013} // end anonymous namespace
1014
1015static StringRef getIdentifier(const Token &Tok) {
1016 if (Tok.is(tok::identifier))
1017 return Tok.getIdentifierInfo()->getName();
1018 const char *S = tok::getKeywordSpelling(Tok.getKind());
1019 if (!S)
1020 return "";
1021 return S;
1022}
1023
1024static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1025 using namespace attr;
1026 switch (Rule) {
1027#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1028 case Value: \
1029 return IsAbstract;
1030#include "clang/Basic/AttrSubMatchRulesList.inc"
1031 }
1032 llvm_unreachable("Invalid attribute subject match rule");
1033 return false;
1034}
1035
1036static void diagnoseExpectedAttributeSubjectSubRule(
1037 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1038 SourceLocation SubRuleLoc) {
1039 auto Diagnostic =
1040 PRef.Diag(SubRuleLoc,
1041 diag::err_pragma_attribute_expected_subject_sub_identifier)
1042 << PrimaryRuleName;
1043 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1044 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1045 else
1046 Diagnostic << /*SubRulesSupported=*/0;
1047}
1048
1049static void diagnoseUnknownAttributeSubjectSubRule(
1050 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1051 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1052
1053 auto Diagnostic =
1054 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1055 << SubRuleName << PrimaryRuleName;
1056 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1057 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1058 else
1059 Diagnostic << /*SubRulesSupported=*/0;
1060}
1061
1062bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1063 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1064 SourceLocation &LastMatchRuleEndLoc) {
1065 bool IsAny = false;
1066 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1067 if (getIdentifier(Tok) == "any") {
1068 AnyLoc = ConsumeToken();
1069 IsAny = true;
1070 if (AnyParens.expectAndConsume())
1071 return true;
1072 }
1073
1074 do {
1075 // Parse the subject matcher rule.
1076 StringRef Name = getIdentifier(Tok);
1077 if (Name.empty()) {
1078 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1079 return true;
1080 }
1081 std::pair<Optional<attr::SubjectMatchRule>,
1082 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1083 Rule = isAttributeSubjectMatchRule(Name);
1084 if (!Rule.first) {
1085 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1086 return true;
1087 }
1088 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1089 SourceLocation RuleLoc = ConsumeToken();
1090
1091 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1092 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1093 if (Parens.expectAndConsume())
1094 return true;
1095 } else if (Parens.consumeOpen()) {
1096 if (!SubjectMatchRules
1097 .insert(
1098 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1099 .second)
1100 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1101 << Name
1102 << FixItHint::CreateRemoval(SourceRange(
1103 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1104 LastMatchRuleEndLoc = RuleLoc;
1105 continue;
1106 }
1107
1108 // Parse the sub-rules.
1109 StringRef SubRuleName = getIdentifier(Tok);
1110 if (SubRuleName.empty()) {
1111 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1112 Tok.getLocation());
1113 return true;
1114 }
1115 attr::SubjectMatchRule SubRule;
1116 if (SubRuleName == "unless") {
1117 SourceLocation SubRuleLoc = ConsumeToken();
1118 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1119 if (Parens.expectAndConsume())
1120 return true;
1121 SubRuleName = getIdentifier(Tok);
1122 if (SubRuleName.empty()) {
1123 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1124 SubRuleLoc);
1125 return true;
1126 }
1127 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1128 if (!SubRuleOrNone) {
1129 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1130 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1131 SubRuleUnlessName, SubRuleLoc);
1132 return true;
1133 }
1134 SubRule = *SubRuleOrNone;
1135 ConsumeToken();
1136 if (Parens.consumeClose())
1137 return true;
1138 } else {
1139 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1140 if (!SubRuleOrNone) {
1141 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1142 SubRuleName, Tok.getLocation());
1143 return true;
1144 }
1145 SubRule = *SubRuleOrNone;
1146 ConsumeToken();
1147 }
1148 SourceLocation RuleEndLoc = Tok.getLocation();
1149 LastMatchRuleEndLoc = RuleEndLoc;
1150 if (Parens.consumeClose())
1151 return true;
1152 if (!SubjectMatchRules
1153 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1154 .second) {
1155 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1156 << attr::getSubjectMatchRuleSpelling(SubRule)
1157 << FixItHint::CreateRemoval(SourceRange(
1158 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1159 continue;
1160 }
1161 } while (IsAny && TryConsumeToken(tok::comma));
1162
1163 if (IsAny)
1164 if (AnyParens.consumeClose())
1165 return true;
1166
1167 return false;
1168}
1169
1170namespace {
1171
1172/// Describes the stage at which attribute subject rule parsing was interruped.
1173enum class MissingAttributeSubjectRulesRecoveryPoint {
1174 Comma,
1175 ApplyTo,
1176 Equals,
1177 Any,
1178 None,
1179};
1180
1181MissingAttributeSubjectRulesRecoveryPoint
1182getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1183 if (const auto *II = Tok.getIdentifierInfo()) {
1184 if (II->isStr("apply_to"))
1185 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1186 if (II->isStr("any"))
1187 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1188 }
1189 if (Tok.is(tok::equal))
1190 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1191 return MissingAttributeSubjectRulesRecoveryPoint::None;
1192}
1193
1194/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1195/// suggests the possible attribute subject rules in a fix-it together with
1196/// any other missing tokens.
1197DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1198 unsigned DiagID, AttributeList &Attribute,
1199 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1200 SourceLocation Loc = PRef.getEndOfPreviousToken();
1201 if (Loc.isInvalid())
1202 Loc = PRef.getCurToken().getLocation();
1203 auto Diagnostic = PRef.Diag(Loc, DiagID);
1204 std::string FixIt;
1205 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1206 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1207 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1208 FixIt = ", ";
1209 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1210 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1211 FixIt += "apply_to";
1212 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1213 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1214 FixIt += " = ";
1215 SourceRange FixItRange(Loc);
1216 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1217 // Gather the subject match rules that are supported by the attribute.
1218 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1219 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1220 if (SubjectMatchRuleSet.empty()) {
1221 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1222 // placeholders will be supported by the fix-its.
1223 return Diagnostic;
1224 }
1225 FixIt += "any(";
1226 bool NeedsComma = false;
1227 for (const auto &I : SubjectMatchRuleSet) {
1228 // Ensure that the missing rule is reported in the fix-it only when it's
1229 // supported in the current language mode.
1230 if (!I.second)
1231 continue;
1232 if (NeedsComma)
1233 FixIt += ", ";
1234 else
1235 NeedsComma = true;
1236 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1237 }
1238 FixIt += ")";
1239 // Check if we need to remove the range
1240 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1241 FixItRange.setEnd(PRef.getCurToken().getLocation());
1242 }
1243 if (FixItRange.getBegin() == FixItRange.getEnd())
1244 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1245 else
1246 Diagnostic << FixItHint::CreateReplacement(
1247 CharSourceRange::getCharRange(FixItRange), FixIt);
1248 return Diagnostic;
1249}
1250
1251} // end anonymous namespace
1252
1253void Parser::HandlePragmaAttribute() {
1254 assert(Tok.is(tok::annot_pragma_attribute) &&
1255 "Expected #pragma attribute annotation token");
1256 SourceLocation PragmaLoc = Tok.getLocation();
1257 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1258 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001259 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001260 Actions.ActOnPragmaAttributePop(PragmaLoc);
1261 return;
1262 }
1263 // Parse the actual attribute with its arguments.
1264 assert(Info->Action == PragmaAttributeInfo::Push &&
1265 "Unexpected #pragma attribute command");
1266 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001267 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001268
1269 ParsedAttributes &Attrs = Info->Attributes;
1270 Attrs.clearListOnly();
1271
1272 auto SkipToEnd = [this]() {
1273 SkipUntil(tok::eof, StopBeforeMatch);
1274 ConsumeToken();
1275 };
1276
1277 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1278 // Parse the CXX11 style attribute.
1279 ParseCXX11AttributeSpecifier(Attrs);
1280 } else if (Tok.is(tok::kw___attribute)) {
1281 ConsumeToken();
1282 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1283 "attribute"))
1284 return SkipToEnd();
1285 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1286 return SkipToEnd();
1287
1288 if (Tok.isNot(tok::identifier)) {
1289 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1290 SkipToEnd();
1291 return;
1292 }
1293 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1294 SourceLocation AttrNameLoc = ConsumeToken();
1295
1296 if (Tok.isNot(tok::l_paren))
1297 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1298 AttributeList::AS_GNU);
1299 else
1300 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1301 /*ScopeName=*/nullptr,
1302 /*ScopeLoc=*/SourceLocation(),
1303 AttributeList::AS_GNU,
1304 /*Declarator=*/nullptr);
1305
1306 if (ExpectAndConsume(tok::r_paren))
1307 return SkipToEnd();
1308 if (ExpectAndConsume(tok::r_paren))
1309 return SkipToEnd();
1310 } else if (Tok.is(tok::kw___declspec)) {
1311 ParseMicrosoftDeclSpecs(Attrs);
1312 } else {
1313 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1314 if (Tok.getIdentifierInfo()) {
1315 // If we suspect that this is an attribute suggest the use of
1316 // '__attribute__'.
1317 if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1318 AttributeList::AS_GNU) !=
1319 AttributeList::UnknownAttribute) {
1320 SourceLocation InsertStartLoc = Tok.getLocation();
1321 ConsumeToken();
1322 if (Tok.is(tok::l_paren)) {
1323 ConsumeAnyToken();
1324 SkipUntil(tok::r_paren, StopBeforeMatch);
1325 if (Tok.isNot(tok::r_paren))
1326 return SkipToEnd();
1327 }
1328 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1329 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1330 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1331 }
1332 }
1333 SkipToEnd();
1334 return;
1335 }
1336
1337 if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
1338 SkipToEnd();
1339 return;
1340 }
1341
1342 // Ensure that we don't have more than one attribute.
1343 if (Attrs.getList()->getNext()) {
1344 SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
1345 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1346 SkipToEnd();
1347 return;
1348 }
1349
1350 if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
1351 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1352 << Attrs.getList()->getName();
1353 SkipToEnd();
1354 return;
1355 }
1356 AttributeList &Attribute = *Attrs.getList();
1357
1358 // Parse the subject-list.
1359 if (!TryConsumeToken(tok::comma)) {
1360 createExpectedAttributeSubjectRulesTokenDiagnostic(
1361 diag::err_expected, Attribute,
1362 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1363 << tok::comma;
1364 SkipToEnd();
1365 return;
1366 }
1367
1368 if (Tok.isNot(tok::identifier)) {
1369 createExpectedAttributeSubjectRulesTokenDiagnostic(
1370 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1371 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1372 SkipToEnd();
1373 return;
1374 }
1375 const IdentifierInfo *II = Tok.getIdentifierInfo();
1376 if (!II->isStr("apply_to")) {
1377 createExpectedAttributeSubjectRulesTokenDiagnostic(
1378 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1379 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1380 SkipToEnd();
1381 return;
1382 }
1383 ConsumeToken();
1384
1385 if (!TryConsumeToken(tok::equal)) {
1386 createExpectedAttributeSubjectRulesTokenDiagnostic(
1387 diag::err_expected, Attribute,
1388 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1389 << tok::equal;
1390 SkipToEnd();
1391 return;
1392 }
1393
1394 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1395 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1396 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1397 LastMatchRuleEndLoc)) {
1398 SkipToEnd();
1399 return;
1400 }
1401
1402 // Tokens following an ill-formed attribute will remain in the token stream
1403 // and must be removed.
1404 if (Tok.isNot(tok::eof)) {
1405 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1406 SkipToEnd();
1407 return;
1408 }
1409
1410 // Consume the eof terminator token.
1411 ConsumeToken();
1412
1413 Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
1414 std::move(SubjectMatchRules));
1415}
1416
Eli Bendersky06a40422014-06-06 20:31:48 +00001417// #pragma GCC visibility comes in two variants:
1418// 'push' '(' [visibility] ')'
1419// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001420void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1421 PragmaIntroducerKind Introducer,
1422 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001423 SourceLocation VisLoc = VisTok.getLocation();
1424
1425 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001426 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001427
1428 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1429
Eli Friedman570024a2010-08-05 06:57:20 +00001430 const IdentifierInfo *VisType;
1431 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001432 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001433 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001434 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001435 if (Tok.isNot(tok::l_paren)) {
1436 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1437 << "visibility";
1438 return;
1439 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001440 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001441 VisType = Tok.getIdentifierInfo();
1442 if (!VisType) {
1443 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1444 << "visibility";
1445 return;
1446 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001447 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001448 if (Tok.isNot(tok::r_paren)) {
1449 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1450 << "visibility";
1451 return;
1452 }
1453 } else {
1454 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1455 << "visibility";
1456 return;
1457 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001458 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001459 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001460 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001461 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1462 << "visibility";
1463 return;
1464 }
1465
David Blaikie2eabcc92016-02-09 18:52:09 +00001466 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001467 Toks[0].startToken();
1468 Toks[0].setKind(tok::annot_pragma_vis);
1469 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001470 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001471 Toks[0].setAnnotationValue(
1472 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001473 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001474}
1475
Daniel Dunbar921b9682008-10-04 19:21:03 +00001476// #pragma pack(...) comes in the following delicious flavors:
1477// pack '(' [integer] ')'
1478// pack '(' 'show' ')'
1479// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001480void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1481 PragmaIntroducerKind Introducer,
1482 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001483 SourceLocation PackLoc = PackTok.getLocation();
1484
1485 Token Tok;
1486 PP.Lex(Tok);
1487 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001488 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001489 return;
1490 }
1491
Denis Zobnin10c4f452016-04-29 18:17:40 +00001492 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1493 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001494 Token Alignment;
1495 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001496 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001497 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001498 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001499
1500 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001501
1502 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1503 // the push/pop stack.
1504 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001505 Action =
1506 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001507 } else if (Tok.is(tok::identifier)) {
1508 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001509 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001510 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001511 PP.Lex(Tok);
1512 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001513 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001514 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001515 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001516 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001517 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001518 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001519 return;
Mike Stump11289f42009-09-09 15:08:12 +00001520 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001521 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001522
Daniel Dunbar921b9682008-10-04 19:21:03 +00001523 if (Tok.is(tok::comma)) {
1524 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001525
Daniel Dunbar921b9682008-10-04 19:21:03 +00001526 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001527 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001528 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001529
1530 PP.Lex(Tok);
1531 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001532 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001533 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001534
Daniel Dunbar921b9682008-10-04 19:21:03 +00001535 if (Tok.is(tok::comma)) {
1536 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001537
Daniel Dunbar921b9682008-10-04 19:21:03 +00001538 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001539 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001540 return;
1541 }
Mike Stump11289f42009-09-09 15:08:12 +00001542
Denis Zobnin10c4f452016-04-29 18:17:40 +00001543 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001544 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001545
1546 PP.Lex(Tok);
1547 }
1548 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001549 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001550 return;
1551 }
1552 }
1553 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001554 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001555 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1556 // the push/pop stack.
1557 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001558 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001559 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001560
1561 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001562 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001563 return;
1564 }
1565
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001566 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001567 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001568 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001569 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1570 return;
1571 }
1572
David Blaikie2eabcc92016-02-09 18:52:09 +00001573 PragmaPackInfo *Info =
1574 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001575 Info->Action = Action;
1576 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001577 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001578
David Blaikie2eabcc92016-02-09 18:52:09 +00001579 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1580 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001581 Toks[0].startToken();
1582 Toks[0].setKind(tok::annot_pragma_pack);
1583 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001584 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001585 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001586 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001587}
1588
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001589// #pragma ms_struct on
1590// #pragma ms_struct off
1591void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1592 PragmaIntroducerKind Introducer,
1593 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001594 PragmaMSStructKind Kind = PMSST_OFF;
1595
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001596 Token Tok;
1597 PP.Lex(Tok);
1598 if (Tok.isNot(tok::identifier)) {
1599 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1600 return;
1601 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001602 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001603 const IdentifierInfo *II = Tok.getIdentifierInfo();
1604 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001605 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001606 PP.Lex(Tok);
1607 }
1608 else if (II->isStr("off") || II->isStr("reset"))
1609 PP.Lex(Tok);
1610 else {
1611 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1612 return;
1613 }
1614
1615 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001616 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1617 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001618 return;
1619 }
Eli Friedman68be1642012-10-04 02:36:51 +00001620
David Blaikie2eabcc92016-02-09 18:52:09 +00001621 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1622 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001623 Toks[0].startToken();
1624 Toks[0].setKind(tok::annot_pragma_msstruct);
1625 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001626 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001627 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1628 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001629 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001630}
1631
Javed Absar2a67c9e2017-06-05 10:11:57 +00001632// #pragma clang section bss="abc" data="" rodata="def" text=""
1633void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1634 PragmaIntroducerKind Introducer, Token &FirstToken) {
1635
1636 Token Tok;
1637 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1638
1639 PP.Lex(Tok); // eat 'section'
1640 while (Tok.isNot(tok::eod)) {
1641 if (Tok.isNot(tok::identifier)) {
1642 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1643 return;
1644 }
1645
1646 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1647 if (SecType->isStr("bss"))
1648 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1649 else if (SecType->isStr("data"))
1650 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1651 else if (SecType->isStr("rodata"))
1652 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1653 else if (SecType->isStr("text"))
1654 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1655 else {
1656 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1657 return;
1658 }
1659
1660 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1661 if (Tok.isNot(tok::equal)) {
1662 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1663 return;
1664 }
1665
1666 std::string SecName;
1667 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1668 return;
1669
1670 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1671 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1672 Sema::PragmaClangSectionAction::PCSA_Clear),
1673 SecKind, SecName);
1674 }
1675}
1676
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001677// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1678// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001679static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001680 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001681 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001682
1683 if (IsOptions) {
1684 PP.Lex(Tok);
1685 if (Tok.isNot(tok::identifier) ||
1686 !Tok.getIdentifierInfo()->isStr("align")) {
1687 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1688 return;
1689 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001690 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001691
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001692 PP.Lex(Tok);
1693 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001694 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1695 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001696 return;
1697 }
1698
1699 PP.Lex(Tok);
1700 if (Tok.isNot(tok::identifier)) {
1701 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001702 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001703 return;
1704 }
1705
John McCallfaf5fb42010-08-26 23:41:50 +00001706 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001707 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001708 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001709 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001710 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001711 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001712 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001713 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001714 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001715 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001716 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001717 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001718 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001719 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001720 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001721 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1722 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001723 return;
1724 }
1725
David Majnemera8f2f1d2015-03-19 00:10:23 +00001726 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001727 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001728 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001729 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001730 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001731 return;
1732 }
1733
David Blaikie2eabcc92016-02-09 18:52:09 +00001734 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1735 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001736 Toks[0].startToken();
1737 Toks[0].setKind(tok::annot_pragma_align);
1738 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001739 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001740 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1741 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001742 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001743}
1744
Douglas Gregorc7d65762010-09-09 22:45:38 +00001745void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1746 PragmaIntroducerKind Introducer,
1747 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001748 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001749}
1750
Douglas Gregorc7d65762010-09-09 22:45:38 +00001751void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1752 PragmaIntroducerKind Introducer,
1753 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001754 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001755}
1756
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001757// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001758void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1759 PragmaIntroducerKind Introducer,
1760 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001761 // FIXME: Should we be expanding macros here? My guess is no.
1762 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001763
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001764 // Lex the left '('.
1765 Token Tok;
1766 PP.Lex(Tok);
1767 if (Tok.isNot(tok::l_paren)) {
1768 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1769 return;
1770 }
Mike Stump11289f42009-09-09 15:08:12 +00001771
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001772 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001773 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001774 SourceLocation RParenLoc;
1775 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001776
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001777 while (true) {
1778 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001779
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001780 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001781 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001782 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001783 LexID = false;
1784 continue;
1785 }
1786
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001787 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001788 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1789 return;
1790 }
Mike Stump11289f42009-09-09 15:08:12 +00001791
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001792 // We are execting a ')' or a ','.
1793 if (Tok.is(tok::comma)) {
1794 LexID = true;
1795 continue;
1796 }
Mike Stump11289f42009-09-09 15:08:12 +00001797
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001798 if (Tok.is(tok::r_paren)) {
1799 RParenLoc = Tok.getLocation();
1800 break;
1801 }
Mike Stump11289f42009-09-09 15:08:12 +00001802
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001803 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001804 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001805 return;
1806 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001807
1808 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001809 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001810 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1811 "unused";
1812 return;
1813 }
1814
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001815 // Verify that we have a location for the right parenthesis.
1816 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001817 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001818
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001819 // For each identifier token, insert into the token stream a
1820 // annot_pragma_unused token followed by the identifier token.
1821 // This allows us to cache a "#pragma unused" that occurs inside an inline
1822 // C++ member function.
1823
David Blaikie2eabcc92016-02-09 18:52:09 +00001824 MutableArrayRef<Token> Toks(
1825 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1826 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001827 for (unsigned i=0; i != Identifiers.size(); i++) {
1828 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1829 pragmaUnusedTok.startToken();
1830 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1831 pragmaUnusedTok.setLocation(UnusedLoc);
1832 idTok = Identifiers[i];
1833 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001834 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001835}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001836
1837// #pragma weak identifier
1838// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001839void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1840 PragmaIntroducerKind Introducer,
1841 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001842 SourceLocation WeakLoc = WeakTok.getLocation();
1843
1844 Token Tok;
1845 PP.Lex(Tok);
1846 if (Tok.isNot(tok::identifier)) {
1847 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1848 return;
1849 }
1850
Eli Friedman68be1642012-10-04 02:36:51 +00001851 Token WeakName = Tok;
1852 bool HasAlias = false;
1853 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001854
1855 PP.Lex(Tok);
1856 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001857 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001858 PP.Lex(Tok);
1859 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001860 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001861 << "weak";
1862 return;
1863 }
Eli Friedman68be1642012-10-04 02:36:51 +00001864 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001865 PP.Lex(Tok);
1866 }
1867
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001868 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001869 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1870 return;
1871 }
1872
Eli Friedman68be1642012-10-04 02:36:51 +00001873 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001874 MutableArrayRef<Token> Toks(
1875 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001876 Token &pragmaUnusedTok = Toks[0];
1877 pragmaUnusedTok.startToken();
1878 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1879 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001880 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001881 Toks[1] = WeakName;
1882 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001883 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001884 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001885 MutableArrayRef<Token> Toks(
1886 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001887 Token &pragmaUnusedTok = Toks[0];
1888 pragmaUnusedTok.startToken();
1889 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1890 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001891 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001892 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001893 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001894 }
1895}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001896
David Chisnall0867d9c2012-02-18 16:12:34 +00001897// #pragma redefine_extname identifier identifier
1898void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1899 PragmaIntroducerKind Introducer,
1900 Token &RedefToken) {
1901 SourceLocation RedefLoc = RedefToken.getLocation();
1902
1903 Token Tok;
1904 PP.Lex(Tok);
1905 if (Tok.isNot(tok::identifier)) {
1906 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1907 "redefine_extname";
1908 return;
1909 }
1910
Eli Friedman68be1642012-10-04 02:36:51 +00001911 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001912 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001913
David Chisnall0867d9c2012-02-18 16:12:34 +00001914 if (Tok.isNot(tok::identifier)) {
1915 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1916 << "redefine_extname";
1917 return;
1918 }
Eli Friedman68be1642012-10-04 02:36:51 +00001919
1920 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001921 PP.Lex(Tok);
1922
1923 if (Tok.isNot(tok::eod)) {
1924 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1925 "redefine_extname";
1926 return;
1927 }
1928
David Blaikie2eabcc92016-02-09 18:52:09 +00001929 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1930 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001931 Token &pragmaRedefTok = Toks[0];
1932 pragmaRedefTok.startToken();
1933 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1934 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001935 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001936 Toks[1] = RedefName;
1937 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001938 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00001939}
1940
1941
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001942void
1943PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1944 PragmaIntroducerKind Introducer,
1945 Token &Tok) {
1946 tok::OnOffSwitch OOS;
1947 if (PP.LexOnOffSwitch(OOS))
1948 return;
1949
David Blaikie2eabcc92016-02-09 18:52:09 +00001950 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1951 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001952 Toks[0].startToken();
1953 Toks[0].setKind(tok::annot_pragma_fp_contract);
1954 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001955 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001956 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1957 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001958 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001959}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001960
1961void
1962PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1963 PragmaIntroducerKind Introducer,
1964 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001965 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001966 if (Tok.isNot(tok::identifier)) {
1967 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1968 "OPENCL";
1969 return;
1970 }
Yaxun Liu5b746652016-12-18 05:18:55 +00001971 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001972 SourceLocation NameLoc = Tok.getLocation();
1973
1974 PP.Lex(Tok);
1975 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00001976 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001977 return;
1978 }
1979
1980 PP.Lex(Tok);
1981 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00001982 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001983 return;
1984 }
Yaxun Liu5b746652016-12-18 05:18:55 +00001985 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001986
Yaxun Liu5b746652016-12-18 05:18:55 +00001987 OpenCLExtState State;
1988 if (Pred->isStr("enable")) {
1989 State = Enable;
1990 } else if (Pred->isStr("disable")) {
1991 State = Disable;
1992 } else if (Pred->isStr("begin"))
1993 State = Begin;
1994 else if (Pred->isStr("end"))
1995 State = End;
1996 else {
1997 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
1998 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001999 return;
2000 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002001 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002002
Eli Friedman68be1642012-10-04 02:36:51 +00002003 PP.Lex(Tok);
2004 if (Tok.isNot(tok::eod)) {
2005 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2006 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002007 return;
2008 }
Eli Friedman68be1642012-10-04 02:36:51 +00002009
Yaxun Liu5b746652016-12-18 05:18:55 +00002010 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2011 Info->first = Ext;
2012 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002013 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2014 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002015 Toks[0].startToken();
2016 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2017 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002018 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002019 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00002020 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002021
2022 if (PP.getPPCallbacks())
Yaxun Liu5b746652016-12-18 05:18:55 +00002023 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2024 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002025}
2026
Alexey Bataeva769e072013-03-22 06:34:35 +00002027/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
2028///
2029void
2030PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2031 PragmaIntroducerKind Introducer,
2032 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002033 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2034 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002035 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002036 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2037 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002038 }
2039 PP.DiscardUntilEndOfDirective();
2040}
2041
2042/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
2043///
2044void
2045PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2046 PragmaIntroducerKind Introducer,
2047 Token &FirstTok) {
2048 SmallVector<Token, 16> Pragma;
2049 Token Tok;
2050 Tok.startToken();
2051 Tok.setKind(tok::annot_pragma_openmp);
2052 Tok.setLocation(FirstTok.getLocation());
2053
2054 while (Tok.isNot(tok::eod)) {
2055 Pragma.push_back(Tok);
2056 PP.Lex(Tok);
2057 }
2058 SourceLocation EodLoc = Tok.getLocation();
2059 Tok.startToken();
2060 Tok.setKind(tok::annot_pragma_openmp_end);
2061 Tok.setLocation(EodLoc);
2062 Pragma.push_back(Tok);
2063
David Blaikie2eabcc92016-02-09 18:52:09 +00002064 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
2065 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2066 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2067 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002068}
Reid Kleckner002562a2013-05-06 21:02:12 +00002069
David Majnemer4bb09802014-02-10 19:50:15 +00002070/// \brief Handle '#pragma pointers_to_members'
2071// The grammar for this pragma is as follows:
2072//
2073// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2074//
2075// #pragma pointers_to_members '(' 'best_case' ')'
2076// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2077// #pragma pointers_to_members '(' inheritance-model ')'
2078void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2079 PragmaIntroducerKind Introducer,
2080 Token &Tok) {
2081 SourceLocation PointersToMembersLoc = Tok.getLocation();
2082 PP.Lex(Tok);
2083 if (Tok.isNot(tok::l_paren)) {
2084 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2085 << "pointers_to_members";
2086 return;
2087 }
2088 PP.Lex(Tok);
2089 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2090 if (!Arg) {
2091 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2092 << "pointers_to_members";
2093 return;
2094 }
2095 PP.Lex(Tok);
2096
David Majnemer86c318f2014-02-11 21:05:00 +00002097 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002098 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002099 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002100 } else {
2101 if (Arg->isStr("full_generality")) {
2102 if (Tok.is(tok::comma)) {
2103 PP.Lex(Tok);
2104
2105 Arg = Tok.getIdentifierInfo();
2106 if (!Arg) {
2107 PP.Diag(Tok.getLocation(),
2108 diag::err_pragma_pointers_to_members_unknown_kind)
2109 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2110 return;
2111 }
2112 PP.Lex(Tok);
2113 } else if (Tok.is(tok::r_paren)) {
2114 // #pragma pointers_to_members(full_generality) implicitly specifies
2115 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002116 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002117 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002118 } else {
2119 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2120 << "full_generality";
2121 return;
2122 }
2123 }
2124
2125 if (Arg) {
2126 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002127 RepresentationMethod =
2128 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002129 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002130 RepresentationMethod =
2131 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002132 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002133 RepresentationMethod =
2134 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002135 } else {
2136 PP.Diag(Tok.getLocation(),
2137 diag::err_pragma_pointers_to_members_unknown_kind)
2138 << Arg << /*HasPointerDeclaration*/ 1;
2139 return;
2140 }
2141 }
2142 }
2143
2144 if (Tok.isNot(tok::r_paren)) {
2145 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2146 << (Arg ? Arg->getName() : "full_generality");
2147 return;
2148 }
2149
David Majnemera8f2f1d2015-03-19 00:10:23 +00002150 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002151 PP.Lex(Tok);
2152 if (Tok.isNot(tok::eod)) {
2153 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2154 << "pointers_to_members";
2155 return;
2156 }
2157
2158 Token AnnotTok;
2159 AnnotTok.startToken();
2160 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2161 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002162 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002163 AnnotTok.setAnnotationValue(
2164 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2165 PP.EnterToken(AnnotTok);
2166}
2167
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002168/// \brief Handle '#pragma vtordisp'
2169// The grammar for this pragma is as follows:
2170//
2171// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2172//
2173// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2174// #pragma vtordisp '(' 'pop' ')'
2175// #pragma vtordisp '(' ')'
2176void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2177 PragmaIntroducerKind Introducer,
2178 Token &Tok) {
2179 SourceLocation VtorDispLoc = Tok.getLocation();
2180 PP.Lex(Tok);
2181 if (Tok.isNot(tok::l_paren)) {
2182 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2183 return;
2184 }
2185 PP.Lex(Tok);
2186
Denis Zobnin2290dac2016-04-29 11:27:00 +00002187 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002188 const IdentifierInfo *II = Tok.getIdentifierInfo();
2189 if (II) {
2190 if (II->isStr("push")) {
2191 // #pragma vtordisp(push, mode)
2192 PP.Lex(Tok);
2193 if (Tok.isNot(tok::comma)) {
2194 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2195 return;
2196 }
2197 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002198 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002199 // not push, could be on/off
2200 } else if (II->isStr("pop")) {
2201 // #pragma vtordisp(pop)
2202 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002203 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002204 }
2205 // not push or pop, could be on/off
2206 } else {
2207 if (Tok.is(tok::r_paren)) {
2208 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002209 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002210 }
2211 }
2212
2213
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002214 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002215 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002216 const IdentifierInfo *II = Tok.getIdentifierInfo();
2217 if (II && II->isStr("off")) {
2218 PP.Lex(Tok);
2219 Value = 0;
2220 } else if (II && II->isStr("on")) {
2221 PP.Lex(Tok);
2222 Value = 1;
2223 } else if (Tok.is(tok::numeric_constant) &&
2224 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2225 if (Value > 2) {
2226 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2227 << 0 << 2 << "vtordisp";
2228 return;
2229 }
2230 } else {
2231 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2232 << "vtordisp";
2233 return;
2234 }
2235 }
2236
2237 // Finish the pragma: ')' $
2238 if (Tok.isNot(tok::r_paren)) {
2239 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2240 return;
2241 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002242 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002243 PP.Lex(Tok);
2244 if (Tok.isNot(tok::eod)) {
2245 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2246 << "vtordisp";
2247 return;
2248 }
2249
2250 // Enter the annotation.
2251 Token AnnotTok;
2252 AnnotTok.startToken();
2253 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2254 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002255 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002256 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002257 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002258 PP.EnterToken(AnnotTok);
2259}
2260
Warren Huntc3b18962014-04-08 22:30:47 +00002261/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
2262/// an annotation token.
2263void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2264 PragmaIntroducerKind Introducer,
2265 Token &Tok) {
2266 Token EoF, AnnotTok;
2267 EoF.startToken();
2268 EoF.setKind(tok::eof);
2269 AnnotTok.startToken();
2270 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2271 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002272 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002273 SmallVector<Token, 8> TokenVector;
2274 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002275 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002276 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002277 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2278 }
Warren Huntc3b18962014-04-08 22:30:47 +00002279 // Add a sentinal EoF token to the end of the list.
2280 TokenVector.push_back(EoF);
2281 // We must allocate this array with new because EnterTokenStream is going to
2282 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00002283 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
2284 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002285 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002286 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2287 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002288 AnnotTok.setAnnotationValue(Value);
2289 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002290}
2291
Aaron Ballman5d041be2013-06-04 02:07:14 +00002292/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
2293///
2294/// The syntax is:
2295/// \code
2296/// #pragma detect_mismatch("name", "value")
2297/// \endcode
2298/// Where 'name' and 'value' are quoted strings. The values are embedded in
2299/// the object file and passed along to the linker. If the linker detects a
2300/// mismatch in the object file's values for the given name, a LNK2038 error
2301/// is emitted. See MSDN for more details.
2302void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2303 PragmaIntroducerKind Introducer,
2304 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002305 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002306 PP.Lex(Tok);
2307 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002308 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002309 return;
2310 }
2311
2312 // Read the name to embed, which must be a string literal.
2313 std::string NameString;
2314 if (!PP.LexStringLiteral(Tok, NameString,
2315 "pragma detect_mismatch",
2316 /*MacroExpansion=*/true))
2317 return;
2318
2319 // Read the comma followed by a second string literal.
2320 std::string ValueString;
2321 if (Tok.isNot(tok::comma)) {
2322 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2323 return;
2324 }
2325
2326 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2327 /*MacroExpansion=*/true))
2328 return;
2329
2330 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002331 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002332 return;
2333 }
2334 PP.Lex(Tok); // Eat the r_paren.
2335
2336 if (Tok.isNot(tok::eod)) {
2337 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2338 return;
2339 }
2340
Reid Kleckner71966c92014-02-20 23:37:45 +00002341 // If the pragma is lexically sound, notify any interested PPCallbacks.
2342 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002343 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002344 ValueString);
2345
Nico Webercbbaeb12016-03-02 19:28:54 +00002346 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002347}
2348
Reid Kleckner002562a2013-05-06 21:02:12 +00002349/// \brief Handle the microsoft \#pragma comment extension.
2350///
2351/// The syntax is:
2352/// \code
2353/// #pragma comment(linker, "foo")
2354/// \endcode
2355/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2356/// "foo" is a string, which is fully macro expanded, and permits string
2357/// concatenation, embedded escape characters etc. See MSDN for more details.
2358void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2359 PragmaIntroducerKind Introducer,
2360 Token &Tok) {
2361 SourceLocation CommentLoc = Tok.getLocation();
2362 PP.Lex(Tok);
2363 if (Tok.isNot(tok::l_paren)) {
2364 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2365 return;
2366 }
2367
2368 // Read the identifier.
2369 PP.Lex(Tok);
2370 if (Tok.isNot(tok::identifier)) {
2371 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2372 return;
2373 }
2374
2375 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002376 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002377 PragmaMSCommentKind Kind =
2378 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2379 .Case("linker", PCK_Linker)
2380 .Case("lib", PCK_Lib)
2381 .Case("compiler", PCK_Compiler)
2382 .Case("exestr", PCK_ExeStr)
2383 .Case("user", PCK_User)
2384 .Default(PCK_Unknown);
2385 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002386 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2387 return;
2388 }
2389
Yunzhong Gao99efc032015-03-23 20:41:42 +00002390 // On PS4, issue a warning about any pragma comments other than
2391 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002392 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002393 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2394 << II->getName();
2395 return;
2396 }
2397
Reid Kleckner002562a2013-05-06 21:02:12 +00002398 // Read the optional string if present.
2399 PP.Lex(Tok);
2400 std::string ArgumentString;
2401 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2402 "pragma comment",
2403 /*MacroExpansion=*/true))
2404 return;
2405
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002406 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002407 // FIXME: If the kind is "compiler" warn if the string is present (it is
2408 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002409 // The MSDN docs say that "lib" and "linker" require a string and have a short
2410 // whitelist of linker options they support, but in practice MSVC doesn't
2411 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002412
2413 if (Tok.isNot(tok::r_paren)) {
2414 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2415 return;
2416 }
2417 PP.Lex(Tok); // eat the r_paren.
2418
2419 if (Tok.isNot(tok::eod)) {
2420 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2421 return;
2422 }
2423
Reid Kleckner71966c92014-02-20 23:37:45 +00002424 // If the pragma is lexically sound, notify any interested PPCallbacks.
2425 if (PP.getPPCallbacks())
2426 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2427
Nico Weber66220292016-03-02 17:28:48 +00002428 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002429}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002430
2431// #pragma clang optimize off
2432// #pragma clang optimize on
2433void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2434 PragmaIntroducerKind Introducer,
2435 Token &FirstToken) {
2436 Token Tok;
2437 PP.Lex(Tok);
2438 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002439 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002440 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002441 return;
2442 }
2443 if (Tok.isNot(tok::identifier)) {
2444 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2445 << PP.getSpelling(Tok);
2446 return;
2447 }
2448 const IdentifierInfo *II = Tok.getIdentifierInfo();
2449 // The only accepted values are 'on' or 'off'.
2450 bool IsOn = false;
2451 if (II->isStr("on")) {
2452 IsOn = true;
2453 } else if (!II->isStr("off")) {
2454 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2455 << PP.getSpelling(Tok);
2456 return;
2457 }
2458 PP.Lex(Tok);
2459
2460 if (Tok.isNot(tok::eod)) {
2461 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2462 << PP.getSpelling(Tok);
2463 return;
2464 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002465
2466 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2467}
2468
Adam Nemet60d32642017-04-04 21:18:36 +00002469namespace {
2470/// Used as the annotation value for tok::annot_pragma_fp.
2471struct TokFPAnnotValue {
2472 enum FlagKinds { Contract };
2473 enum FlagValues { On, Off, Fast };
2474
2475 FlagKinds FlagKind;
2476 FlagValues FlagValue;
2477};
2478} // end anonymous namespace
2479
2480void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2481 PragmaIntroducerKind Introducer,
2482 Token &Tok) {
2483 // fp
2484 Token PragmaName = Tok;
2485 SmallVector<Token, 1> TokenList;
2486
2487 PP.Lex(Tok);
2488 if (Tok.isNot(tok::identifier)) {
2489 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2490 << /*MissingOption=*/true << "";
2491 return;
2492 }
2493
2494 while (Tok.is(tok::identifier)) {
2495 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2496
2497 auto FlagKind =
2498 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2499 OptionInfo->getName())
2500 .Case("contract", TokFPAnnotValue::Contract)
2501 .Default(None);
2502 if (!FlagKind) {
2503 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2504 << /*MissingOption=*/false << OptionInfo;
2505 return;
2506 }
2507 PP.Lex(Tok);
2508
2509 // Read '('
2510 if (Tok.isNot(tok::l_paren)) {
2511 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2512 return;
2513 }
2514 PP.Lex(Tok);
2515
2516 if (Tok.isNot(tok::identifier)) {
2517 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2518 << PP.getSpelling(Tok) << OptionInfo->getName();
2519 return;
2520 }
2521 const IdentifierInfo *II = Tok.getIdentifierInfo();
2522
2523 auto FlagValue =
2524 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2525 II->getName())
2526 .Case("on", TokFPAnnotValue::On)
2527 .Case("off", TokFPAnnotValue::Off)
2528 .Case("fast", TokFPAnnotValue::Fast)
2529 .Default(llvm::None);
2530
2531 if (!FlagValue) {
2532 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2533 << PP.getSpelling(Tok) << OptionInfo->getName();
2534 return;
2535 }
2536 PP.Lex(Tok);
2537
2538 // Read ')'
2539 if (Tok.isNot(tok::r_paren)) {
2540 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2541 return;
2542 }
2543 PP.Lex(Tok);
2544
2545 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2546 TokFPAnnotValue{*FlagKind, *FlagValue};
2547 // Generate the loop hint token.
2548 Token FPTok;
2549 FPTok.startToken();
2550 FPTok.setKind(tok::annot_pragma_fp);
2551 FPTok.setLocation(PragmaName.getLocation());
2552 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2553 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2554 TokenList.push_back(FPTok);
2555 }
2556
2557 if (Tok.isNot(tok::eod)) {
2558 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2559 << "clang fp";
2560 return;
2561 }
2562
2563 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2564 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2565
2566 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2567 /*DisableMacroExpansion=*/false);
2568}
2569
2570void Parser::HandlePragmaFP() {
2571 assert(Tok.is(tok::annot_pragma_fp));
2572 auto *AnnotValue =
2573 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2574
2575 LangOptions::FPContractModeKind FPC;
2576 switch (AnnotValue->FlagValue) {
2577 case TokFPAnnotValue::On:
2578 FPC = LangOptions::FPC_On;
2579 break;
2580 case TokFPAnnotValue::Fast:
2581 FPC = LangOptions::FPC_Fast;
2582 break;
2583 case TokFPAnnotValue::Off:
2584 FPC = LangOptions::FPC_Off;
2585 break;
2586 }
2587
2588 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002589 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002590}
2591
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002592/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002593static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2594 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002595 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002596 SmallVector<Token, 1> ValueList;
2597 int OpenParens = ValueInParens ? 1 : 0;
2598 // Read constant expression.
2599 while (Tok.isNot(tok::eod)) {
2600 if (Tok.is(tok::l_paren))
2601 OpenParens++;
2602 else if (Tok.is(tok::r_paren)) {
2603 OpenParens--;
2604 if (OpenParens == 0 && ValueInParens)
2605 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002606 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002607
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002608 ValueList.push_back(Tok);
2609 PP.Lex(Tok);
2610 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002611
2612 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002613 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002614 if (Tok.isNot(tok::r_paren)) {
2615 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2616 return true;
2617 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002618 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002619 }
2620
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002621 Token EOFTok;
2622 EOFTok.startToken();
2623 EOFTok.setKind(tok::eof);
2624 EOFTok.setLocation(Tok.getLocation());
2625 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2626
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002627 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002628
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002629 Info.PragmaName = PragmaName;
2630 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002631 return false;
2632}
2633
Eli Bendersky06a40422014-06-06 20:31:48 +00002634/// \brief Handle the \#pragma clang loop directive.
2635/// #pragma clang 'loop' loop-hints
2636///
2637/// loop-hints:
2638/// loop-hint loop-hints[opt]
2639///
2640/// loop-hint:
2641/// 'vectorize' '(' loop-hint-keyword ')'
2642/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002643/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002644/// 'vectorize_width' '(' loop-hint-value ')'
2645/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002646/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002647///
2648/// loop-hint-keyword:
2649/// 'enable'
2650/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002651/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002652///
Mark Heffernan450c2382014-07-23 17:31:31 +00002653/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002654/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002655/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002656/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002657///
Eli Bendersky06a40422014-06-06 20:31:48 +00002658/// loop-hint-value:
2659/// constant-expression
2660///
2661/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2662/// try vectorizing the instructions of the loop it precedes. Specifying
2663/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2664/// interleaving multiple iterations of the loop it precedes. The width of the
2665/// vector instructions is specified by vectorize_width() and the number of
2666/// interleaved loop iterations is specified by interleave_count(). Specifying a
2667/// value of 1 effectively disables vectorization/interleaving, even if it is
2668/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2669/// only works on inner loops.
2670///
Eli Bendersky86483b32014-06-11 17:56:26 +00002671/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002672/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2673/// completely if the trip count is known at compile time and unroll partially
2674/// if the trip count is not known. Specifying unroll(full) is similar to
2675/// unroll(enable) but will unroll the loop only if the trip count is known at
2676/// compile time. Specifying unroll(disable) disables unrolling for the
2677/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2678/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002679void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2680 PragmaIntroducerKind Introducer,
2681 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002682 // Incoming token is "loop" from "#pragma clang loop".
2683 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002684 SmallVector<Token, 1> TokenList;
2685
2686 // Lex the optimization option and verify it is an identifier.
2687 PP.Lex(Tok);
2688 if (Tok.isNot(tok::identifier)) {
2689 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2690 << /*MissingOption=*/true << "";
2691 return;
2692 }
2693
2694 while (Tok.is(tok::identifier)) {
2695 Token Option = Tok;
2696 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2697
Eli Bendersky86483b32014-06-11 17:56:26 +00002698 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002699 .Case("vectorize", true)
2700 .Case("interleave", true)
2701 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002702 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002703 .Case("vectorize_width", true)
2704 .Case("interleave_count", true)
2705 .Case("unroll_count", true)
2706 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002707 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002708 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2709 << /*MissingOption=*/false << OptionInfo;
2710 return;
2711 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002712 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002713
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002714 // Read '('
2715 if (Tok.isNot(tok::l_paren)) {
2716 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002717 return;
2718 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002719 PP.Lex(Tok);
2720
2721 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2722 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2723 *Info))
2724 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002725
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002726 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002727 Token LoopHintTok;
2728 LoopHintTok.startToken();
2729 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002730 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002731 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002732 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2733 TokenList.push_back(LoopHintTok);
2734 }
2735
2736 if (Tok.isNot(tok::eod)) {
2737 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2738 << "clang loop";
2739 return;
2740 }
2741
David Blaikie2eabcc92016-02-09 18:52:09 +00002742 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2743 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002744
David Blaikie2eabcc92016-02-09 18:52:09 +00002745 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2746 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002747}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002748
2749/// \brief Handle the loop unroll optimization pragmas.
2750/// #pragma unroll
2751/// #pragma unroll unroll-hint-value
2752/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002753/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002754///
2755/// unroll-hint-value:
2756/// constant-expression
2757///
Mark Heffernanc888e412014-07-24 18:09:38 +00002758/// Loop unrolling hints can be specified with '#pragma unroll' or
2759/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2760/// contained in parentheses. With no argument the directive instructs llvm to
2761/// try to unroll the loop completely. A positive integer argument can be
2762/// specified to indicate the number of times the loop should be unrolled. To
2763/// maximize compatibility with other compilers the unroll count argument can be
2764/// specified with or without parentheses. Specifying, '#pragma nounroll'
2765/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002766void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2767 PragmaIntroducerKind Introducer,
2768 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002769 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2770 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002771 Token PragmaName = Tok;
2772 PP.Lex(Tok);
2773 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2774 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002775 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002776 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002777 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002778 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2779 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2780 << "nounroll";
2781 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002782 } else {
2783 // Unroll pragma with an argument: "#pragma unroll N" or
2784 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002785 // Read '(' if it exists.
2786 bool ValueInParens = Tok.is(tok::l_paren);
2787 if (ValueInParens)
2788 PP.Lex(Tok);
2789
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002790 Token Option;
2791 Option.startToken();
2792 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002793 return;
2794
2795 // In CUDA, the argument to '#pragma unroll' should not be contained in
2796 // parentheses.
2797 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002798 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002799 diag::warn_pragma_unroll_cuda_value_in_parens);
2800
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002801 if (Tok.isNot(tok::eod)) {
2802 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2803 << "unroll";
2804 return;
2805 }
2806 }
2807
2808 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002809 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002810 TokenArray[0].startToken();
2811 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2812 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002813 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002814 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002815 PP.EnterTokenStream(std::move(TokenArray), 1,
2816 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002817}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002818
2819/// \brief Handle the Microsoft \#pragma intrinsic extension.
2820///
2821/// The syntax is:
2822/// \code
2823/// #pragma intrinsic(memset)
2824/// #pragma intrinsic(strlen, memcpy)
2825/// \endcode
2826///
2827/// Pragma intrisic tells the compiler to use a builtin version of the
2828/// function. Clang does it anyway, so the pragma doesn't really do anything.
2829/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2830/// isn't an intrinsic in clang and suggest to include intrin.h.
2831void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2832 PragmaIntroducerKind Introducer,
2833 Token &Tok) {
2834 PP.Lex(Tok);
2835
2836 if (Tok.isNot(tok::l_paren)) {
2837 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2838 << "intrinsic";
2839 return;
2840 }
2841 PP.Lex(Tok);
2842
2843 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2844
2845 while (Tok.is(tok::identifier)) {
2846 IdentifierInfo *II = Tok.getIdentifierInfo();
2847 if (!II->getBuiltinID())
2848 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2849 << II << SuggestIntrinH;
2850
2851 PP.Lex(Tok);
2852 if (Tok.isNot(tok::comma))
2853 break;
2854 PP.Lex(Tok);
2855 }
2856
2857 if (Tok.isNot(tok::r_paren)) {
2858 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2859 << "intrinsic";
2860 return;
2861 }
2862 PP.Lex(Tok);
2863
2864 if (Tok.isNot(tok::eod))
2865 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2866 << "intrinsic";
2867}
Justin Lebar67a78a62016-10-08 22:15:58 +00002868void PragmaForceCUDAHostDeviceHandler::HandlePragma(
2869 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
2870 Token FirstTok = Tok;
2871
2872 PP.Lex(Tok);
2873 IdentifierInfo *Info = Tok.getIdentifierInfo();
2874 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
2875 PP.Diag(FirstTok.getLocation(),
2876 diag::warn_pragma_force_cuda_host_device_bad_arg);
2877 return;
2878 }
2879
2880 if (Info->isStr("begin"))
2881 Actions.PushForceCUDAHostDevice();
2882 else if (!Actions.PopForceCUDAHostDevice())
2883 PP.Diag(FirstTok.getLocation(),
2884 diag::err_pragma_cannot_end_force_cuda_host_device);
2885
2886 PP.Lex(Tok);
2887 if (!Tok.is(tok::eod))
2888 PP.Diag(FirstTok.getLocation(),
2889 diag::warn_pragma_force_cuda_host_device_bad_arg);
2890}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00002891
2892/// \brief Handle the #pragma clang attribute directive.
2893///
2894/// The syntax is:
2895/// \code
2896/// #pragma clang attribute push(attribute, subject-set)
2897/// #pragma clang attribute pop
2898/// \endcode
2899///
2900/// The subject-set clause defines the set of declarations which receive the
2901/// attribute. Its exact syntax is described in the LanguageExtensions document
2902/// in Clang's documentation.
2903///
2904/// This directive instructs the compiler to begin/finish applying the specified
2905/// attribute to the set of attribute-specific declarations in the active range
2906/// of the pragma.
2907void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
2908 PragmaIntroducerKind Introducer,
2909 Token &FirstToken) {
2910 Token Tok;
2911 PP.Lex(Tok);
2912 auto *Info = new (PP.getPreprocessorAllocator())
2913 PragmaAttributeInfo(AttributesForPragmaAttribute);
2914
2915 // Parse the 'push' or 'pop'.
2916 if (Tok.isNot(tok::identifier)) {
2917 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
2918 return;
2919 }
2920 const auto *II = Tok.getIdentifierInfo();
2921 if (II->isStr("push"))
2922 Info->Action = PragmaAttributeInfo::Push;
2923 else if (II->isStr("pop"))
2924 Info->Action = PragmaAttributeInfo::Pop;
2925 else {
2926 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
2927 << PP.getSpelling(Tok);
2928 return;
2929 }
2930 PP.Lex(Tok);
2931
2932 // Parse the actual attribute.
2933 if (Info->Action == PragmaAttributeInfo::Push) {
2934 if (Tok.isNot(tok::l_paren)) {
2935 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2936 return;
2937 }
2938 PP.Lex(Tok);
2939
2940 // Lex the attribute tokens.
2941 SmallVector<Token, 16> AttributeTokens;
2942 int OpenParens = 1;
2943 while (Tok.isNot(tok::eod)) {
2944 if (Tok.is(tok::l_paren))
2945 OpenParens++;
2946 else if (Tok.is(tok::r_paren)) {
2947 OpenParens--;
2948 if (OpenParens == 0)
2949 break;
2950 }
2951
2952 AttributeTokens.push_back(Tok);
2953 PP.Lex(Tok);
2954 }
2955
2956 if (AttributeTokens.empty()) {
2957 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
2958 return;
2959 }
2960 if (Tok.isNot(tok::r_paren)) {
2961 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2962 return;
2963 }
2964 SourceLocation EndLoc = Tok.getLocation();
2965 PP.Lex(Tok);
2966
2967 // Terminate the attribute for parsing.
2968 Token EOFTok;
2969 EOFTok.startToken();
2970 EOFTok.setKind(tok::eof);
2971 EOFTok.setLocation(EndLoc);
2972 AttributeTokens.push_back(EOFTok);
2973
2974 Info->Tokens =
2975 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
2976 }
2977
2978 if (Tok.isNot(tok::eod))
2979 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2980 << "clang attribute";
2981
2982 // Generate the annotated pragma token.
2983 auto TokenArray = llvm::make_unique<Token[]>(1);
2984 TokenArray[0].startToken();
2985 TokenArray[0].setKind(tok::annot_pragma_attribute);
2986 TokenArray[0].setLocation(FirstToken.getLocation());
2987 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
2988 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2989 PP.EnterTokenStream(std::move(TokenArray), 1,
2990 /*DisableMacroExpansion=*/false);
2991}