blob: 198d5c6e9cb0387a2ed07a0cf4ddfcf6a5269d20 [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());
Alex Lorenz45b40142017-07-28 14:41:21 +0000425 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000426 ExprResult Alignment;
427 if (Info->Alignment.is(tok::numeric_constant)) {
428 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000429 if (Alignment.isInvalid()) {
430 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000431 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000432 }
Eli Friedman68be1642012-10-04 02:36:51 +0000433 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000434 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
435 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000436 // Consume the token after processing the pragma to enable pragma-specific
437 // #include warnings.
438 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000439}
440
Eli Friedman68be1642012-10-04 02:36:51 +0000441void Parser::HandlePragmaMSStruct() {
442 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000443 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
444 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000445 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000446 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000447}
448
449void Parser::HandlePragmaAlign() {
450 assert(Tok.is(tok::annot_pragma_align));
451 Sema::PragmaOptionsAlignKind Kind =
452 static_cast<Sema::PragmaOptionsAlignKind>(
453 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000454 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000455 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
456}
457
Richard Smithba3a4f92016-01-12 21:59:26 +0000458void Parser::HandlePragmaDump() {
459 assert(Tok.is(tok::annot_pragma_dump));
460 IdentifierInfo *II =
461 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
462 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000463 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000464}
465
Eli Friedman68be1642012-10-04 02:36:51 +0000466void Parser::HandlePragmaWeak() {
467 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000468 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000469 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
470 Tok.getLocation());
471 ConsumeToken(); // The weak name.
472}
473
474void Parser::HandlePragmaWeakAlias() {
475 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000476 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000477 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
478 SourceLocation WeakNameLoc = Tok.getLocation();
479 ConsumeToken();
480 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
481 SourceLocation AliasNameLoc = Tok.getLocation();
482 ConsumeToken();
483 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
484 WeakNameLoc, AliasNameLoc);
485
486}
487
488void Parser::HandlePragmaRedefineExtname() {
489 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000490 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000491 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
492 SourceLocation RedefNameLoc = Tok.getLocation();
493 ConsumeToken();
494 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
495 SourceLocation AliasNameLoc = Tok.getLocation();
496 ConsumeToken();
497 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
498 RedefNameLoc, AliasNameLoc);
499}
500
501void Parser::HandlePragmaFPContract() {
502 assert(Tok.is(tok::annot_pragma_fp_contract));
503 tok::OnOffSwitch OOS =
504 static_cast<tok::OnOffSwitch>(
505 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000506
507 LangOptions::FPContractModeKind FPC;
508 switch (OOS) {
509 case tok::OOS_ON:
510 FPC = LangOptions::FPC_On;
511 break;
512 case tok::OOS_OFF:
513 FPC = LangOptions::FPC_Off;
514 break;
515 case tok::OOS_DEFAULT:
516 FPC = getLangOpts().getDefaultFPContractMode();
517 break;
518 }
519
520 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000521 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000522}
523
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000524StmtResult Parser::HandlePragmaCaptured()
525{
526 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000527 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000528
529 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000530 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000531 return StmtError();
532 }
533
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000534 SourceLocation Loc = Tok.getLocation();
535
Momchil Velikov57c681f2017-08-10 15:43:06 +0000536 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
537 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000538 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
539 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000540
541 StmtResult R = ParseCompoundStatement();
542 CapturedRegionScope.Exit();
543
544 if (R.isInvalid()) {
545 Actions.ActOnCapturedRegionError();
546 return StmtError();
547 }
548
549 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000550}
551
Eli Friedman68be1642012-10-04 02:36:51 +0000552namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000553 enum OpenCLExtState : char {
554 Disable, Enable, Begin, End
555 };
556 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000557}
558
559void Parser::HandlePragmaOpenCLExtension() {
560 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000561 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
562 auto State = Data->second;
563 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000564 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000565 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000566
Yaxun Liu5b746652016-12-18 05:18:55 +0000567 auto &Opt = Actions.getOpenCLOptions();
568 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000569 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
570 // overriding all previously issued extension directives, but only if the
571 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000572 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000573 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000574 Opt.disableAll();
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000575 Opt.enableSupportedCore(getLangOpts().OpenCLVersion);
576 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000577 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000578 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000579 } else if (State == Begin) {
580 if (!Opt.isKnown(Name) ||
581 !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
582 Opt.support(Name);
583 }
584 Actions.setCurrentOpenCLExtension(Name);
585 } else if (State == End) {
586 if (Name != Actions.getCurrentOpenCLExtension())
587 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
588 Actions.setCurrentOpenCLExtension("");
589 } else if (!Opt.isKnown(Name))
590 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
591 else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
592 Opt.enable(Name, State == Enable);
593 else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
594 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
595 else
596 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000597}
598
David Majnemer4bb09802014-02-10 19:50:15 +0000599void Parser::HandlePragmaMSPointersToMembers() {
600 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000601 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
602 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000603 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000604 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000605 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
606}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000607
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000608void Parser::HandlePragmaMSVtorDisp() {
609 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
610 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000611 Sema::PragmaMsStackAction Action =
612 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000613 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000614 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000615 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000616}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000617
Warren Huntc3b18962014-04-08 22:30:47 +0000618void Parser::HandlePragmaMSPragma() {
619 assert(Tok.is(tok::annot_pragma_ms_pragma));
620 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000621 auto TheTokens =
622 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
623 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000624 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000625 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000626 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000627 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000628
Warren Huntc3b18962014-04-08 22:30:47 +0000629 // Figure out which #pragma we're dealing with. The switch has no default
630 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000631 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000632 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
633 .Case("data_seg", &Parser::HandlePragmaMSSegment)
634 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
635 .Case("const_seg", &Parser::HandlePragmaMSSegment)
636 .Case("code_seg", &Parser::HandlePragmaMSSegment)
637 .Case("section", &Parser::HandlePragmaMSSection)
638 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000639
640 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
641 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
642 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000643 while (Tok.isNot(tok::eof))
644 PP.Lex(Tok);
645 PP.Lex(Tok);
646 }
647}
648
Reid Kleckner722b1df2014-07-18 00:13:16 +0000649bool Parser::HandlePragmaMSSection(StringRef PragmaName,
650 SourceLocation PragmaLocation) {
651 if (Tok.isNot(tok::l_paren)) {
652 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
653 return false;
654 }
Warren Huntc3b18962014-04-08 22:30:47 +0000655 PP.Lex(Tok); // (
656 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000657 if (Tok.isNot(tok::string_literal)) {
658 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
659 << PragmaName;
660 return false;
661 }
662 ExprResult StringResult = ParseStringLiteralExpression();
663 if (StringResult.isInvalid())
664 return false; // Already diagnosed.
665 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
666 if (SegmentName->getCharByteWidth() != 1) {
667 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
668 << PragmaName;
669 return false;
670 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000671 int SectionFlags = ASTContext::PSF_Read;
672 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000673 while (Tok.is(tok::comma)) {
674 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000675 // Ignore "long" and "short".
676 // They are undocumented, but widely used, section attributes which appear
677 // to do nothing.
678 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
679 PP.Lex(Tok); // long/short
680 continue;
681 }
682
Reid Kleckner722b1df2014-07-18 00:13:16 +0000683 if (!Tok.isAnyIdentifier()) {
684 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
685 << PragmaName;
686 return false;
687 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000688 ASTContext::PragmaSectionFlag Flag =
689 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000690 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000691 .Case("read", ASTContext::PSF_Read)
692 .Case("write", ASTContext::PSF_Write)
693 .Case("execute", ASTContext::PSF_Execute)
694 .Case("shared", ASTContext::PSF_Invalid)
695 .Case("nopage", ASTContext::PSF_Invalid)
696 .Case("nocache", ASTContext::PSF_Invalid)
697 .Case("discard", ASTContext::PSF_Invalid)
698 .Case("remove", ASTContext::PSF_Invalid)
699 .Default(ASTContext::PSF_None);
700 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
701 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000702 ? diag::warn_pragma_invalid_specific_action
703 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000704 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000705 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000706 }
707 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000708 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000709 PP.Lex(Tok); // Identifier
710 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000711 // If no section attributes are specified, the section will be marked as
712 // read/write.
713 if (SectionFlagsAreDefault)
714 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000715 if (Tok.isNot(tok::r_paren)) {
716 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
717 return false;
718 }
Warren Huntc3b18962014-04-08 22:30:47 +0000719 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000720 if (Tok.isNot(tok::eof)) {
721 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
722 << PragmaName;
723 return false;
724 }
Warren Huntc3b18962014-04-08 22:30:47 +0000725 PP.Lex(Tok); // eof
726 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000727 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000728}
729
Reid Kleckner722b1df2014-07-18 00:13:16 +0000730bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
731 SourceLocation PragmaLocation) {
732 if (Tok.isNot(tok::l_paren)) {
733 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
734 return false;
735 }
Warren Huntc3b18962014-04-08 22:30:47 +0000736 PP.Lex(Tok); // (
737 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000738 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000739 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000740 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000741 if (PushPop == "push")
742 Action = Sema::PSK_Push;
743 else if (PushPop == "pop")
744 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000745 else {
746 PP.Diag(PragmaLocation,
747 diag::warn_pragma_expected_section_push_pop_or_name)
748 << PragmaName;
749 return false;
750 }
Warren Huntc3b18962014-04-08 22:30:47 +0000751 if (Action != Sema::PSK_Reset) {
752 PP.Lex(Tok); // push | pop
753 if (Tok.is(tok::comma)) {
754 PP.Lex(Tok); // ,
755 // If we've got a comma, we either need a label or a string.
756 if (Tok.isAnyIdentifier()) {
757 SlotLabel = Tok.getIdentifierInfo()->getName();
758 PP.Lex(Tok); // identifier
759 if (Tok.is(tok::comma))
760 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000761 else if (Tok.isNot(tok::r_paren)) {
762 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
763 << PragmaName;
764 return false;
765 }
Warren Huntc3b18962014-04-08 22:30:47 +0000766 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000767 } else if (Tok.isNot(tok::r_paren)) {
768 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
769 return false;
770 }
Warren Huntc3b18962014-04-08 22:30:47 +0000771 }
772 }
773 // Grab the string literal for our section name.
774 StringLiteral *SegmentName = nullptr;
775 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000776 if (Tok.isNot(tok::string_literal)) {
777 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000778 diag::warn_pragma_expected_section_name :
779 diag::warn_pragma_expected_section_label_or_name :
780 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000781 PP.Diag(PragmaLocation, DiagID) << PragmaName;
782 return false;
783 }
784 ExprResult StringResult = ParseStringLiteralExpression();
785 if (StringResult.isInvalid())
786 return false; // Already diagnosed.
787 SegmentName = cast<StringLiteral>(StringResult.get());
788 if (SegmentName->getCharByteWidth() != 1) {
789 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
790 << PragmaName;
791 return false;
792 }
Warren Huntc3b18962014-04-08 22:30:47 +0000793 // Setting section "" has no effect
794 if (SegmentName->getLength())
795 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
796 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000797 if (Tok.isNot(tok::r_paren)) {
798 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
799 return false;
800 }
Warren Huntc3b18962014-04-08 22:30:47 +0000801 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000802 if (Tok.isNot(tok::eof)) {
803 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
804 << PragmaName;
805 return false;
806 }
Warren Huntc3b18962014-04-08 22:30:47 +0000807 PP.Lex(Tok); // eof
808 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
809 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000810 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000811}
812
Reid Kleckner1a711b12014-07-22 00:53:05 +0000813// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000814bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
815 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000816 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
817 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
818 return false;
819 }
820
Reid Kleckner1a711b12014-07-22 00:53:05 +0000821 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
822 PragmaName))
823 return false;
824
825 // Parse either the known section names or the string section name.
826 StringLiteral *SegmentName = nullptr;
827 if (Tok.isAnyIdentifier()) {
828 auto *II = Tok.getIdentifierInfo();
829 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
830 .Case("compiler", "\".CRT$XCC\"")
831 .Case("lib", "\".CRT$XCL\"")
832 .Case("user", "\".CRT$XCU\"")
833 .Default("");
834
835 if (!Section.empty()) {
836 // Pretend the user wrote the appropriate string literal here.
837 Token Toks[1];
838 Toks[0].startToken();
839 Toks[0].setKind(tok::string_literal);
840 Toks[0].setLocation(Tok.getLocation());
841 Toks[0].setLiteralData(Section.data());
842 Toks[0].setLength(Section.size());
843 SegmentName =
844 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
845 PP.Lex(Tok);
846 }
847 } else if (Tok.is(tok::string_literal)) {
848 ExprResult StringResult = ParseStringLiteralExpression();
849 if (StringResult.isInvalid())
850 return false;
851 SegmentName = cast<StringLiteral>(StringResult.get());
852 if (SegmentName->getCharByteWidth() != 1) {
853 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
854 << PragmaName;
855 return false;
856 }
857 // FIXME: Add support for the '[, func-name]' part of the pragma.
858 }
859
860 if (!SegmentName) {
861 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
862 return false;
863 }
864
865 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
866 PragmaName) ||
867 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
868 PragmaName))
869 return false;
870
871 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
872 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000873}
874
Benjamin Kramere003ca22015-10-28 13:54:16 +0000875namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +0000876struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000877 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000878 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +0000879 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +0000880};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000881} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +0000882
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000883static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
884 std::string PragmaString;
885 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
886 PragmaString = "clang loop ";
887 PragmaString += Option.getIdentifierInfo()->getName();
888 } else {
889 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
890 "Unexpected pragma name");
891 PragmaString = "unroll";
892 }
893 return PragmaString;
894}
895
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000896bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000897 assert(Tok.is(tok::annot_pragma_loop_hint));
898 PragmaLoopHintInfo *Info =
899 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
900
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000901 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
902 Hint.PragmaNameLoc = IdentifierLoc::create(
903 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000904
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000905 // It is possible that the loop hint has no option identifier, such as
906 // #pragma unroll(4).
907 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
908 ? Info->Option.getIdentifierInfo()
909 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000910 Hint.OptionLoc = IdentifierLoc::create(
911 Actions.Context, Info->Option.getLocation(), OptionInfo);
912
David Blaikie2eabcc92016-02-09 18:52:09 +0000913 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000914
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000915 // Return a valid hint if pragma unroll or nounroll were specified
916 // without an argument.
917 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
918 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
David Blaikie2eabcc92016-02-09 18:52:09 +0000919 if (Toks.empty() && (PragmaUnroll || PragmaNoUnroll)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000920 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000921 Hint.Range = Info->PragmaName.getLocation();
922 return true;
923 }
924
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000925 // The constant expression is always followed by an eof token, which increases
926 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +0000927 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000928 "PragmaLoopHintInfo::Toks must contain at least one token.");
929
930 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +0000931 bool OptionUnroll = false;
Adam Nemet2de463e2016-06-14 12:04:26 +0000932 bool OptionDistribute = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000933 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +0000934 if (OptionInfo) { // Pragma Unroll does not specify an option.
935 OptionUnroll = OptionInfo->isStr("unroll");
Adam Nemet2de463e2016-06-14 12:04:26 +0000936 OptionDistribute = OptionInfo->isStr("distribute");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000937 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
938 .Case("vectorize", true)
939 .Case("interleave", true)
Adam Nemet2de463e2016-06-14 12:04:26 +0000940 .Default(false) ||
941 OptionUnroll || OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000942 }
943
Adam Nemet2de463e2016-06-14 12:04:26 +0000944 bool AssumeSafetyArg = !OptionUnroll && !OptionDistribute;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000945 // Verify loop hint has an argument.
946 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000947 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000948 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
Adam Nemet2de463e2016-06-14 12:04:26 +0000949 << /*StateArgument=*/StateOption << /*FullKeyword=*/OptionUnroll
950 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000951 return false;
952 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000953
954 // Validate the argument.
955 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +0000956 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000957 SourceLocation StateLoc = Toks[0].getLocation();
958 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +0000959
960 bool Valid = StateInfo &&
961 llvm::StringSwitch<bool>(StateInfo->getName())
962 .Cases("enable", "disable", true)
963 .Case("full", OptionUnroll)
Adam Nemet2de463e2016-06-14 12:04:26 +0000964 .Case("assume_safety", AssumeSafetyArg)
Adam Nemet50de4e82016-04-19 22:17:45 +0000965 .Default(false);
966 if (!Valid) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000967 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
Adam Nemet2de463e2016-06-14 12:04:26 +0000968 << /*FullKeyword=*/OptionUnroll
969 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000970 return false;
971 }
David Blaikie2eabcc92016-02-09 18:52:09 +0000972 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000973 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
974 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000975 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
976 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000977 // Enter constant expression including eof terminator into token stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000978 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +0000979 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000980
981 ExprResult R = ParseConstantExpression();
982
983 // Tokens following an error in an ill-formed constant expression will
984 // remain in the token stream and must be removed.
985 if (Tok.isNot(tok::eof)) {
986 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
987 << PragmaLoopHintString(Info->PragmaName, Info->Option);
988 while (Tok.isNot(tok::eof))
989 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000990 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000991
992 ConsumeToken(); // Consume the constant expression eof terminator.
993
994 if (R.isInvalid() ||
995 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
996 return false;
997
998 // Argument is a constant expression with an integer type.
999 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001000 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001001
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001002 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001003 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001004 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001005}
1006
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001007namespace {
1008struct PragmaAttributeInfo {
1009 enum ActionType { Push, Pop };
1010 ParsedAttributes &Attributes;
1011 ActionType Action;
1012 ArrayRef<Token> Tokens;
1013
1014 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1015};
1016
1017#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1018
1019} // end anonymous namespace
1020
1021static StringRef getIdentifier(const Token &Tok) {
1022 if (Tok.is(tok::identifier))
1023 return Tok.getIdentifierInfo()->getName();
1024 const char *S = tok::getKeywordSpelling(Tok.getKind());
1025 if (!S)
1026 return "";
1027 return S;
1028}
1029
1030static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1031 using namespace attr;
1032 switch (Rule) {
1033#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1034 case Value: \
1035 return IsAbstract;
1036#include "clang/Basic/AttrSubMatchRulesList.inc"
1037 }
1038 llvm_unreachable("Invalid attribute subject match rule");
1039 return false;
1040}
1041
1042static void diagnoseExpectedAttributeSubjectSubRule(
1043 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1044 SourceLocation SubRuleLoc) {
1045 auto Diagnostic =
1046 PRef.Diag(SubRuleLoc,
1047 diag::err_pragma_attribute_expected_subject_sub_identifier)
1048 << PrimaryRuleName;
1049 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1050 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1051 else
1052 Diagnostic << /*SubRulesSupported=*/0;
1053}
1054
1055static void diagnoseUnknownAttributeSubjectSubRule(
1056 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1057 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1058
1059 auto Diagnostic =
1060 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1061 << SubRuleName << PrimaryRuleName;
1062 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1063 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1064 else
1065 Diagnostic << /*SubRulesSupported=*/0;
1066}
1067
1068bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1069 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1070 SourceLocation &LastMatchRuleEndLoc) {
1071 bool IsAny = false;
1072 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1073 if (getIdentifier(Tok) == "any") {
1074 AnyLoc = ConsumeToken();
1075 IsAny = true;
1076 if (AnyParens.expectAndConsume())
1077 return true;
1078 }
1079
1080 do {
1081 // Parse the subject matcher rule.
1082 StringRef Name = getIdentifier(Tok);
1083 if (Name.empty()) {
1084 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1085 return true;
1086 }
1087 std::pair<Optional<attr::SubjectMatchRule>,
1088 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1089 Rule = isAttributeSubjectMatchRule(Name);
1090 if (!Rule.first) {
1091 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1092 return true;
1093 }
1094 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1095 SourceLocation RuleLoc = ConsumeToken();
1096
1097 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1098 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1099 if (Parens.expectAndConsume())
1100 return true;
1101 } else if (Parens.consumeOpen()) {
1102 if (!SubjectMatchRules
1103 .insert(
1104 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1105 .second)
1106 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1107 << Name
1108 << FixItHint::CreateRemoval(SourceRange(
1109 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1110 LastMatchRuleEndLoc = RuleLoc;
1111 continue;
1112 }
1113
1114 // Parse the sub-rules.
1115 StringRef SubRuleName = getIdentifier(Tok);
1116 if (SubRuleName.empty()) {
1117 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1118 Tok.getLocation());
1119 return true;
1120 }
1121 attr::SubjectMatchRule SubRule;
1122 if (SubRuleName == "unless") {
1123 SourceLocation SubRuleLoc = ConsumeToken();
1124 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1125 if (Parens.expectAndConsume())
1126 return true;
1127 SubRuleName = getIdentifier(Tok);
1128 if (SubRuleName.empty()) {
1129 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1130 SubRuleLoc);
1131 return true;
1132 }
1133 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1134 if (!SubRuleOrNone) {
1135 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1136 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1137 SubRuleUnlessName, SubRuleLoc);
1138 return true;
1139 }
1140 SubRule = *SubRuleOrNone;
1141 ConsumeToken();
1142 if (Parens.consumeClose())
1143 return true;
1144 } else {
1145 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1146 if (!SubRuleOrNone) {
1147 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1148 SubRuleName, Tok.getLocation());
1149 return true;
1150 }
1151 SubRule = *SubRuleOrNone;
1152 ConsumeToken();
1153 }
1154 SourceLocation RuleEndLoc = Tok.getLocation();
1155 LastMatchRuleEndLoc = RuleEndLoc;
1156 if (Parens.consumeClose())
1157 return true;
1158 if (!SubjectMatchRules
1159 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1160 .second) {
1161 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1162 << attr::getSubjectMatchRuleSpelling(SubRule)
1163 << FixItHint::CreateRemoval(SourceRange(
1164 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1165 continue;
1166 }
1167 } while (IsAny && TryConsumeToken(tok::comma));
1168
1169 if (IsAny)
1170 if (AnyParens.consumeClose())
1171 return true;
1172
1173 return false;
1174}
1175
1176namespace {
1177
1178/// Describes the stage at which attribute subject rule parsing was interruped.
1179enum class MissingAttributeSubjectRulesRecoveryPoint {
1180 Comma,
1181 ApplyTo,
1182 Equals,
1183 Any,
1184 None,
1185};
1186
1187MissingAttributeSubjectRulesRecoveryPoint
1188getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1189 if (const auto *II = Tok.getIdentifierInfo()) {
1190 if (II->isStr("apply_to"))
1191 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1192 if (II->isStr("any"))
1193 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1194 }
1195 if (Tok.is(tok::equal))
1196 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1197 return MissingAttributeSubjectRulesRecoveryPoint::None;
1198}
1199
1200/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1201/// suggests the possible attribute subject rules in a fix-it together with
1202/// any other missing tokens.
1203DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1204 unsigned DiagID, AttributeList &Attribute,
1205 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1206 SourceLocation Loc = PRef.getEndOfPreviousToken();
1207 if (Loc.isInvalid())
1208 Loc = PRef.getCurToken().getLocation();
1209 auto Diagnostic = PRef.Diag(Loc, DiagID);
1210 std::string FixIt;
1211 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1212 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1213 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1214 FixIt = ", ";
1215 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1216 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1217 FixIt += "apply_to";
1218 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1219 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1220 FixIt += " = ";
1221 SourceRange FixItRange(Loc);
1222 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1223 // Gather the subject match rules that are supported by the attribute.
1224 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1225 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1226 if (SubjectMatchRuleSet.empty()) {
1227 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1228 // placeholders will be supported by the fix-its.
1229 return Diagnostic;
1230 }
1231 FixIt += "any(";
1232 bool NeedsComma = false;
1233 for (const auto &I : SubjectMatchRuleSet) {
1234 // Ensure that the missing rule is reported in the fix-it only when it's
1235 // supported in the current language mode.
1236 if (!I.second)
1237 continue;
1238 if (NeedsComma)
1239 FixIt += ", ";
1240 else
1241 NeedsComma = true;
1242 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1243 }
1244 FixIt += ")";
1245 // Check if we need to remove the range
1246 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1247 FixItRange.setEnd(PRef.getCurToken().getLocation());
1248 }
1249 if (FixItRange.getBegin() == FixItRange.getEnd())
1250 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1251 else
1252 Diagnostic << FixItHint::CreateReplacement(
1253 CharSourceRange::getCharRange(FixItRange), FixIt);
1254 return Diagnostic;
1255}
1256
1257} // end anonymous namespace
1258
1259void Parser::HandlePragmaAttribute() {
1260 assert(Tok.is(tok::annot_pragma_attribute) &&
1261 "Expected #pragma attribute annotation token");
1262 SourceLocation PragmaLoc = Tok.getLocation();
1263 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1264 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001265 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001266 Actions.ActOnPragmaAttributePop(PragmaLoc);
1267 return;
1268 }
1269 // Parse the actual attribute with its arguments.
1270 assert(Info->Action == PragmaAttributeInfo::Push &&
1271 "Unexpected #pragma attribute command");
1272 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001273 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001274
1275 ParsedAttributes &Attrs = Info->Attributes;
1276 Attrs.clearListOnly();
1277
1278 auto SkipToEnd = [this]() {
1279 SkipUntil(tok::eof, StopBeforeMatch);
1280 ConsumeToken();
1281 };
1282
1283 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1284 // Parse the CXX11 style attribute.
1285 ParseCXX11AttributeSpecifier(Attrs);
1286 } else if (Tok.is(tok::kw___attribute)) {
1287 ConsumeToken();
1288 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1289 "attribute"))
1290 return SkipToEnd();
1291 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1292 return SkipToEnd();
1293
1294 if (Tok.isNot(tok::identifier)) {
1295 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1296 SkipToEnd();
1297 return;
1298 }
1299 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1300 SourceLocation AttrNameLoc = ConsumeToken();
1301
1302 if (Tok.isNot(tok::l_paren))
1303 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1304 AttributeList::AS_GNU);
1305 else
1306 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1307 /*ScopeName=*/nullptr,
1308 /*ScopeLoc=*/SourceLocation(),
1309 AttributeList::AS_GNU,
1310 /*Declarator=*/nullptr);
1311
1312 if (ExpectAndConsume(tok::r_paren))
1313 return SkipToEnd();
1314 if (ExpectAndConsume(tok::r_paren))
1315 return SkipToEnd();
1316 } else if (Tok.is(tok::kw___declspec)) {
1317 ParseMicrosoftDeclSpecs(Attrs);
1318 } else {
1319 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1320 if (Tok.getIdentifierInfo()) {
1321 // If we suspect that this is an attribute suggest the use of
1322 // '__attribute__'.
1323 if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1324 AttributeList::AS_GNU) !=
1325 AttributeList::UnknownAttribute) {
1326 SourceLocation InsertStartLoc = Tok.getLocation();
1327 ConsumeToken();
1328 if (Tok.is(tok::l_paren)) {
1329 ConsumeAnyToken();
1330 SkipUntil(tok::r_paren, StopBeforeMatch);
1331 if (Tok.isNot(tok::r_paren))
1332 return SkipToEnd();
1333 }
1334 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1335 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1336 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1337 }
1338 }
1339 SkipToEnd();
1340 return;
1341 }
1342
1343 if (!Attrs.getList() || Attrs.getList()->isInvalid()) {
1344 SkipToEnd();
1345 return;
1346 }
1347
1348 // Ensure that we don't have more than one attribute.
1349 if (Attrs.getList()->getNext()) {
1350 SourceLocation Loc = Attrs.getList()->getNext()->getLoc();
1351 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1352 SkipToEnd();
1353 return;
1354 }
1355
1356 if (!Attrs.getList()->isSupportedByPragmaAttribute()) {
1357 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1358 << Attrs.getList()->getName();
1359 SkipToEnd();
1360 return;
1361 }
1362 AttributeList &Attribute = *Attrs.getList();
1363
1364 // Parse the subject-list.
1365 if (!TryConsumeToken(tok::comma)) {
1366 createExpectedAttributeSubjectRulesTokenDiagnostic(
1367 diag::err_expected, Attribute,
1368 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1369 << tok::comma;
1370 SkipToEnd();
1371 return;
1372 }
1373
1374 if (Tok.isNot(tok::identifier)) {
1375 createExpectedAttributeSubjectRulesTokenDiagnostic(
1376 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1377 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1378 SkipToEnd();
1379 return;
1380 }
1381 const IdentifierInfo *II = Tok.getIdentifierInfo();
1382 if (!II->isStr("apply_to")) {
1383 createExpectedAttributeSubjectRulesTokenDiagnostic(
1384 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1385 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1386 SkipToEnd();
1387 return;
1388 }
1389 ConsumeToken();
1390
1391 if (!TryConsumeToken(tok::equal)) {
1392 createExpectedAttributeSubjectRulesTokenDiagnostic(
1393 diag::err_expected, Attribute,
1394 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1395 << tok::equal;
1396 SkipToEnd();
1397 return;
1398 }
1399
1400 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1401 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1402 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1403 LastMatchRuleEndLoc)) {
1404 SkipToEnd();
1405 return;
1406 }
1407
1408 // Tokens following an ill-formed attribute will remain in the token stream
1409 // and must be removed.
1410 if (Tok.isNot(tok::eof)) {
1411 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1412 SkipToEnd();
1413 return;
1414 }
1415
1416 // Consume the eof terminator token.
1417 ConsumeToken();
1418
1419 Actions.ActOnPragmaAttributePush(Attribute, PragmaLoc,
1420 std::move(SubjectMatchRules));
1421}
1422
Eli Bendersky06a40422014-06-06 20:31:48 +00001423// #pragma GCC visibility comes in two variants:
1424// 'push' '(' [visibility] ')'
1425// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001426void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1427 PragmaIntroducerKind Introducer,
1428 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001429 SourceLocation VisLoc = VisTok.getLocation();
1430
1431 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001432 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001433
1434 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1435
Eli Friedman570024a2010-08-05 06:57:20 +00001436 const IdentifierInfo *VisType;
1437 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001438 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001439 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001440 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001441 if (Tok.isNot(tok::l_paren)) {
1442 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1443 << "visibility";
1444 return;
1445 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001446 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001447 VisType = Tok.getIdentifierInfo();
1448 if (!VisType) {
1449 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1450 << "visibility";
1451 return;
1452 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001453 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001454 if (Tok.isNot(tok::r_paren)) {
1455 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1456 << "visibility";
1457 return;
1458 }
1459 } else {
1460 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1461 << "visibility";
1462 return;
1463 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001464 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001465 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001466 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001467 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1468 << "visibility";
1469 return;
1470 }
1471
David Blaikie2eabcc92016-02-09 18:52:09 +00001472 auto Toks = llvm::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001473 Toks[0].startToken();
1474 Toks[0].setKind(tok::annot_pragma_vis);
1475 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001476 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001477 Toks[0].setAnnotationValue(
1478 const_cast<void*>(static_cast<const void*>(VisType)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001479 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +00001480}
1481
Daniel Dunbar921b9682008-10-04 19:21:03 +00001482// #pragma pack(...) comes in the following delicious flavors:
1483// pack '(' [integer] ')'
1484// pack '(' 'show' ')'
1485// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +00001486void PragmaPackHandler::HandlePragma(Preprocessor &PP,
1487 PragmaIntroducerKind Introducer,
1488 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001489 SourceLocation PackLoc = PackTok.getLocation();
1490
1491 Token Tok;
1492 PP.Lex(Tok);
1493 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001494 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001495 return;
1496 }
1497
Denis Zobnin10c4f452016-04-29 18:17:40 +00001498 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1499 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001500 Token Alignment;
1501 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001502 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001503 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001504 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001505
1506 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001507
1508 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1509 // the push/pop stack.
1510 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001511 Action =
1512 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001513 } else if (Tok.is(tok::identifier)) {
1514 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001515 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001516 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001517 PP.Lex(Tok);
1518 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001519 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001520 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001521 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001522 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001523 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001524 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001525 return;
Mike Stump11289f42009-09-09 15:08:12 +00001526 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001527 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001528
Daniel Dunbar921b9682008-10-04 19:21:03 +00001529 if (Tok.is(tok::comma)) {
1530 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001531
Daniel Dunbar921b9682008-10-04 19:21:03 +00001532 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001533 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001534 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001535
1536 PP.Lex(Tok);
1537 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001538 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001539 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001540
Daniel Dunbar921b9682008-10-04 19:21:03 +00001541 if (Tok.is(tok::comma)) {
1542 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001543
Daniel Dunbar921b9682008-10-04 19:21:03 +00001544 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001545 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001546 return;
1547 }
Mike Stump11289f42009-09-09 15:08:12 +00001548
Denis Zobnin10c4f452016-04-29 18:17:40 +00001549 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001550 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001551
1552 PP.Lex(Tok);
1553 }
1554 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001555 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001556 return;
1557 }
1558 }
1559 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001560 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001561 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1562 // the push/pop stack.
1563 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001564 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001565 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001566
1567 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001568 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001569 return;
1570 }
1571
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001572 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001573 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001574 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001575 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1576 return;
1577 }
1578
David Blaikie2eabcc92016-02-09 18:52:09 +00001579 PragmaPackInfo *Info =
1580 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001581 Info->Action = Action;
1582 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001583 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001584
David Blaikie2eabcc92016-02-09 18:52:09 +00001585 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1586 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001587 Toks[0].startToken();
1588 Toks[0].setKind(tok::annot_pragma_pack);
1589 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001590 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001591 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00001592 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001593}
1594
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001595// #pragma ms_struct on
1596// #pragma ms_struct off
1597void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1598 PragmaIntroducerKind Introducer,
1599 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001600 PragmaMSStructKind Kind = PMSST_OFF;
1601
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001602 Token Tok;
1603 PP.Lex(Tok);
1604 if (Tok.isNot(tok::identifier)) {
1605 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1606 return;
1607 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001608 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001609 const IdentifierInfo *II = Tok.getIdentifierInfo();
1610 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001611 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001612 PP.Lex(Tok);
1613 }
1614 else if (II->isStr("off") || II->isStr("reset"))
1615 PP.Lex(Tok);
1616 else {
1617 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1618 return;
1619 }
1620
1621 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001622 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1623 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001624 return;
1625 }
Eli Friedman68be1642012-10-04 02:36:51 +00001626
David Blaikie2eabcc92016-02-09 18:52:09 +00001627 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1628 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001629 Toks[0].startToken();
1630 Toks[0].setKind(tok::annot_pragma_msstruct);
1631 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001632 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001633 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1634 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001635 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001636}
1637
Javed Absar2a67c9e2017-06-05 10:11:57 +00001638// #pragma clang section bss="abc" data="" rodata="def" text=""
1639void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
1640 PragmaIntroducerKind Introducer, Token &FirstToken) {
1641
1642 Token Tok;
1643 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1644
1645 PP.Lex(Tok); // eat 'section'
1646 while (Tok.isNot(tok::eod)) {
1647 if (Tok.isNot(tok::identifier)) {
1648 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1649 return;
1650 }
1651
1652 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1653 if (SecType->isStr("bss"))
1654 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1655 else if (SecType->isStr("data"))
1656 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1657 else if (SecType->isStr("rodata"))
1658 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1659 else if (SecType->isStr("text"))
1660 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1661 else {
1662 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1663 return;
1664 }
1665
1666 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1667 if (Tok.isNot(tok::equal)) {
1668 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1669 return;
1670 }
1671
1672 std::string SecName;
1673 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1674 return;
1675
1676 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1677 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1678 Sema::PragmaClangSectionAction::PCSA_Clear),
1679 SecKind, SecName);
1680 }
1681}
1682
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001683// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1684// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001685static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001686 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001687 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001688
1689 if (IsOptions) {
1690 PP.Lex(Tok);
1691 if (Tok.isNot(tok::identifier) ||
1692 !Tok.getIdentifierInfo()->isStr("align")) {
1693 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1694 return;
1695 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001696 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001697
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001698 PP.Lex(Tok);
1699 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001700 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1701 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001702 return;
1703 }
1704
1705 PP.Lex(Tok);
1706 if (Tok.isNot(tok::identifier)) {
1707 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001708 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001709 return;
1710 }
1711
John McCallfaf5fb42010-08-26 23:41:50 +00001712 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001713 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001714 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001715 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001716 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001717 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001718 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001719 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001720 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001721 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001722 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001723 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001724 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001725 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001726 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001727 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1728 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001729 return;
1730 }
1731
David Majnemera8f2f1d2015-03-19 00:10:23 +00001732 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001733 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001734 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001735 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001736 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001737 return;
1738 }
1739
David Blaikie2eabcc92016-02-09 18:52:09 +00001740 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1741 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001742 Toks[0].startToken();
1743 Toks[0].setKind(tok::annot_pragma_align);
1744 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001745 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001746 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1747 static_cast<uintptr_t>(Kind)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001748 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001749}
1750
Douglas Gregorc7d65762010-09-09 22:45:38 +00001751void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1752 PragmaIntroducerKind Introducer,
1753 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001754 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001755}
1756
Douglas Gregorc7d65762010-09-09 22:45:38 +00001757void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1758 PragmaIntroducerKind Introducer,
1759 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001760 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001761}
1762
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001763// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001764void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1765 PragmaIntroducerKind Introducer,
1766 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001767 // FIXME: Should we be expanding macros here? My guess is no.
1768 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001769
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001770 // Lex the left '('.
1771 Token Tok;
1772 PP.Lex(Tok);
1773 if (Tok.isNot(tok::l_paren)) {
1774 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1775 return;
1776 }
Mike Stump11289f42009-09-09 15:08:12 +00001777
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001778 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001779 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001780 SourceLocation RParenLoc;
1781 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001782
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001783 while (true) {
1784 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001785
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001786 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001787 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001788 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001789 LexID = false;
1790 continue;
1791 }
1792
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001793 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001794 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1795 return;
1796 }
Mike Stump11289f42009-09-09 15:08:12 +00001797
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001798 // We are execting a ')' or a ','.
1799 if (Tok.is(tok::comma)) {
1800 LexID = true;
1801 continue;
1802 }
Mike Stump11289f42009-09-09 15:08:12 +00001803
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001804 if (Tok.is(tok::r_paren)) {
1805 RParenLoc = Tok.getLocation();
1806 break;
1807 }
Mike Stump11289f42009-09-09 15:08:12 +00001808
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001809 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001810 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001811 return;
1812 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001813
1814 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001815 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001816 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1817 "unused";
1818 return;
1819 }
1820
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001821 // Verify that we have a location for the right parenthesis.
1822 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001823 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001824
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001825 // For each identifier token, insert into the token stream a
1826 // annot_pragma_unused token followed by the identifier token.
1827 // This allows us to cache a "#pragma unused" that occurs inside an inline
1828 // C++ member function.
1829
David Blaikie2eabcc92016-02-09 18:52:09 +00001830 MutableArrayRef<Token> Toks(
1831 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1832 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001833 for (unsigned i=0; i != Identifiers.size(); i++) {
1834 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1835 pragmaUnusedTok.startToken();
1836 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1837 pragmaUnusedTok.setLocation(UnusedLoc);
1838 idTok = Identifiers[i];
1839 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001840 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001841}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001842
1843// #pragma weak identifier
1844// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001845void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1846 PragmaIntroducerKind Introducer,
1847 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001848 SourceLocation WeakLoc = WeakTok.getLocation();
1849
1850 Token Tok;
1851 PP.Lex(Tok);
1852 if (Tok.isNot(tok::identifier)) {
1853 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1854 return;
1855 }
1856
Eli Friedman68be1642012-10-04 02:36:51 +00001857 Token WeakName = Tok;
1858 bool HasAlias = false;
1859 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001860
1861 PP.Lex(Tok);
1862 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001863 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001864 PP.Lex(Tok);
1865 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001866 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001867 << "weak";
1868 return;
1869 }
Eli Friedman68be1642012-10-04 02:36:51 +00001870 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001871 PP.Lex(Tok);
1872 }
1873
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001874 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001875 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1876 return;
1877 }
1878
Eli Friedman68be1642012-10-04 02:36:51 +00001879 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00001880 MutableArrayRef<Token> Toks(
1881 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001882 Token &pragmaUnusedTok = Toks[0];
1883 pragmaUnusedTok.startToken();
1884 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1885 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001886 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001887 Toks[1] = WeakName;
1888 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001889 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001890 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00001891 MutableArrayRef<Token> Toks(
1892 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00001893 Token &pragmaUnusedTok = Toks[0];
1894 pragmaUnusedTok.startToken();
1895 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1896 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001897 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001898 Toks[1] = WeakName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001899 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001900 }
1901}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001902
David Chisnall0867d9c2012-02-18 16:12:34 +00001903// #pragma redefine_extname identifier identifier
1904void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1905 PragmaIntroducerKind Introducer,
1906 Token &RedefToken) {
1907 SourceLocation RedefLoc = RedefToken.getLocation();
1908
1909 Token Tok;
1910 PP.Lex(Tok);
1911 if (Tok.isNot(tok::identifier)) {
1912 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1913 "redefine_extname";
1914 return;
1915 }
1916
Eli Friedman68be1642012-10-04 02:36:51 +00001917 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001918 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001919
David Chisnall0867d9c2012-02-18 16:12:34 +00001920 if (Tok.isNot(tok::identifier)) {
1921 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1922 << "redefine_extname";
1923 return;
1924 }
Eli Friedman68be1642012-10-04 02:36:51 +00001925
1926 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001927 PP.Lex(Tok);
1928
1929 if (Tok.isNot(tok::eod)) {
1930 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1931 "redefine_extname";
1932 return;
1933 }
1934
David Blaikie2eabcc92016-02-09 18:52:09 +00001935 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
1936 3);
Eli Friedman68be1642012-10-04 02:36:51 +00001937 Token &pragmaRedefTok = Toks[0];
1938 pragmaRedefTok.startToken();
1939 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1940 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001941 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001942 Toks[1] = RedefName;
1943 Toks[2] = AliasName;
David Blaikie2eabcc92016-02-09 18:52:09 +00001944 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
David Chisnall0867d9c2012-02-18 16:12:34 +00001945}
1946
1947
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001948void
1949PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1950 PragmaIntroducerKind Introducer,
1951 Token &Tok) {
1952 tok::OnOffSwitch OOS;
1953 if (PP.LexOnOffSwitch(OOS))
1954 return;
1955
David Blaikie2eabcc92016-02-09 18:52:09 +00001956 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1957 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001958 Toks[0].startToken();
1959 Toks[0].setKind(tok::annot_pragma_fp_contract);
1960 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001961 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00001962 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1963 static_cast<uintptr_t>(OOS)));
David Blaikie2eabcc92016-02-09 18:52:09 +00001964 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001965}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001966
1967void
1968PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1969 PragmaIntroducerKind Introducer,
1970 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001971 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001972 if (Tok.isNot(tok::identifier)) {
1973 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1974 "OPENCL";
1975 return;
1976 }
Yaxun Liu5b746652016-12-18 05:18:55 +00001977 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001978 SourceLocation NameLoc = Tok.getLocation();
1979
1980 PP.Lex(Tok);
1981 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00001982 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001983 return;
1984 }
1985
1986 PP.Lex(Tok);
1987 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00001988 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001989 return;
1990 }
Yaxun Liu5b746652016-12-18 05:18:55 +00001991 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001992
Yaxun Liu5b746652016-12-18 05:18:55 +00001993 OpenCLExtState State;
1994 if (Pred->isStr("enable")) {
1995 State = Enable;
1996 } else if (Pred->isStr("disable")) {
1997 State = Disable;
1998 } else if (Pred->isStr("begin"))
1999 State = Begin;
2000 else if (Pred->isStr("end"))
2001 State = End;
2002 else {
2003 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2004 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002005 return;
2006 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002007 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002008
Eli Friedman68be1642012-10-04 02:36:51 +00002009 PP.Lex(Tok);
2010 if (Tok.isNot(tok::eod)) {
2011 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2012 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002013 return;
2014 }
Eli Friedman68be1642012-10-04 02:36:51 +00002015
Yaxun Liu5b746652016-12-18 05:18:55 +00002016 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2017 Info->first = Ext;
2018 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002019 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2020 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002021 Toks[0].startToken();
2022 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2023 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002024 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002025 Toks[0].setAnnotationEndLoc(StateLoc);
David Blaikie2eabcc92016-02-09 18:52:09 +00002026 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002027
2028 if (PP.getPPCallbacks())
Yaxun Liu5b746652016-12-18 05:18:55 +00002029 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2030 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002031}
2032
Alexey Bataeva769e072013-03-22 06:34:35 +00002033/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
2034///
2035void
2036PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2037 PragmaIntroducerKind Introducer,
2038 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002039 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2040 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002041 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002042 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2043 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002044 }
2045 PP.DiscardUntilEndOfDirective();
2046}
2047
2048/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
2049///
2050void
2051PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2052 PragmaIntroducerKind Introducer,
2053 Token &FirstTok) {
2054 SmallVector<Token, 16> Pragma;
2055 Token Tok;
2056 Tok.startToken();
2057 Tok.setKind(tok::annot_pragma_openmp);
2058 Tok.setLocation(FirstTok.getLocation());
2059
2060 while (Tok.isNot(tok::eod)) {
2061 Pragma.push_back(Tok);
2062 PP.Lex(Tok);
2063 }
2064 SourceLocation EodLoc = Tok.getLocation();
2065 Tok.startToken();
2066 Tok.setKind(tok::annot_pragma_openmp_end);
2067 Tok.setLocation(EodLoc);
2068 Pragma.push_back(Tok);
2069
David Blaikie2eabcc92016-02-09 18:52:09 +00002070 auto Toks = llvm::make_unique<Token[]>(Pragma.size());
2071 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2072 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2073 /*DisableMacroExpansion=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002074}
Reid Kleckner002562a2013-05-06 21:02:12 +00002075
David Majnemer4bb09802014-02-10 19:50:15 +00002076/// \brief Handle '#pragma pointers_to_members'
2077// The grammar for this pragma is as follows:
2078//
2079// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2080//
2081// #pragma pointers_to_members '(' 'best_case' ')'
2082// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2083// #pragma pointers_to_members '(' inheritance-model ')'
2084void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2085 PragmaIntroducerKind Introducer,
2086 Token &Tok) {
2087 SourceLocation PointersToMembersLoc = Tok.getLocation();
2088 PP.Lex(Tok);
2089 if (Tok.isNot(tok::l_paren)) {
2090 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2091 << "pointers_to_members";
2092 return;
2093 }
2094 PP.Lex(Tok);
2095 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2096 if (!Arg) {
2097 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2098 << "pointers_to_members";
2099 return;
2100 }
2101 PP.Lex(Tok);
2102
David Majnemer86c318f2014-02-11 21:05:00 +00002103 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002104 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002105 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002106 } else {
2107 if (Arg->isStr("full_generality")) {
2108 if (Tok.is(tok::comma)) {
2109 PP.Lex(Tok);
2110
2111 Arg = Tok.getIdentifierInfo();
2112 if (!Arg) {
2113 PP.Diag(Tok.getLocation(),
2114 diag::err_pragma_pointers_to_members_unknown_kind)
2115 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2116 return;
2117 }
2118 PP.Lex(Tok);
2119 } else if (Tok.is(tok::r_paren)) {
2120 // #pragma pointers_to_members(full_generality) implicitly specifies
2121 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002122 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002123 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002124 } else {
2125 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2126 << "full_generality";
2127 return;
2128 }
2129 }
2130
2131 if (Arg) {
2132 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002133 RepresentationMethod =
2134 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002135 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002136 RepresentationMethod =
2137 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002138 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002139 RepresentationMethod =
2140 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002141 } else {
2142 PP.Diag(Tok.getLocation(),
2143 diag::err_pragma_pointers_to_members_unknown_kind)
2144 << Arg << /*HasPointerDeclaration*/ 1;
2145 return;
2146 }
2147 }
2148 }
2149
2150 if (Tok.isNot(tok::r_paren)) {
2151 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2152 << (Arg ? Arg->getName() : "full_generality");
2153 return;
2154 }
2155
David Majnemera8f2f1d2015-03-19 00:10:23 +00002156 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002157 PP.Lex(Tok);
2158 if (Tok.isNot(tok::eod)) {
2159 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2160 << "pointers_to_members";
2161 return;
2162 }
2163
2164 Token AnnotTok;
2165 AnnotTok.startToken();
2166 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2167 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002168 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002169 AnnotTok.setAnnotationValue(
2170 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2171 PP.EnterToken(AnnotTok);
2172}
2173
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002174/// \brief Handle '#pragma vtordisp'
2175// The grammar for this pragma is as follows:
2176//
2177// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2178//
2179// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2180// #pragma vtordisp '(' 'pop' ')'
2181// #pragma vtordisp '(' ')'
2182void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2183 PragmaIntroducerKind Introducer,
2184 Token &Tok) {
2185 SourceLocation VtorDispLoc = Tok.getLocation();
2186 PP.Lex(Tok);
2187 if (Tok.isNot(tok::l_paren)) {
2188 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2189 return;
2190 }
2191 PP.Lex(Tok);
2192
Denis Zobnin2290dac2016-04-29 11:27:00 +00002193 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002194 const IdentifierInfo *II = Tok.getIdentifierInfo();
2195 if (II) {
2196 if (II->isStr("push")) {
2197 // #pragma vtordisp(push, mode)
2198 PP.Lex(Tok);
2199 if (Tok.isNot(tok::comma)) {
2200 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2201 return;
2202 }
2203 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002204 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002205 // not push, could be on/off
2206 } else if (II->isStr("pop")) {
2207 // #pragma vtordisp(pop)
2208 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002209 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002210 }
2211 // not push or pop, could be on/off
2212 } else {
2213 if (Tok.is(tok::r_paren)) {
2214 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002215 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002216 }
2217 }
2218
2219
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002220 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002221 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002222 const IdentifierInfo *II = Tok.getIdentifierInfo();
2223 if (II && II->isStr("off")) {
2224 PP.Lex(Tok);
2225 Value = 0;
2226 } else if (II && II->isStr("on")) {
2227 PP.Lex(Tok);
2228 Value = 1;
2229 } else if (Tok.is(tok::numeric_constant) &&
2230 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2231 if (Value > 2) {
2232 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2233 << 0 << 2 << "vtordisp";
2234 return;
2235 }
2236 } else {
2237 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2238 << "vtordisp";
2239 return;
2240 }
2241 }
2242
2243 // Finish the pragma: ')' $
2244 if (Tok.isNot(tok::r_paren)) {
2245 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2246 return;
2247 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002248 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002249 PP.Lex(Tok);
2250 if (Tok.isNot(tok::eod)) {
2251 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2252 << "vtordisp";
2253 return;
2254 }
2255
2256 // Enter the annotation.
2257 Token AnnotTok;
2258 AnnotTok.startToken();
2259 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2260 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002261 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002262 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002263 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002264 PP.EnterToken(AnnotTok);
2265}
2266
Warren Huntc3b18962014-04-08 22:30:47 +00002267/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
2268/// an annotation token.
2269void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2270 PragmaIntroducerKind Introducer,
2271 Token &Tok) {
2272 Token EoF, AnnotTok;
2273 EoF.startToken();
2274 EoF.setKind(tok::eof);
2275 AnnotTok.startToken();
2276 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2277 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002278 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002279 SmallVector<Token, 8> TokenVector;
2280 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002281 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002282 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002283 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2284 }
Warren Huntc3b18962014-04-08 22:30:47 +00002285 // Add a sentinal EoF token to the end of the list.
2286 TokenVector.push_back(EoF);
2287 // We must allocate this array with new because EnterTokenStream is going to
2288 // delete it later.
David Blaikie2eabcc92016-02-09 18:52:09 +00002289 auto TokenArray = llvm::make_unique<Token[]>(TokenVector.size());
2290 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002291 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002292 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2293 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002294 AnnotTok.setAnnotationValue(Value);
2295 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002296}
2297
Aaron Ballman5d041be2013-06-04 02:07:14 +00002298/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
2299///
2300/// The syntax is:
2301/// \code
2302/// #pragma detect_mismatch("name", "value")
2303/// \endcode
2304/// Where 'name' and 'value' are quoted strings. The values are embedded in
2305/// the object file and passed along to the linker. If the linker detects a
2306/// mismatch in the object file's values for the given name, a LNK2038 error
2307/// is emitted. See MSDN for more details.
2308void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
2309 PragmaIntroducerKind Introducer,
2310 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002311 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002312 PP.Lex(Tok);
2313 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002314 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002315 return;
2316 }
2317
2318 // Read the name to embed, which must be a string literal.
2319 std::string NameString;
2320 if (!PP.LexStringLiteral(Tok, NameString,
2321 "pragma detect_mismatch",
2322 /*MacroExpansion=*/true))
2323 return;
2324
2325 // Read the comma followed by a second string literal.
2326 std::string ValueString;
2327 if (Tok.isNot(tok::comma)) {
2328 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2329 return;
2330 }
2331
2332 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
2333 /*MacroExpansion=*/true))
2334 return;
2335
2336 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002337 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002338 return;
2339 }
2340 PP.Lex(Tok); // Eat the r_paren.
2341
2342 if (Tok.isNot(tok::eod)) {
2343 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2344 return;
2345 }
2346
Reid Kleckner71966c92014-02-20 23:37:45 +00002347 // If the pragma is lexically sound, notify any interested PPCallbacks.
2348 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002349 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002350 ValueString);
2351
Nico Webercbbaeb12016-03-02 19:28:54 +00002352 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002353}
2354
Reid Kleckner002562a2013-05-06 21:02:12 +00002355/// \brief Handle the microsoft \#pragma comment extension.
2356///
2357/// The syntax is:
2358/// \code
2359/// #pragma comment(linker, "foo")
2360/// \endcode
2361/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2362/// "foo" is a string, which is fully macro expanded, and permits string
2363/// concatenation, embedded escape characters etc. See MSDN for more details.
2364void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
2365 PragmaIntroducerKind Introducer,
2366 Token &Tok) {
2367 SourceLocation CommentLoc = Tok.getLocation();
2368 PP.Lex(Tok);
2369 if (Tok.isNot(tok::l_paren)) {
2370 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2371 return;
2372 }
2373
2374 // Read the identifier.
2375 PP.Lex(Tok);
2376 if (Tok.isNot(tok::identifier)) {
2377 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2378 return;
2379 }
2380
2381 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002382 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002383 PragmaMSCommentKind Kind =
2384 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2385 .Case("linker", PCK_Linker)
2386 .Case("lib", PCK_Lib)
2387 .Case("compiler", PCK_Compiler)
2388 .Case("exestr", PCK_ExeStr)
2389 .Case("user", PCK_User)
2390 .Default(PCK_Unknown);
2391 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002392 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2393 return;
2394 }
2395
Yunzhong Gao99efc032015-03-23 20:41:42 +00002396 // On PS4, issue a warning about any pragma comments other than
2397 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002398 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002399 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2400 << II->getName();
2401 return;
2402 }
2403
Reid Kleckner002562a2013-05-06 21:02:12 +00002404 // Read the optional string if present.
2405 PP.Lex(Tok);
2406 std::string ArgumentString;
2407 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2408 "pragma comment",
2409 /*MacroExpansion=*/true))
2410 return;
2411
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002412 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002413 // FIXME: If the kind is "compiler" warn if the string is present (it is
2414 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002415 // The MSDN docs say that "lib" and "linker" require a string and have a short
2416 // whitelist of linker options they support, but in practice MSVC doesn't
2417 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002418
2419 if (Tok.isNot(tok::r_paren)) {
2420 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2421 return;
2422 }
2423 PP.Lex(Tok); // eat the r_paren.
2424
2425 if (Tok.isNot(tok::eod)) {
2426 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2427 return;
2428 }
2429
Reid Kleckner71966c92014-02-20 23:37:45 +00002430 // If the pragma is lexically sound, notify any interested PPCallbacks.
2431 if (PP.getPPCallbacks())
2432 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2433
Nico Weber66220292016-03-02 17:28:48 +00002434 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002435}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002436
2437// #pragma clang optimize off
2438// #pragma clang optimize on
2439void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
2440 PragmaIntroducerKind Introducer,
2441 Token &FirstToken) {
2442 Token Tok;
2443 PP.Lex(Tok);
2444 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002445 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002446 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002447 return;
2448 }
2449 if (Tok.isNot(tok::identifier)) {
2450 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2451 << PP.getSpelling(Tok);
2452 return;
2453 }
2454 const IdentifierInfo *II = Tok.getIdentifierInfo();
2455 // The only accepted values are 'on' or 'off'.
2456 bool IsOn = false;
2457 if (II->isStr("on")) {
2458 IsOn = true;
2459 } else if (!II->isStr("off")) {
2460 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2461 << PP.getSpelling(Tok);
2462 return;
2463 }
2464 PP.Lex(Tok);
2465
2466 if (Tok.isNot(tok::eod)) {
2467 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2468 << PP.getSpelling(Tok);
2469 return;
2470 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002471
2472 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2473}
2474
Adam Nemet60d32642017-04-04 21:18:36 +00002475namespace {
2476/// Used as the annotation value for tok::annot_pragma_fp.
2477struct TokFPAnnotValue {
2478 enum FlagKinds { Contract };
2479 enum FlagValues { On, Off, Fast };
2480
2481 FlagKinds FlagKind;
2482 FlagValues FlagValue;
2483};
2484} // end anonymous namespace
2485
2486void PragmaFPHandler::HandlePragma(Preprocessor &PP,
2487 PragmaIntroducerKind Introducer,
2488 Token &Tok) {
2489 // fp
2490 Token PragmaName = Tok;
2491 SmallVector<Token, 1> TokenList;
2492
2493 PP.Lex(Tok);
2494 if (Tok.isNot(tok::identifier)) {
2495 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2496 << /*MissingOption=*/true << "";
2497 return;
2498 }
2499
2500 while (Tok.is(tok::identifier)) {
2501 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2502
2503 auto FlagKind =
2504 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2505 OptionInfo->getName())
2506 .Case("contract", TokFPAnnotValue::Contract)
2507 .Default(None);
2508 if (!FlagKind) {
2509 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2510 << /*MissingOption=*/false << OptionInfo;
2511 return;
2512 }
2513 PP.Lex(Tok);
2514
2515 // Read '('
2516 if (Tok.isNot(tok::l_paren)) {
2517 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2518 return;
2519 }
2520 PP.Lex(Tok);
2521
2522 if (Tok.isNot(tok::identifier)) {
2523 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2524 << PP.getSpelling(Tok) << OptionInfo->getName();
2525 return;
2526 }
2527 const IdentifierInfo *II = Tok.getIdentifierInfo();
2528
2529 auto FlagValue =
2530 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2531 II->getName())
2532 .Case("on", TokFPAnnotValue::On)
2533 .Case("off", TokFPAnnotValue::Off)
2534 .Case("fast", TokFPAnnotValue::Fast)
2535 .Default(llvm::None);
2536
2537 if (!FlagValue) {
2538 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2539 << PP.getSpelling(Tok) << OptionInfo->getName();
2540 return;
2541 }
2542 PP.Lex(Tok);
2543
2544 // Read ')'
2545 if (Tok.isNot(tok::r_paren)) {
2546 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2547 return;
2548 }
2549 PP.Lex(Tok);
2550
2551 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2552 TokFPAnnotValue{*FlagKind, *FlagValue};
2553 // Generate the loop hint token.
2554 Token FPTok;
2555 FPTok.startToken();
2556 FPTok.setKind(tok::annot_pragma_fp);
2557 FPTok.setLocation(PragmaName.getLocation());
2558 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2559 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2560 TokenList.push_back(FPTok);
2561 }
2562
2563 if (Tok.isNot(tok::eod)) {
2564 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2565 << "clang fp";
2566 return;
2567 }
2568
2569 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2570 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2571
2572 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2573 /*DisableMacroExpansion=*/false);
2574}
2575
2576void Parser::HandlePragmaFP() {
2577 assert(Tok.is(tok::annot_pragma_fp));
2578 auto *AnnotValue =
2579 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2580
2581 LangOptions::FPContractModeKind FPC;
2582 switch (AnnotValue->FlagValue) {
2583 case TokFPAnnotValue::On:
2584 FPC = LangOptions::FPC_On;
2585 break;
2586 case TokFPAnnotValue::Fast:
2587 FPC = LangOptions::FPC_Fast;
2588 break;
2589 case TokFPAnnotValue::Off:
2590 FPC = LangOptions::FPC_Off;
2591 break;
2592 }
2593
2594 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002595 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002596}
2597
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002598/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002599static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2600 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002601 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002602 SmallVector<Token, 1> ValueList;
2603 int OpenParens = ValueInParens ? 1 : 0;
2604 // Read constant expression.
2605 while (Tok.isNot(tok::eod)) {
2606 if (Tok.is(tok::l_paren))
2607 OpenParens++;
2608 else if (Tok.is(tok::r_paren)) {
2609 OpenParens--;
2610 if (OpenParens == 0 && ValueInParens)
2611 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002612 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002613
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002614 ValueList.push_back(Tok);
2615 PP.Lex(Tok);
2616 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002617
2618 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002619 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002620 if (Tok.isNot(tok::r_paren)) {
2621 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2622 return true;
2623 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002624 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002625 }
2626
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002627 Token EOFTok;
2628 EOFTok.startToken();
2629 EOFTok.setKind(tok::eof);
2630 EOFTok.setLocation(Tok.getLocation());
2631 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2632
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002633 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002634
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002635 Info.PragmaName = PragmaName;
2636 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002637 return false;
2638}
2639
Eli Bendersky06a40422014-06-06 20:31:48 +00002640/// \brief Handle the \#pragma clang loop directive.
2641/// #pragma clang 'loop' loop-hints
2642///
2643/// loop-hints:
2644/// loop-hint loop-hints[opt]
2645///
2646/// loop-hint:
2647/// 'vectorize' '(' loop-hint-keyword ')'
2648/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002649/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002650/// 'vectorize_width' '(' loop-hint-value ')'
2651/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002652/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002653///
2654/// loop-hint-keyword:
2655/// 'enable'
2656/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002657/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002658///
Mark Heffernan450c2382014-07-23 17:31:31 +00002659/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002660/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002661/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002662/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002663///
Eli Bendersky06a40422014-06-06 20:31:48 +00002664/// loop-hint-value:
2665/// constant-expression
2666///
2667/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2668/// try vectorizing the instructions of the loop it precedes. Specifying
2669/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2670/// interleaving multiple iterations of the loop it precedes. The width of the
2671/// vector instructions is specified by vectorize_width() and the number of
2672/// interleaved loop iterations is specified by interleave_count(). Specifying a
2673/// value of 1 effectively disables vectorization/interleaving, even if it is
2674/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2675/// only works on inner loops.
2676///
Eli Bendersky86483b32014-06-11 17:56:26 +00002677/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002678/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2679/// completely if the trip count is known at compile time and unroll partially
2680/// if the trip count is not known. Specifying unroll(full) is similar to
2681/// unroll(enable) but will unroll the loop only if the trip count is known at
2682/// compile time. Specifying unroll(disable) disables unrolling for the
2683/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2684/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002685void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
2686 PragmaIntroducerKind Introducer,
2687 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002688 // Incoming token is "loop" from "#pragma clang loop".
2689 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002690 SmallVector<Token, 1> TokenList;
2691
2692 // Lex the optimization option and verify it is an identifier.
2693 PP.Lex(Tok);
2694 if (Tok.isNot(tok::identifier)) {
2695 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2696 << /*MissingOption=*/true << "";
2697 return;
2698 }
2699
2700 while (Tok.is(tok::identifier)) {
2701 Token Option = Tok;
2702 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2703
Eli Bendersky86483b32014-06-11 17:56:26 +00002704 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002705 .Case("vectorize", true)
2706 .Case("interleave", true)
2707 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002708 .Case("distribute", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002709 .Case("vectorize_width", true)
2710 .Case("interleave_count", true)
2711 .Case("unroll_count", true)
2712 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002713 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002714 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2715 << /*MissingOption=*/false << OptionInfo;
2716 return;
2717 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002718 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002719
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002720 // Read '('
2721 if (Tok.isNot(tok::l_paren)) {
2722 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002723 return;
2724 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002725 PP.Lex(Tok);
2726
2727 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2728 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2729 *Info))
2730 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002731
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002732 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002733 Token LoopHintTok;
2734 LoopHintTok.startToken();
2735 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002736 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002737 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002738 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2739 TokenList.push_back(LoopHintTok);
2740 }
2741
2742 if (Tok.isNot(tok::eod)) {
2743 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2744 << "clang loop";
2745 return;
2746 }
2747
David Blaikie2eabcc92016-02-09 18:52:09 +00002748 auto TokenArray = llvm::make_unique<Token[]>(TokenList.size());
2749 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002750
David Blaikie2eabcc92016-02-09 18:52:09 +00002751 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
2752 /*DisableMacroExpansion=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002753}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002754
2755/// \brief Handle the loop unroll optimization pragmas.
2756/// #pragma unroll
2757/// #pragma unroll unroll-hint-value
2758/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002759/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002760///
2761/// unroll-hint-value:
2762/// constant-expression
2763///
Mark Heffernanc888e412014-07-24 18:09:38 +00002764/// Loop unrolling hints can be specified with '#pragma unroll' or
2765/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2766/// contained in parentheses. With no argument the directive instructs llvm to
2767/// try to unroll the loop completely. A positive integer argument can be
2768/// specified to indicate the number of times the loop should be unrolled. To
2769/// maximize compatibility with other compilers the unroll count argument can be
2770/// specified with or without parentheses. Specifying, '#pragma nounroll'
2771/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002772void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2773 PragmaIntroducerKind Introducer,
2774 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002775 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2776 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002777 Token PragmaName = Tok;
2778 PP.Lex(Tok);
2779 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2780 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002781 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002782 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002783 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002784 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2785 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2786 << "nounroll";
2787 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002788 } else {
2789 // Unroll pragma with an argument: "#pragma unroll N" or
2790 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002791 // Read '(' if it exists.
2792 bool ValueInParens = Tok.is(tok::l_paren);
2793 if (ValueInParens)
2794 PP.Lex(Tok);
2795
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002796 Token Option;
2797 Option.startToken();
2798 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002799 return;
2800
2801 // In CUDA, the argument to '#pragma unroll' should not be contained in
2802 // parentheses.
2803 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002804 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002805 diag::warn_pragma_unroll_cuda_value_in_parens);
2806
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002807 if (Tok.isNot(tok::eod)) {
2808 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2809 << "unroll";
2810 return;
2811 }
2812 }
2813
2814 // Generate the hint token.
David Blaikie2eabcc92016-02-09 18:52:09 +00002815 auto TokenArray = llvm::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002816 TokenArray[0].startToken();
2817 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2818 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002819 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002820 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00002821 PP.EnterTokenStream(std::move(TokenArray), 1,
2822 /*DisableMacroExpansion=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002823}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00002824
2825/// \brief Handle the Microsoft \#pragma intrinsic extension.
2826///
2827/// The syntax is:
2828/// \code
2829/// #pragma intrinsic(memset)
2830/// #pragma intrinsic(strlen, memcpy)
2831/// \endcode
2832///
2833/// Pragma intrisic tells the compiler to use a builtin version of the
2834/// function. Clang does it anyway, so the pragma doesn't really do anything.
2835/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
2836/// isn't an intrinsic in clang and suggest to include intrin.h.
2837void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
2838 PragmaIntroducerKind Introducer,
2839 Token &Tok) {
2840 PP.Lex(Tok);
2841
2842 if (Tok.isNot(tok::l_paren)) {
2843 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
2844 << "intrinsic";
2845 return;
2846 }
2847 PP.Lex(Tok);
2848
2849 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
2850
2851 while (Tok.is(tok::identifier)) {
2852 IdentifierInfo *II = Tok.getIdentifierInfo();
2853 if (!II->getBuiltinID())
2854 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
2855 << II << SuggestIntrinH;
2856
2857 PP.Lex(Tok);
2858 if (Tok.isNot(tok::comma))
2859 break;
2860 PP.Lex(Tok);
2861 }
2862
2863 if (Tok.isNot(tok::r_paren)) {
2864 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
2865 << "intrinsic";
2866 return;
2867 }
2868 PP.Lex(Tok);
2869
2870 if (Tok.isNot(tok::eod))
2871 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2872 << "intrinsic";
2873}
Justin Lebar67a78a62016-10-08 22:15:58 +00002874void PragmaForceCUDAHostDeviceHandler::HandlePragma(
2875 Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) {
2876 Token FirstTok = Tok;
2877
2878 PP.Lex(Tok);
2879 IdentifierInfo *Info = Tok.getIdentifierInfo();
2880 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
2881 PP.Diag(FirstTok.getLocation(),
2882 diag::warn_pragma_force_cuda_host_device_bad_arg);
2883 return;
2884 }
2885
2886 if (Info->isStr("begin"))
2887 Actions.PushForceCUDAHostDevice();
2888 else if (!Actions.PopForceCUDAHostDevice())
2889 PP.Diag(FirstTok.getLocation(),
2890 diag::err_pragma_cannot_end_force_cuda_host_device);
2891
2892 PP.Lex(Tok);
2893 if (!Tok.is(tok::eod))
2894 PP.Diag(FirstTok.getLocation(),
2895 diag::warn_pragma_force_cuda_host_device_bad_arg);
2896}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00002897
2898/// \brief Handle the #pragma clang attribute directive.
2899///
2900/// The syntax is:
2901/// \code
2902/// #pragma clang attribute push(attribute, subject-set)
2903/// #pragma clang attribute pop
2904/// \endcode
2905///
2906/// The subject-set clause defines the set of declarations which receive the
2907/// attribute. Its exact syntax is described in the LanguageExtensions document
2908/// in Clang's documentation.
2909///
2910/// This directive instructs the compiler to begin/finish applying the specified
2911/// attribute to the set of attribute-specific declarations in the active range
2912/// of the pragma.
2913void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
2914 PragmaIntroducerKind Introducer,
2915 Token &FirstToken) {
2916 Token Tok;
2917 PP.Lex(Tok);
2918 auto *Info = new (PP.getPreprocessorAllocator())
2919 PragmaAttributeInfo(AttributesForPragmaAttribute);
2920
2921 // Parse the 'push' or 'pop'.
2922 if (Tok.isNot(tok::identifier)) {
2923 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_push_pop);
2924 return;
2925 }
2926 const auto *II = Tok.getIdentifierInfo();
2927 if (II->isStr("push"))
2928 Info->Action = PragmaAttributeInfo::Push;
2929 else if (II->isStr("pop"))
2930 Info->Action = PragmaAttributeInfo::Pop;
2931 else {
2932 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
2933 << PP.getSpelling(Tok);
2934 return;
2935 }
2936 PP.Lex(Tok);
2937
2938 // Parse the actual attribute.
2939 if (Info->Action == PragmaAttributeInfo::Push) {
2940 if (Tok.isNot(tok::l_paren)) {
2941 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2942 return;
2943 }
2944 PP.Lex(Tok);
2945
2946 // Lex the attribute tokens.
2947 SmallVector<Token, 16> AttributeTokens;
2948 int OpenParens = 1;
2949 while (Tok.isNot(tok::eod)) {
2950 if (Tok.is(tok::l_paren))
2951 OpenParens++;
2952 else if (Tok.is(tok::r_paren)) {
2953 OpenParens--;
2954 if (OpenParens == 0)
2955 break;
2956 }
2957
2958 AttributeTokens.push_back(Tok);
2959 PP.Lex(Tok);
2960 }
2961
2962 if (AttributeTokens.empty()) {
2963 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
2964 return;
2965 }
2966 if (Tok.isNot(tok::r_paren)) {
2967 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2968 return;
2969 }
2970 SourceLocation EndLoc = Tok.getLocation();
2971 PP.Lex(Tok);
2972
2973 // Terminate the attribute for parsing.
2974 Token EOFTok;
2975 EOFTok.startToken();
2976 EOFTok.setKind(tok::eof);
2977 EOFTok.setLocation(EndLoc);
2978 AttributeTokens.push_back(EOFTok);
2979
2980 Info->Tokens =
2981 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
2982 }
2983
2984 if (Tok.isNot(tok::eod))
2985 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2986 << "clang attribute";
2987
2988 // Generate the annotated pragma token.
2989 auto TokenArray = llvm::make_unique<Token[]>(1);
2990 TokenArray[0].startToken();
2991 TokenArray[0].setKind(tok::annot_pragma_attribute);
2992 TokenArray[0].setLocation(FirstToken.getLocation());
2993 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
2994 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2995 PP.EnterTokenStream(std::move(TokenArray), 1,
2996 /*DisableMacroExpansion=*/false);
2997}