blob: 55919fd50bebd9a1312f6fdaea2ff2b73caa879f [file] [log] [blame]
Daniel Dunbar921b9682008-10-04 19:21:03 +00001//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the language specific #pragma handlers.
11//
12//===----------------------------------------------------------------------===//
13
Warren Huntc3b18962014-04-08 22:30:47 +000014#include "RAIIObjectsForParser.h"
David Majnemerad2986e2014-08-14 06:35:08 +000015#include "clang/Basic/TargetInfo.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000016#include "clang/Lex/Preprocessor.h"
17#include "clang/Parse/ParseDiagnostic.h"
18#include "clang/Parse/Parser.h"
19#include "clang/Sema/LoopHint.h"
20#include "clang/Sema/Scope.h"
21#include "llvm/ADT/StringSwitch.h"
22using namespace clang;
Daniel Dunbar921b9682008-10-04 19:21:03 +000023
Reid Kleckner5b086462014-02-20 22:52:09 +000024namespace {
25
26struct PragmaAlignHandler : public PragmaHandler {
27 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000028 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
29 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000030};
31
32struct PragmaGCCVisibilityHandler : public PragmaHandler {
33 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000034 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
35 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000036};
37
38struct PragmaOptionsHandler : public PragmaHandler {
39 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000040 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
41 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000042};
43
44struct PragmaPackHandler : public PragmaHandler {
45 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000046 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
47 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000048};
49
50struct PragmaMSStructHandler : public PragmaHandler {
51 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000052 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
53 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000054};
55
56struct PragmaUnusedHandler : public PragmaHandler {
57 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000058 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
59 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000060};
61
62struct PragmaWeakHandler : public PragmaHandler {
63 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000064 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
65 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000066};
67
68struct PragmaRedefineExtnameHandler : public PragmaHandler {
69 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000070 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
71 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000072};
73
74struct PragmaOpenCLExtensionHandler : public PragmaHandler {
75 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000076 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
77 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000078};
79
80
81struct PragmaFPContractHandler : public PragmaHandler {
82 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000083 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
84 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000085};
86
87struct PragmaNoOpenMPHandler : public PragmaHandler {
88 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000089 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
90 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000091};
92
93struct PragmaOpenMPHandler : public PragmaHandler {
94 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000095 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
96 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000097};
98
99/// PragmaCommentHandler - "\#pragma comment ...".
100struct PragmaCommentHandler : public PragmaHandler {
101 PragmaCommentHandler(Sema &Actions)
102 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000103 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
104 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000105private:
106 Sema &Actions;
107};
108
109struct PragmaDetectMismatchHandler : public PragmaHandler {
110 PragmaDetectMismatchHandler(Sema &Actions)
111 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
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 +0000114private:
115 Sema &Actions;
116};
117
118struct PragmaMSPointersToMembers : public PragmaHandler {
119 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
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 +0000122};
123
124struct PragmaMSVtorDisp : public PragmaHandler {
125 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000126 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
127 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000128};
129
Warren Huntc3b18962014-04-08 22:30:47 +0000130struct PragmaMSPragma : public PragmaHandler {
131 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000132 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
133 Token &FirstToken) override;
134};
135
Dario Domizioli13a0a382014-05-23 12:13:25 +0000136/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
137struct PragmaOptimizeHandler : public PragmaHandler {
138 PragmaOptimizeHandler(Sema &S)
139 : PragmaHandler("optimize"), Actions(S) {}
140 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
141 Token &FirstToken) override;
142private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000143 Sema &Actions;
144};
145
146struct PragmaLoopHintHandler : public PragmaHandler {
147 PragmaLoopHintHandler() : PragmaHandler("loop") {}
148 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
149 Token &FirstToken) override;
150};
151
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000152struct PragmaUnrollHintHandler : public PragmaHandler {
153 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
154 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
155 Token &FirstToken) override;
156};
157
Eli Bendersky06a40422014-06-06 20:31:48 +0000158} // end namespace
159
160void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000161 AlignHandler.reset(new PragmaAlignHandler());
162 PP.AddPragmaHandler(AlignHandler.get());
163
164 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
165 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
166
167 OptionsHandler.reset(new PragmaOptionsHandler());
168 PP.AddPragmaHandler(OptionsHandler.get());
169
170 PackHandler.reset(new PragmaPackHandler());
171 PP.AddPragmaHandler(PackHandler.get());
172
173 MSStructHandler.reset(new PragmaMSStructHandler());
174 PP.AddPragmaHandler(MSStructHandler.get());
175
176 UnusedHandler.reset(new PragmaUnusedHandler());
177 PP.AddPragmaHandler(UnusedHandler.get());
178
179 WeakHandler.reset(new PragmaWeakHandler());
180 PP.AddPragmaHandler(WeakHandler.get());
181
182 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
183 PP.AddPragmaHandler(RedefineExtnameHandler.get());
184
185 FPContractHandler.reset(new PragmaFPContractHandler());
186 PP.AddPragmaHandler("STDC", FPContractHandler.get());
187
188 if (getLangOpts().OpenCL) {
189 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
190 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
191
192 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
193 }
194 if (getLangOpts().OpenMP)
195 OpenMPHandler.reset(new PragmaOpenMPHandler());
196 else
197 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
198 PP.AddPragmaHandler(OpenMPHandler.get());
199
200 if (getLangOpts().MicrosoftExt) {
201 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
202 PP.AddPragmaHandler(MSCommentHandler.get());
203 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
204 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
205 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
206 PP.AddPragmaHandler(MSPointersToMembers.get());
207 MSVtorDisp.reset(new PragmaMSVtorDisp());
208 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000209 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000210 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000211 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
212 PP.AddPragmaHandler(MSDataSeg.get());
213 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
214 PP.AddPragmaHandler(MSBSSSeg.get());
215 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
216 PP.AddPragmaHandler(MSConstSeg.get());
217 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
218 PP.AddPragmaHandler(MSCodeSeg.get());
219 MSSection.reset(new PragmaMSPragma("section"));
220 PP.AddPragmaHandler(MSSection.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000221 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000222
223 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
224 PP.AddPragmaHandler("clang", OptimizeHandler.get());
225
226 LoopHintHandler.reset(new PragmaLoopHintHandler());
227 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000228
229 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
230 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000231
232 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
233 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000234}
235
236void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000237 // Remove the pragma handlers we installed.
238 PP.RemovePragmaHandler(AlignHandler.get());
239 AlignHandler.reset();
240 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
241 GCCVisibilityHandler.reset();
242 PP.RemovePragmaHandler(OptionsHandler.get());
243 OptionsHandler.reset();
244 PP.RemovePragmaHandler(PackHandler.get());
245 PackHandler.reset();
246 PP.RemovePragmaHandler(MSStructHandler.get());
247 MSStructHandler.reset();
248 PP.RemovePragmaHandler(UnusedHandler.get());
249 UnusedHandler.reset();
250 PP.RemovePragmaHandler(WeakHandler.get());
251 WeakHandler.reset();
252 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
253 RedefineExtnameHandler.reset();
254
255 if (getLangOpts().OpenCL) {
256 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
257 OpenCLExtensionHandler.reset();
258 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
259 }
260 PP.RemovePragmaHandler(OpenMPHandler.get());
261 OpenMPHandler.reset();
262
263 if (getLangOpts().MicrosoftExt) {
264 PP.RemovePragmaHandler(MSCommentHandler.get());
265 MSCommentHandler.reset();
266 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
267 MSDetectMismatchHandler.reset();
268 PP.RemovePragmaHandler(MSPointersToMembers.get());
269 MSPointersToMembers.reset();
270 PP.RemovePragmaHandler(MSVtorDisp.get());
271 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000272 PP.RemovePragmaHandler(MSInitSeg.get());
273 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000274 PP.RemovePragmaHandler(MSDataSeg.get());
275 MSDataSeg.reset();
276 PP.RemovePragmaHandler(MSBSSSeg.get());
277 MSBSSSeg.reset();
278 PP.RemovePragmaHandler(MSConstSeg.get());
279 MSConstSeg.reset();
280 PP.RemovePragmaHandler(MSCodeSeg.get());
281 MSCodeSeg.reset();
282 PP.RemovePragmaHandler(MSSection.get());
283 MSSection.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000284 }
285
286 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
287 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000288
289 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
290 OptimizeHandler.reset();
291
292 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
293 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000294
295 PP.RemovePragmaHandler(UnrollHintHandler.get());
296 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000297
298 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
299 NoUnrollHintHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000300}
301
302/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000303///
304/// Each annot_pragma_unused is followed by the argument token so e.g.
305/// "#pragma unused(x,y)" becomes:
306/// annot_pragma_unused 'x' annot_pragma_unused 'y'
307void Parser::HandlePragmaUnused() {
308 assert(Tok.is(tok::annot_pragma_unused));
309 SourceLocation UnusedLoc = ConsumeToken();
310 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
311 ConsumeToken(); // The argument token.
312}
Eli Friedman570024a2010-08-05 06:57:20 +0000313
Rafael Espindola273fd772012-01-26 02:02:57 +0000314void Parser::HandlePragmaVisibility() {
315 assert(Tok.is(tok::annot_pragma_vis));
316 const IdentifierInfo *VisType =
317 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
318 SourceLocation VisLoc = ConsumeToken();
319 Actions.ActOnPragmaVisibility(VisType, VisLoc);
320}
321
Eli Friedmanec52f922012-02-23 23:47:16 +0000322struct PragmaPackInfo {
323 Sema::PragmaPackKind Kind;
324 IdentifierInfo *Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000325 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000326 SourceLocation LParenLoc;
327 SourceLocation RParenLoc;
328};
329
330void Parser::HandlePragmaPack() {
331 assert(Tok.is(tok::annot_pragma_pack));
332 PragmaPackInfo *Info =
333 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
334 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000335 ExprResult Alignment;
336 if (Info->Alignment.is(tok::numeric_constant)) {
337 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
338 if (Alignment.isInvalid())
339 return;
340 }
341 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanec52f922012-02-23 23:47:16 +0000342 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +0000343}
344
Eli Friedman68be1642012-10-04 02:36:51 +0000345void Parser::HandlePragmaMSStruct() {
346 assert(Tok.is(tok::annot_pragma_msstruct));
347 Sema::PragmaMSStructKind Kind =
348 static_cast<Sema::PragmaMSStructKind>(
349 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
350 Actions.ActOnPragmaMSStruct(Kind);
351 ConsumeToken(); // The annotation token.
352}
353
354void Parser::HandlePragmaAlign() {
355 assert(Tok.is(tok::annot_pragma_align));
356 Sema::PragmaOptionsAlignKind Kind =
357 static_cast<Sema::PragmaOptionsAlignKind>(
358 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
359 SourceLocation PragmaLoc = ConsumeToken();
360 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
361}
362
363void Parser::HandlePragmaWeak() {
364 assert(Tok.is(tok::annot_pragma_weak));
365 SourceLocation PragmaLoc = ConsumeToken();
366 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
367 Tok.getLocation());
368 ConsumeToken(); // The weak name.
369}
370
371void Parser::HandlePragmaWeakAlias() {
372 assert(Tok.is(tok::annot_pragma_weakalias));
373 SourceLocation PragmaLoc = ConsumeToken();
374 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
375 SourceLocation WeakNameLoc = Tok.getLocation();
376 ConsumeToken();
377 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
378 SourceLocation AliasNameLoc = Tok.getLocation();
379 ConsumeToken();
380 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
381 WeakNameLoc, AliasNameLoc);
382
383}
384
385void Parser::HandlePragmaRedefineExtname() {
386 assert(Tok.is(tok::annot_pragma_redefine_extname));
387 SourceLocation RedefLoc = ConsumeToken();
388 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
389 SourceLocation RedefNameLoc = Tok.getLocation();
390 ConsumeToken();
391 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
392 SourceLocation AliasNameLoc = Tok.getLocation();
393 ConsumeToken();
394 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
395 RedefNameLoc, AliasNameLoc);
396}
397
398void Parser::HandlePragmaFPContract() {
399 assert(Tok.is(tok::annot_pragma_fp_contract));
400 tok::OnOffSwitch OOS =
401 static_cast<tok::OnOffSwitch>(
402 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
403 Actions.ActOnPragmaFPContract(OOS);
404 ConsumeToken(); // The annotation token.
405}
406
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000407StmtResult Parser::HandlePragmaCaptured()
408{
409 assert(Tok.is(tok::annot_pragma_captured));
410 ConsumeToken();
411
412 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000413 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000414 return StmtError();
415 }
416
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000417 SourceLocation Loc = Tok.getLocation();
418
419 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000420 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
421 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000422
423 StmtResult R = ParseCompoundStatement();
424 CapturedRegionScope.Exit();
425
426 if (R.isInvalid()) {
427 Actions.ActOnCapturedRegionError();
428 return StmtError();
429 }
430
431 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000432}
433
Eli Friedman68be1642012-10-04 02:36:51 +0000434namespace {
435 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
436}
437
438void Parser::HandlePragmaOpenCLExtension() {
439 assert(Tok.is(tok::annot_pragma_opencl_extension));
440 OpenCLExtData data =
441 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
442 unsigned state = data.getInt();
443 IdentifierInfo *ename = data.getPointer();
444 SourceLocation NameLoc = Tok.getLocation();
445 ConsumeToken(); // The annotation token.
446
447 OpenCLOptions &f = Actions.getOpenCLOptions();
448 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
449 // overriding all previously issued extension directives, but only if the
450 // behavior is set to disable."
451 if (state == 0 && ename->isStr("all")) {
452#define OPENCLEXT(nm) f.nm = 0;
453#include "clang/Basic/OpenCLExtensions.def"
454 }
455#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
456#include "clang/Basic/OpenCLExtensions.def"
457 else {
458 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
459 return;
460 }
461}
462
David Majnemer4bb09802014-02-10 19:50:15 +0000463void Parser::HandlePragmaMSPointersToMembers() {
464 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000465 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
466 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000467 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
468 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
469 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
470}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000471
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000472void Parser::HandlePragmaMSVtorDisp() {
473 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
474 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
475 Sema::PragmaVtorDispKind Kind =
476 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
477 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
478 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
479 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
480}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000481
Warren Huntc3b18962014-04-08 22:30:47 +0000482void Parser::HandlePragmaMSPragma() {
483 assert(Tok.is(tok::annot_pragma_ms_pragma));
484 // Grab the tokens out of the annotation and enter them into the stream.
485 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
486 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
487 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
488 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000489 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000490 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000491
Warren Huntc3b18962014-04-08 22:30:47 +0000492 // Figure out which #pragma we're dealing with. The switch has no default
493 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000494 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000495 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
496 .Case("data_seg", &Parser::HandlePragmaMSSegment)
497 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
498 .Case("const_seg", &Parser::HandlePragmaMSSegment)
499 .Case("code_seg", &Parser::HandlePragmaMSSegment)
500 .Case("section", &Parser::HandlePragmaMSSection)
501 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000502
503 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
504 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
505 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000506 while (Tok.isNot(tok::eof))
507 PP.Lex(Tok);
508 PP.Lex(Tok);
509 }
510}
511
Reid Kleckner722b1df2014-07-18 00:13:16 +0000512bool Parser::HandlePragmaMSSection(StringRef PragmaName,
513 SourceLocation PragmaLocation) {
514 if (Tok.isNot(tok::l_paren)) {
515 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
516 return false;
517 }
Warren Huntc3b18962014-04-08 22:30:47 +0000518 PP.Lex(Tok); // (
519 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000520 if (Tok.isNot(tok::string_literal)) {
521 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
522 << PragmaName;
523 return false;
524 }
525 ExprResult StringResult = ParseStringLiteralExpression();
526 if (StringResult.isInvalid())
527 return false; // Already diagnosed.
528 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
529 if (SegmentName->getCharByteWidth() != 1) {
530 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
531 << PragmaName;
532 return false;
533 }
Warren Huntc3b18962014-04-08 22:30:47 +0000534 int SectionFlags = 0;
535 while (Tok.is(tok::comma)) {
536 PP.Lex(Tok); // ,
Reid Kleckner722b1df2014-07-18 00:13:16 +0000537 if (!Tok.isAnyIdentifier()) {
538 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
539 << PragmaName;
540 return false;
541 }
Warren Huntc3b18962014-04-08 22:30:47 +0000542 Sema::PragmaSectionFlag Flag =
543 llvm::StringSwitch<Sema::PragmaSectionFlag>(
544 Tok.getIdentifierInfo()->getName())
545 .Case("read", Sema::PSF_Read)
546 .Case("write", Sema::PSF_Write)
547 .Case("execute", Sema::PSF_Execute)
548 .Case("shared", Sema::PSF_Invalid)
549 .Case("nopage", Sema::PSF_Invalid)
550 .Case("nocache", Sema::PSF_Invalid)
551 .Case("discard", Sema::PSF_Invalid)
552 .Case("remove", Sema::PSF_Invalid)
553 .Default(Sema::PSF_None);
554 if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000555 PP.Diag(PragmaLocation, Flag == Sema::PSF_None
556 ? diag::warn_pragma_invalid_specific_action
557 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000558 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000559 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000560 }
561 SectionFlags |= Flag;
562 PP.Lex(Tok); // Identifier
563 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000564 if (Tok.isNot(tok::r_paren)) {
565 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
566 return false;
567 }
Warren Huntc3b18962014-04-08 22:30:47 +0000568 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000569 if (Tok.isNot(tok::eof)) {
570 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
571 << PragmaName;
572 return false;
573 }
Warren Huntc3b18962014-04-08 22:30:47 +0000574 PP.Lex(Tok); // eof
575 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000576 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000577}
578
Reid Kleckner722b1df2014-07-18 00:13:16 +0000579bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
580 SourceLocation PragmaLocation) {
581 if (Tok.isNot(tok::l_paren)) {
582 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
583 return false;
584 }
Warren Huntc3b18962014-04-08 22:30:47 +0000585 PP.Lex(Tok); // (
586 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000587 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000588 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000589 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000590 if (PushPop == "push")
591 Action = Sema::PSK_Push;
592 else if (PushPop == "pop")
593 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000594 else {
595 PP.Diag(PragmaLocation,
596 diag::warn_pragma_expected_section_push_pop_or_name)
597 << PragmaName;
598 return false;
599 }
Warren Huntc3b18962014-04-08 22:30:47 +0000600 if (Action != Sema::PSK_Reset) {
601 PP.Lex(Tok); // push | pop
602 if (Tok.is(tok::comma)) {
603 PP.Lex(Tok); // ,
604 // If we've got a comma, we either need a label or a string.
605 if (Tok.isAnyIdentifier()) {
606 SlotLabel = Tok.getIdentifierInfo()->getName();
607 PP.Lex(Tok); // identifier
608 if (Tok.is(tok::comma))
609 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000610 else if (Tok.isNot(tok::r_paren)) {
611 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
612 << PragmaName;
613 return false;
614 }
Warren Huntc3b18962014-04-08 22:30:47 +0000615 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000616 } else if (Tok.isNot(tok::r_paren)) {
617 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
618 return false;
619 }
Warren Huntc3b18962014-04-08 22:30:47 +0000620 }
621 }
622 // Grab the string literal for our section name.
623 StringLiteral *SegmentName = nullptr;
624 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000625 if (Tok.isNot(tok::string_literal)) {
626 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000627 diag::warn_pragma_expected_section_name :
628 diag::warn_pragma_expected_section_label_or_name :
629 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000630 PP.Diag(PragmaLocation, DiagID) << PragmaName;
631 return false;
632 }
633 ExprResult StringResult = ParseStringLiteralExpression();
634 if (StringResult.isInvalid())
635 return false; // Already diagnosed.
636 SegmentName = cast<StringLiteral>(StringResult.get());
637 if (SegmentName->getCharByteWidth() != 1) {
638 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
639 << PragmaName;
640 return false;
641 }
Warren Huntc3b18962014-04-08 22:30:47 +0000642 // Setting section "" has no effect
643 if (SegmentName->getLength())
644 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
645 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000646 if (Tok.isNot(tok::r_paren)) {
647 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
648 return false;
649 }
Warren Huntc3b18962014-04-08 22:30:47 +0000650 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000651 if (Tok.isNot(tok::eof)) {
652 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
653 << PragmaName;
654 return false;
655 }
Warren Huntc3b18962014-04-08 22:30:47 +0000656 PP.Lex(Tok); // eof
657 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
658 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000659 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000660}
661
Reid Kleckner1a711b12014-07-22 00:53:05 +0000662// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000663bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
664 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000665 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
666 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
667 return false;
668 }
669
Reid Kleckner1a711b12014-07-22 00:53:05 +0000670 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
671 PragmaName))
672 return false;
673
674 // Parse either the known section names or the string section name.
675 StringLiteral *SegmentName = nullptr;
676 if (Tok.isAnyIdentifier()) {
677 auto *II = Tok.getIdentifierInfo();
678 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
679 .Case("compiler", "\".CRT$XCC\"")
680 .Case("lib", "\".CRT$XCL\"")
681 .Case("user", "\".CRT$XCU\"")
682 .Default("");
683
684 if (!Section.empty()) {
685 // Pretend the user wrote the appropriate string literal here.
686 Token Toks[1];
687 Toks[0].startToken();
688 Toks[0].setKind(tok::string_literal);
689 Toks[0].setLocation(Tok.getLocation());
690 Toks[0].setLiteralData(Section.data());
691 Toks[0].setLength(Section.size());
692 SegmentName =
693 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
694 PP.Lex(Tok);
695 }
696 } else if (Tok.is(tok::string_literal)) {
697 ExprResult StringResult = ParseStringLiteralExpression();
698 if (StringResult.isInvalid())
699 return false;
700 SegmentName = cast<StringLiteral>(StringResult.get());
701 if (SegmentName->getCharByteWidth() != 1) {
702 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
703 << PragmaName;
704 return false;
705 }
706 // FIXME: Add support for the '[, func-name]' part of the pragma.
707 }
708
709 if (!SegmentName) {
710 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
711 return false;
712 }
713
714 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
715 PragmaName) ||
716 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
717 PragmaName))
718 return false;
719
720 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
721 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000722}
723
724struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000725 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000726 Token Option;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000727 Token *Toks;
728 size_t TokSize;
729 PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {}
Eli Bendersky06a40422014-06-06 20:31:48 +0000730};
731
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000732static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
733 std::string PragmaString;
734 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
735 PragmaString = "clang loop ";
736 PragmaString += Option.getIdentifierInfo()->getName();
737 } else {
738 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
739 "Unexpected pragma name");
740 PragmaString = "unroll";
741 }
742 return PragmaString;
743}
744
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000745bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +0000746 assert(Tok.is(tok::annot_pragma_loop_hint));
747 PragmaLoopHintInfo *Info =
748 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
749
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000750 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
751 Hint.PragmaNameLoc = IdentifierLoc::create(
752 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +0000753
Aaron Ballmanef940aa2014-07-31 21:24:32 +0000754 // It is possible that the loop hint has no option identifier, such as
755 // #pragma unroll(4).
756 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
757 ? Info->Option.getIdentifierInfo()
758 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000759 Hint.OptionLoc = IdentifierLoc::create(
760 Actions.Context, Info->Option.getLocation(), OptionInfo);
761
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000762 Token *Toks = Info->Toks;
763 size_t TokSize = Info->TokSize;
764
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000765 // Return a valid hint if pragma unroll or nounroll were specified
766 // without an argument.
767 bool PragmaUnroll = PragmaNameInfo->getName() == "unroll";
768 bool PragmaNoUnroll = PragmaNameInfo->getName() == "nounroll";
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000769 if (TokSize == 0 && (PragmaUnroll || PragmaNoUnroll)) {
770 ConsumeToken(); // The annotation token.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000771 Hint.Range = Info->PragmaName.getLocation();
772 return true;
773 }
774
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000775 // The constant expression is always followed by an eof token, which increases
776 // the TokSize by 1.
777 assert(TokSize > 0 &&
778 "PragmaLoopHintInfo::Toks must contain at least one token.");
779
780 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000781 bool StateOption = false;
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000782 if (OptionInfo) { // Pragma unroll does not specify an option.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000783 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
784 .Case("vectorize", true)
785 .Case("interleave", true)
786 .Case("unroll", true)
787 .Default(false);
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000788 }
789
790 // Verify loop hint has an argument.
791 if (Toks[0].is(tok::eof)) {
792 ConsumeToken(); // The annotation token.
793 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
794 << /*StateArgument=*/StateOption << /*FullKeyword=*/PragmaUnroll;
795 return false;
796 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000797
798 // Validate the argument.
799 if (StateOption) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000800 ConsumeToken(); // The annotation token.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000801 bool OptionUnroll = OptionInfo->isStr("unroll");
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000802 SourceLocation StateLoc = Toks[0].getLocation();
803 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000804 if (!StateInfo || ((OptionUnroll ? !StateInfo->isStr("full")
805 : !StateInfo->isStr("enable")) &&
806 !StateInfo->isStr("disable"))) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000807 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
808 << /*FullKeyword=*/OptionUnroll;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000809 return false;
810 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000811 if (TokSize > 2)
812 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
813 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000814 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
815 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000816 // Enter constant expression including eof terminator into token stream.
817 PP.EnterTokenStream(Toks, TokSize, /*DisableMacroExpansion=*/false,
818 /*OwnsTokens=*/false);
819 ConsumeToken(); // The annotation token.
820
821 ExprResult R = ParseConstantExpression();
822
823 // Tokens following an error in an ill-formed constant expression will
824 // remain in the token stream and must be removed.
825 if (Tok.isNot(tok::eof)) {
826 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
827 << PragmaLoopHintString(Info->PragmaName, Info->Option);
828 while (Tok.isNot(tok::eof))
829 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000830 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000831
832 ConsumeToken(); // Consume the constant expression eof terminator.
833
834 if (R.isInvalid() ||
835 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
836 return false;
837
838 // Argument is a constant expression with an integer type.
839 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000840 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000841
Tyler Nowickic724a83e2014-10-12 20:46:07 +0000842 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
843 Info->Toks[TokSize - 1].getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +0000844 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000845}
846
847// #pragma GCC visibility comes in two variants:
848// 'push' '(' [visibility] ')'
849// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000850void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
851 PragmaIntroducerKind Introducer,
852 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000853 SourceLocation VisLoc = VisTok.getLocation();
854
855 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000856 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000857
858 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
859
Eli Friedman570024a2010-08-05 06:57:20 +0000860 const IdentifierInfo *VisType;
861 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +0000862 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +0000863 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000864 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000865 if (Tok.isNot(tok::l_paren)) {
866 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
867 << "visibility";
868 return;
869 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000870 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000871 VisType = Tok.getIdentifierInfo();
872 if (!VisType) {
873 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
874 << "visibility";
875 return;
876 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000877 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000878 if (Tok.isNot(tok::r_paren)) {
879 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
880 << "visibility";
881 return;
882 }
883 } else {
884 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
885 << "visibility";
886 return;
887 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000888 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000889 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000890 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
891 << "visibility";
892 return;
893 }
894
Rafael Espindola273fd772012-01-26 02:02:57 +0000895 Token *Toks = new Token[1];
896 Toks[0].startToken();
897 Toks[0].setKind(tok::annot_pragma_vis);
898 Toks[0].setLocation(VisLoc);
899 Toks[0].setAnnotationValue(
900 const_cast<void*>(static_cast<const void*>(VisType)));
901 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
902 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000903}
904
Daniel Dunbar921b9682008-10-04 19:21:03 +0000905// #pragma pack(...) comes in the following delicious flavors:
906// pack '(' [integer] ')'
907// pack '(' 'show' ')'
908// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000909void PragmaPackHandler::HandlePragma(Preprocessor &PP,
910 PragmaIntroducerKind Introducer,
911 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000912 SourceLocation PackLoc = PackTok.getLocation();
913
914 Token Tok;
915 PP.Lex(Tok);
916 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000917 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000918 return;
919 }
920
John McCallfaf5fb42010-08-26 23:41:50 +0000921 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Craig Topper161e4db2014-05-21 06:02:52 +0000922 IdentifierInfo *Name = nullptr;
Eli Friedman68be1642012-10-04 02:36:51 +0000923 Token Alignment;
924 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000925 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000926 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000927 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000928 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000929
930 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000931
932 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
933 // the push/pop stack.
934 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000935 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000936 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000937 } else if (Tok.is(tok::identifier)) {
938 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000939 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000940 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000941 PP.Lex(Tok);
942 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000943 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000944 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000945 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000946 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000947 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000948 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000949 return;
Mike Stump11289f42009-09-09 15:08:12 +0000950 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000951 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000952
Daniel Dunbar921b9682008-10-04 19:21:03 +0000953 if (Tok.is(tok::comma)) {
954 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000955
Daniel Dunbar921b9682008-10-04 19:21:03 +0000956 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000957 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000958
959 PP.Lex(Tok);
960 } else if (Tok.is(tok::identifier)) {
961 Name = Tok.getIdentifierInfo();
962 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000963
Daniel Dunbar921b9682008-10-04 19:21:03 +0000964 if (Tok.is(tok::comma)) {
965 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000966
Daniel Dunbar921b9682008-10-04 19:21:03 +0000967 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000968 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000969 return;
970 }
Mike Stump11289f42009-09-09 15:08:12 +0000971
Eli Friedman68be1642012-10-04 02:36:51 +0000972 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000973
974 PP.Lex(Tok);
975 }
976 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000977 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000978 return;
979 }
980 }
981 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000982 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000983 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
984 // the push/pop stack.
985 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
986 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000987 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000988
989 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000990 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000991 return;
992 }
993
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000994 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000995 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000996 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000997 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
998 return;
999 }
1000
Daniel Dunbar340cf242012-02-29 01:38:22 +00001001 PragmaPackInfo *Info =
1002 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
1003 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
1004 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +00001005 Info->Kind = Kind;
1006 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +00001007 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001008 Info->LParenLoc = LParenLoc;
1009 Info->RParenLoc = RParenLoc;
1010
Daniel Dunbar340cf242012-02-29 01:38:22 +00001011 Token *Toks =
1012 (Token*) PP.getPreprocessorAllocator().Allocate(
1013 sizeof(Token) * 1, llvm::alignOf<Token>());
1014 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +00001015 Toks[0].startToken();
1016 Toks[0].setKind(tok::annot_pragma_pack);
1017 Toks[0].setLocation(PackLoc);
1018 Toks[0].setAnnotationValue(static_cast<void*>(Info));
1019 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +00001020 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001021}
1022
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001023// #pragma ms_struct on
1024// #pragma ms_struct off
1025void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
1026 PragmaIntroducerKind Introducer,
1027 Token &MSStructTok) {
1028 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
1029
1030 Token Tok;
1031 PP.Lex(Tok);
1032 if (Tok.isNot(tok::identifier)) {
1033 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1034 return;
1035 }
1036 const IdentifierInfo *II = Tok.getIdentifierInfo();
1037 if (II->isStr("on")) {
1038 Kind = Sema::PMSST_ON;
1039 PP.Lex(Tok);
1040 }
1041 else if (II->isStr("off") || II->isStr("reset"))
1042 PP.Lex(Tok);
1043 else {
1044 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1045 return;
1046 }
1047
1048 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001049 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1050 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001051 return;
1052 }
Eli Friedman68be1642012-10-04 02:36:51 +00001053
1054 Token *Toks =
1055 (Token*) PP.getPreprocessorAllocator().Allocate(
1056 sizeof(Token) * 1, llvm::alignOf<Token>());
1057 new (Toks) Token();
1058 Toks[0].startToken();
1059 Toks[0].setKind(tok::annot_pragma_msstruct);
1060 Toks[0].setLocation(MSStructTok.getLocation());
1061 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1062 static_cast<uintptr_t>(Kind)));
1063 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1064 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001065}
1066
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001067// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1068// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001069static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001070 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001071 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001072
1073 if (IsOptions) {
1074 PP.Lex(Tok);
1075 if (Tok.isNot(tok::identifier) ||
1076 !Tok.getIdentifierInfo()->isStr("align")) {
1077 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1078 return;
1079 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001080 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001081
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001082 PP.Lex(Tok);
1083 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001084 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1085 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001086 return;
1087 }
1088
1089 PP.Lex(Tok);
1090 if (Tok.isNot(tok::identifier)) {
1091 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001092 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001093 return;
1094 }
1095
John McCallfaf5fb42010-08-26 23:41:50 +00001096 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001097 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001098 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001099 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001100 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001101 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001102 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001103 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001104 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001105 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001106 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001107 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001108 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001109 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001110 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001111 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1112 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001113 return;
1114 }
1115
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001116 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001117 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001118 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001119 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001120 return;
1121 }
1122
Eli Friedman68be1642012-10-04 02:36:51 +00001123 Token *Toks =
1124 (Token*) PP.getPreprocessorAllocator().Allocate(
1125 sizeof(Token) * 1, llvm::alignOf<Token>());
1126 new (Toks) Token();
1127 Toks[0].startToken();
1128 Toks[0].setKind(tok::annot_pragma_align);
1129 Toks[0].setLocation(FirstTok.getLocation());
1130 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1131 static_cast<uintptr_t>(Kind)));
1132 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1133 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001134}
1135
Douglas Gregorc7d65762010-09-09 22:45:38 +00001136void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1137 PragmaIntroducerKind Introducer,
1138 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001139 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001140}
1141
Douglas Gregorc7d65762010-09-09 22:45:38 +00001142void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1143 PragmaIntroducerKind Introducer,
1144 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001145 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001146}
1147
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001148// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001149void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1150 PragmaIntroducerKind Introducer,
1151 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001152 // FIXME: Should we be expanding macros here? My guess is no.
1153 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001154
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001155 // Lex the left '('.
1156 Token Tok;
1157 PP.Lex(Tok);
1158 if (Tok.isNot(tok::l_paren)) {
1159 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1160 return;
1161 }
Mike Stump11289f42009-09-09 15:08:12 +00001162
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001163 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001164 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001165 SourceLocation RParenLoc;
1166 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001167
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001168 while (true) {
1169 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001170
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001171 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001172 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001173 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001174 LexID = false;
1175 continue;
1176 }
1177
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001178 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001179 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1180 return;
1181 }
Mike Stump11289f42009-09-09 15:08:12 +00001182
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001183 // We are execting a ')' or a ','.
1184 if (Tok.is(tok::comma)) {
1185 LexID = true;
1186 continue;
1187 }
Mike Stump11289f42009-09-09 15:08:12 +00001188
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001189 if (Tok.is(tok::r_paren)) {
1190 RParenLoc = Tok.getLocation();
1191 break;
1192 }
Mike Stump11289f42009-09-09 15:08:12 +00001193
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001194 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001195 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001196 return;
1197 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001198
1199 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001200 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001201 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1202 "unused";
1203 return;
1204 }
1205
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001206 // Verify that we have a location for the right parenthesis.
1207 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001208 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001209
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001210 // For each identifier token, insert into the token stream a
1211 // annot_pragma_unused token followed by the identifier token.
1212 // This allows us to cache a "#pragma unused" that occurs inside an inline
1213 // C++ member function.
1214
Daniel Dunbar340cf242012-02-29 01:38:22 +00001215 Token *Toks =
1216 (Token*) PP.getPreprocessorAllocator().Allocate(
1217 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001218 for (unsigned i=0; i != Identifiers.size(); i++) {
1219 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1220 pragmaUnusedTok.startToken();
1221 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1222 pragmaUnusedTok.setLocation(UnusedLoc);
1223 idTok = Identifiers[i];
1224 }
Daniel Dunbar340cf242012-02-29 01:38:22 +00001225 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1226 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001227}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001228
1229// #pragma weak identifier
1230// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001231void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1232 PragmaIntroducerKind Introducer,
1233 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001234 SourceLocation WeakLoc = WeakTok.getLocation();
1235
1236 Token Tok;
1237 PP.Lex(Tok);
1238 if (Tok.isNot(tok::identifier)) {
1239 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1240 return;
1241 }
1242
Eli Friedman68be1642012-10-04 02:36:51 +00001243 Token WeakName = Tok;
1244 bool HasAlias = false;
1245 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001246
1247 PP.Lex(Tok);
1248 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001249 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001250 PP.Lex(Tok);
1251 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001252 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001253 << "weak";
1254 return;
1255 }
Eli Friedman68be1642012-10-04 02:36:51 +00001256 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001257 PP.Lex(Tok);
1258 }
1259
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001260 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001261 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1262 return;
1263 }
1264
Eli Friedman68be1642012-10-04 02:36:51 +00001265 if (HasAlias) {
1266 Token *Toks =
1267 (Token*) PP.getPreprocessorAllocator().Allocate(
1268 sizeof(Token) * 3, llvm::alignOf<Token>());
1269 Token &pragmaUnusedTok = Toks[0];
1270 pragmaUnusedTok.startToken();
1271 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1272 pragmaUnusedTok.setLocation(WeakLoc);
1273 Toks[1] = WeakName;
1274 Toks[2] = AliasName;
1275 PP.EnterTokenStream(Toks, 3,
1276 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001277 } else {
Eli Friedman68be1642012-10-04 02:36:51 +00001278 Token *Toks =
1279 (Token*) PP.getPreprocessorAllocator().Allocate(
1280 sizeof(Token) * 2, llvm::alignOf<Token>());
1281 Token &pragmaUnusedTok = Toks[0];
1282 pragmaUnusedTok.startToken();
1283 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1284 pragmaUnusedTok.setLocation(WeakLoc);
1285 Toks[1] = WeakName;
1286 PP.EnterTokenStream(Toks, 2,
1287 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001288 }
1289}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001290
David Chisnall0867d9c2012-02-18 16:12:34 +00001291// #pragma redefine_extname identifier identifier
1292void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1293 PragmaIntroducerKind Introducer,
1294 Token &RedefToken) {
1295 SourceLocation RedefLoc = RedefToken.getLocation();
1296
1297 Token Tok;
1298 PP.Lex(Tok);
1299 if (Tok.isNot(tok::identifier)) {
1300 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1301 "redefine_extname";
1302 return;
1303 }
1304
Eli Friedman68be1642012-10-04 02:36:51 +00001305 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001306 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001307
David Chisnall0867d9c2012-02-18 16:12:34 +00001308 if (Tok.isNot(tok::identifier)) {
1309 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1310 << "redefine_extname";
1311 return;
1312 }
Eli Friedman68be1642012-10-04 02:36:51 +00001313
1314 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001315 PP.Lex(Tok);
1316
1317 if (Tok.isNot(tok::eod)) {
1318 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1319 "redefine_extname";
1320 return;
1321 }
1322
Eli Friedman68be1642012-10-04 02:36:51 +00001323 Token *Toks =
1324 (Token*) PP.getPreprocessorAllocator().Allocate(
1325 sizeof(Token) * 3, llvm::alignOf<Token>());
1326 Token &pragmaRedefTok = Toks[0];
1327 pragmaRedefTok.startToken();
1328 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1329 pragmaRedefTok.setLocation(RedefLoc);
1330 Toks[1] = RedefName;
1331 Toks[2] = AliasName;
1332 PP.EnterTokenStream(Toks, 3,
1333 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00001334}
1335
1336
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001337void
1338PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1339 PragmaIntroducerKind Introducer,
1340 Token &Tok) {
1341 tok::OnOffSwitch OOS;
1342 if (PP.LexOnOffSwitch(OOS))
1343 return;
1344
Eli Friedman68be1642012-10-04 02:36:51 +00001345 Token *Toks =
1346 (Token*) PP.getPreprocessorAllocator().Allocate(
1347 sizeof(Token) * 1, llvm::alignOf<Token>());
1348 new (Toks) Token();
1349 Toks[0].startToken();
1350 Toks[0].setKind(tok::annot_pragma_fp_contract);
1351 Toks[0].setLocation(Tok.getLocation());
1352 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1353 static_cast<uintptr_t>(OOS)));
1354 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1355 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001356}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001357
1358void
1359PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1360 PragmaIntroducerKind Introducer,
1361 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001362 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001363 if (Tok.isNot(tok::identifier)) {
1364 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1365 "OPENCL";
1366 return;
1367 }
1368 IdentifierInfo *ename = Tok.getIdentifierInfo();
1369 SourceLocation NameLoc = Tok.getLocation();
1370
1371 PP.Lex(Tok);
1372 if (Tok.isNot(tok::colon)) {
1373 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1374 return;
1375 }
1376
1377 PP.Lex(Tok);
1378 if (Tok.isNot(tok::identifier)) {
1379 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1380 return;
1381 }
1382 IdentifierInfo *op = Tok.getIdentifierInfo();
1383
1384 unsigned state;
1385 if (op->isStr("enable")) {
1386 state = 1;
1387 } else if (op->isStr("disable")) {
1388 state = 0;
1389 } else {
1390 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1391 return;
1392 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001393 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001394
Eli Friedman68be1642012-10-04 02:36:51 +00001395 PP.Lex(Tok);
1396 if (Tok.isNot(tok::eod)) {
1397 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1398 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001399 return;
1400 }
Eli Friedman68be1642012-10-04 02:36:51 +00001401
1402 OpenCLExtData data(ename, state);
1403 Token *Toks =
1404 (Token*) PP.getPreprocessorAllocator().Allocate(
1405 sizeof(Token) * 1, llvm::alignOf<Token>());
1406 new (Toks) Token();
1407 Toks[0].startToken();
1408 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1409 Toks[0].setLocation(NameLoc);
1410 Toks[0].setAnnotationValue(data.getOpaqueValue());
1411 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1412 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001413
1414 if (PP.getPPCallbacks())
1415 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1416 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001417}
1418
Alexey Bataeva769e072013-03-22 06:34:35 +00001419/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1420///
1421void
1422PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1423 PragmaIntroducerKind Introducer,
1424 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00001425 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1426 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00001427 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00001428 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1429 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00001430 }
1431 PP.DiscardUntilEndOfDirective();
1432}
1433
1434/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1435///
1436void
1437PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1438 PragmaIntroducerKind Introducer,
1439 Token &FirstTok) {
1440 SmallVector<Token, 16> Pragma;
1441 Token Tok;
1442 Tok.startToken();
1443 Tok.setKind(tok::annot_pragma_openmp);
1444 Tok.setLocation(FirstTok.getLocation());
1445
1446 while (Tok.isNot(tok::eod)) {
1447 Pragma.push_back(Tok);
1448 PP.Lex(Tok);
1449 }
1450 SourceLocation EodLoc = Tok.getLocation();
1451 Tok.startToken();
1452 Tok.setKind(tok::annot_pragma_openmp_end);
1453 Tok.setLocation(EodLoc);
1454 Pragma.push_back(Tok);
1455
1456 Token *Toks = new Token[Pragma.size()];
1457 std::copy(Pragma.begin(), Pragma.end(), Toks);
1458 PP.EnterTokenStream(Toks, Pragma.size(),
1459 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1460}
Reid Kleckner002562a2013-05-06 21:02:12 +00001461
David Majnemer4bb09802014-02-10 19:50:15 +00001462/// \brief Handle '#pragma pointers_to_members'
1463// The grammar for this pragma is as follows:
1464//
1465// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1466//
1467// #pragma pointers_to_members '(' 'best_case' ')'
1468// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1469// #pragma pointers_to_members '(' inheritance-model ')'
1470void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1471 PragmaIntroducerKind Introducer,
1472 Token &Tok) {
1473 SourceLocation PointersToMembersLoc = Tok.getLocation();
1474 PP.Lex(Tok);
1475 if (Tok.isNot(tok::l_paren)) {
1476 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1477 << "pointers_to_members";
1478 return;
1479 }
1480 PP.Lex(Tok);
1481 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1482 if (!Arg) {
1483 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1484 << "pointers_to_members";
1485 return;
1486 }
1487 PP.Lex(Tok);
1488
David Majnemer86c318f2014-02-11 21:05:00 +00001489 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001490 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001491 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001492 } else {
1493 if (Arg->isStr("full_generality")) {
1494 if (Tok.is(tok::comma)) {
1495 PP.Lex(Tok);
1496
1497 Arg = Tok.getIdentifierInfo();
1498 if (!Arg) {
1499 PP.Diag(Tok.getLocation(),
1500 diag::err_pragma_pointers_to_members_unknown_kind)
1501 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1502 return;
1503 }
1504 PP.Lex(Tok);
1505 } else if (Tok.is(tok::r_paren)) {
1506 // #pragma pointers_to_members(full_generality) implicitly specifies
1507 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00001508 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00001509 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001510 } else {
1511 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1512 << "full_generality";
1513 return;
1514 }
1515 }
1516
1517 if (Arg) {
1518 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001519 RepresentationMethod =
1520 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001521 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001522 RepresentationMethod =
1523 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001524 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001525 RepresentationMethod =
1526 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001527 } else {
1528 PP.Diag(Tok.getLocation(),
1529 diag::err_pragma_pointers_to_members_unknown_kind)
1530 << Arg << /*HasPointerDeclaration*/ 1;
1531 return;
1532 }
1533 }
1534 }
1535
1536 if (Tok.isNot(tok::r_paren)) {
1537 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1538 << (Arg ? Arg->getName() : "full_generality");
1539 return;
1540 }
1541
1542 PP.Lex(Tok);
1543 if (Tok.isNot(tok::eod)) {
1544 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1545 << "pointers_to_members";
1546 return;
1547 }
1548
1549 Token AnnotTok;
1550 AnnotTok.startToken();
1551 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1552 AnnotTok.setLocation(PointersToMembersLoc);
1553 AnnotTok.setAnnotationValue(
1554 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1555 PP.EnterToken(AnnotTok);
1556}
1557
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001558/// \brief Handle '#pragma vtordisp'
1559// The grammar for this pragma is as follows:
1560//
1561// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1562//
1563// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1564// #pragma vtordisp '(' 'pop' ')'
1565// #pragma vtordisp '(' ')'
1566void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1567 PragmaIntroducerKind Introducer,
1568 Token &Tok) {
1569 SourceLocation VtorDispLoc = Tok.getLocation();
1570 PP.Lex(Tok);
1571 if (Tok.isNot(tok::l_paren)) {
1572 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1573 return;
1574 }
1575 PP.Lex(Tok);
1576
1577 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1578 const IdentifierInfo *II = Tok.getIdentifierInfo();
1579 if (II) {
1580 if (II->isStr("push")) {
1581 // #pragma vtordisp(push, mode)
1582 PP.Lex(Tok);
1583 if (Tok.isNot(tok::comma)) {
1584 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1585 return;
1586 }
1587 PP.Lex(Tok);
1588 Kind = Sema::PVDK_Push;
1589 // not push, could be on/off
1590 } else if (II->isStr("pop")) {
1591 // #pragma vtordisp(pop)
1592 PP.Lex(Tok);
1593 Kind = Sema::PVDK_Pop;
1594 }
1595 // not push or pop, could be on/off
1596 } else {
1597 if (Tok.is(tok::r_paren)) {
1598 // #pragma vtordisp()
1599 Kind = Sema::PVDK_Reset;
1600 }
1601 }
1602
1603
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001604 uint64_t Value = 0;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001605 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1606 const IdentifierInfo *II = Tok.getIdentifierInfo();
1607 if (II && II->isStr("off")) {
1608 PP.Lex(Tok);
1609 Value = 0;
1610 } else if (II && II->isStr("on")) {
1611 PP.Lex(Tok);
1612 Value = 1;
1613 } else if (Tok.is(tok::numeric_constant) &&
1614 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1615 if (Value > 2) {
1616 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1617 << 0 << 2 << "vtordisp";
1618 return;
1619 }
1620 } else {
1621 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1622 << "vtordisp";
1623 return;
1624 }
1625 }
1626
1627 // Finish the pragma: ')' $
1628 if (Tok.isNot(tok::r_paren)) {
1629 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1630 return;
1631 }
1632 PP.Lex(Tok);
1633 if (Tok.isNot(tok::eod)) {
1634 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1635 << "vtordisp";
1636 return;
1637 }
1638
1639 // Enter the annotation.
1640 Token AnnotTok;
1641 AnnotTok.startToken();
1642 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1643 AnnotTok.setLocation(VtorDispLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001644 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1645 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001646 PP.EnterToken(AnnotTok);
1647}
1648
Warren Huntc3b18962014-04-08 22:30:47 +00001649/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1650/// an annotation token.
1651void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1652 PragmaIntroducerKind Introducer,
1653 Token &Tok) {
1654 Token EoF, AnnotTok;
1655 EoF.startToken();
1656 EoF.setKind(tok::eof);
1657 AnnotTok.startToken();
1658 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1659 AnnotTok.setLocation(Tok.getLocation());
1660 SmallVector<Token, 8> TokenVector;
1661 // Suck up all of the tokens before the eod.
1662 for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1663 TokenVector.push_back(Tok);
1664 // Add a sentinal EoF token to the end of the list.
1665 TokenVector.push_back(EoF);
1666 // We must allocate this array with new because EnterTokenStream is going to
1667 // delete it later.
1668 Token *TokenArray = new Token[TokenVector.size()];
1669 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1670 auto Value = new (PP.getPreprocessorAllocator())
1671 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1672 AnnotTok.setAnnotationValue(Value);
1673 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001674}
1675
Aaron Ballman5d041be2013-06-04 02:07:14 +00001676/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1677///
1678/// The syntax is:
1679/// \code
1680/// #pragma detect_mismatch("name", "value")
1681/// \endcode
1682/// Where 'name' and 'value' are quoted strings. The values are embedded in
1683/// the object file and passed along to the linker. If the linker detects a
1684/// mismatch in the object file's values for the given name, a LNK2038 error
1685/// is emitted. See MSDN for more details.
1686void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1687 PragmaIntroducerKind Introducer,
1688 Token &Tok) {
1689 SourceLocation CommentLoc = Tok.getLocation();
1690 PP.Lex(Tok);
1691 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001692 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001693 return;
1694 }
1695
1696 // Read the name to embed, which must be a string literal.
1697 std::string NameString;
1698 if (!PP.LexStringLiteral(Tok, NameString,
1699 "pragma detect_mismatch",
1700 /*MacroExpansion=*/true))
1701 return;
1702
1703 // Read the comma followed by a second string literal.
1704 std::string ValueString;
1705 if (Tok.isNot(tok::comma)) {
1706 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1707 return;
1708 }
1709
1710 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1711 /*MacroExpansion=*/true))
1712 return;
1713
1714 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001715 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001716 return;
1717 }
1718 PP.Lex(Tok); // Eat the r_paren.
1719
1720 if (Tok.isNot(tok::eod)) {
1721 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1722 return;
1723 }
1724
Reid Kleckner71966c92014-02-20 23:37:45 +00001725 // If the pragma is lexically sound, notify any interested PPCallbacks.
1726 if (PP.getPPCallbacks())
1727 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1728 ValueString);
1729
Aaron Ballman5d041be2013-06-04 02:07:14 +00001730 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1731}
1732
Reid Kleckner002562a2013-05-06 21:02:12 +00001733/// \brief Handle the microsoft \#pragma comment extension.
1734///
1735/// The syntax is:
1736/// \code
1737/// #pragma comment(linker, "foo")
1738/// \endcode
1739/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1740/// "foo" is a string, which is fully macro expanded, and permits string
1741/// concatenation, embedded escape characters etc. See MSDN for more details.
1742void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1743 PragmaIntroducerKind Introducer,
1744 Token &Tok) {
1745 SourceLocation CommentLoc = Tok.getLocation();
1746 PP.Lex(Tok);
1747 if (Tok.isNot(tok::l_paren)) {
1748 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1749 return;
1750 }
1751
1752 // Read the identifier.
1753 PP.Lex(Tok);
1754 if (Tok.isNot(tok::identifier)) {
1755 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1756 return;
1757 }
1758
1759 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001760 IdentifierInfo *II = Tok.getIdentifierInfo();
1761 Sema::PragmaMSCommentKind Kind =
1762 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1763 .Case("linker", Sema::PCK_Linker)
1764 .Case("lib", Sema::PCK_Lib)
1765 .Case("compiler", Sema::PCK_Compiler)
1766 .Case("exestr", Sema::PCK_ExeStr)
1767 .Case("user", Sema::PCK_User)
1768 .Default(Sema::PCK_Unknown);
1769 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001770 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1771 return;
1772 }
1773
1774 // Read the optional string if present.
1775 PP.Lex(Tok);
1776 std::string ArgumentString;
1777 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1778 "pragma comment",
1779 /*MacroExpansion=*/true))
1780 return;
1781
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001782 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001783 // FIXME: If the kind is "compiler" warn if the string is present (it is
1784 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001785 // The MSDN docs say that "lib" and "linker" require a string and have a short
1786 // whitelist of linker options they support, but in practice MSVC doesn't
1787 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001788
1789 if (Tok.isNot(tok::r_paren)) {
1790 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1791 return;
1792 }
1793 PP.Lex(Tok); // eat the r_paren.
1794
1795 if (Tok.isNot(tok::eod)) {
1796 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1797 return;
1798 }
1799
Reid Kleckner71966c92014-02-20 23:37:45 +00001800 // If the pragma is lexically sound, notify any interested PPCallbacks.
1801 if (PP.getPPCallbacks())
1802 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1803
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001804 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001805}
Dario Domizioli13a0a382014-05-23 12:13:25 +00001806
1807// #pragma clang optimize off
1808// #pragma clang optimize on
1809void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1810 PragmaIntroducerKind Introducer,
1811 Token &FirstToken) {
1812 Token Tok;
1813 PP.Lex(Tok);
1814 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001815 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00001816 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00001817 return;
1818 }
1819 if (Tok.isNot(tok::identifier)) {
1820 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1821 << PP.getSpelling(Tok);
1822 return;
1823 }
1824 const IdentifierInfo *II = Tok.getIdentifierInfo();
1825 // The only accepted values are 'on' or 'off'.
1826 bool IsOn = false;
1827 if (II->isStr("on")) {
1828 IsOn = true;
1829 } else if (!II->isStr("off")) {
1830 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1831 << PP.getSpelling(Tok);
1832 return;
1833 }
1834 PP.Lex(Tok);
1835
1836 if (Tok.isNot(tok::eod)) {
1837 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1838 << PP.getSpelling(Tok);
1839 return;
1840 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001841
1842 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1843}
1844
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001845/// \brief Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001846static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
1847 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001848 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001849 SmallVector<Token, 1> ValueList;
1850 int OpenParens = ValueInParens ? 1 : 0;
1851 // Read constant expression.
1852 while (Tok.isNot(tok::eod)) {
1853 if (Tok.is(tok::l_paren))
1854 OpenParens++;
1855 else if (Tok.is(tok::r_paren)) {
1856 OpenParens--;
1857 if (OpenParens == 0 && ValueInParens)
1858 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001859 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001860
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001861 ValueList.push_back(Tok);
1862 PP.Lex(Tok);
1863 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001864
1865 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001866 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001867 if (Tok.isNot(tok::r_paren)) {
1868 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1869 return true;
1870 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001871 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001872 }
1873
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001874 Token EOFTok;
1875 EOFTok.startToken();
1876 EOFTok.setKind(tok::eof);
1877 EOFTok.setLocation(Tok.getLocation());
1878 ValueList.push_back(EOFTok); // Terminates expression for parsing.
1879
1880 Token *TokenArray =
1881 new (PP.getPreprocessorAllocator()) Token[ValueList.size()];
1882 std::copy(ValueList.begin(), ValueList.end(), TokenArray);
1883 Info.Toks = TokenArray;
1884 Info.TokSize = ValueList.size();
1885
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001886 Info.PragmaName = PragmaName;
1887 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001888 return false;
1889}
1890
Eli Bendersky06a40422014-06-06 20:31:48 +00001891/// \brief Handle the \#pragma clang loop directive.
1892/// #pragma clang 'loop' loop-hints
1893///
1894/// loop-hints:
1895/// loop-hint loop-hints[opt]
1896///
1897/// loop-hint:
1898/// 'vectorize' '(' loop-hint-keyword ')'
1899/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00001900/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001901/// 'vectorize_width' '(' loop-hint-value ')'
1902/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00001903/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001904///
1905/// loop-hint-keyword:
1906/// 'enable'
1907/// 'disable'
1908///
Mark Heffernan450c2382014-07-23 17:31:31 +00001909/// unroll-hint-keyword:
1910/// 'full'
1911/// 'disable'
1912///
Eli Bendersky06a40422014-06-06 20:31:48 +00001913/// loop-hint-value:
1914/// constant-expression
1915///
1916/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1917/// try vectorizing the instructions of the loop it precedes. Specifying
1918/// interleave(enable) or interleave_count(_value_) instructs llvm to try
1919/// interleaving multiple iterations of the loop it precedes. The width of the
1920/// vector instructions is specified by vectorize_width() and the number of
1921/// interleaved loop iterations is specified by interleave_count(). Specifying a
1922/// value of 1 effectively disables vectorization/interleaving, even if it is
1923/// possible and profitable, and 0 is invalid. The loop vectorizer currently
1924/// only works on inner loops.
1925///
Eli Bendersky86483b32014-06-11 17:56:26 +00001926/// The unroll and unroll_count directives control the concatenation
Mark Heffernan450c2382014-07-23 17:31:31 +00001927/// unroller. Specifying unroll(full) instructs llvm to try to
Eli Bendersky86483b32014-06-11 17:56:26 +00001928/// unroll the loop completely, and unroll(disable) disables unrolling
1929/// for the loop. Specifying unroll_count(_value_) instructs llvm to
1930/// try to unroll the loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00001931void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1932 PragmaIntroducerKind Introducer,
1933 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001934 // Incoming token is "loop" from "#pragma clang loop".
1935 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00001936 SmallVector<Token, 1> TokenList;
1937
1938 // Lex the optimization option and verify it is an identifier.
1939 PP.Lex(Tok);
1940 if (Tok.isNot(tok::identifier)) {
1941 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1942 << /*MissingOption=*/true << "";
1943 return;
1944 }
1945
1946 while (Tok.is(tok::identifier)) {
1947 Token Option = Tok;
1948 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
1949
Eli Bendersky86483b32014-06-11 17:56:26 +00001950 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001951 .Case("vectorize", true)
1952 .Case("interleave", true)
1953 .Case("unroll", true)
1954 .Case("vectorize_width", true)
1955 .Case("interleave_count", true)
1956 .Case("unroll_count", true)
1957 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00001958 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001959 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1960 << /*MissingOption=*/false << OptionInfo;
1961 return;
1962 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00001963 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001964
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001965 // Read '('
1966 if (Tok.isNot(tok::l_paren)) {
1967 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00001968 return;
1969 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001970 PP.Lex(Tok);
1971
1972 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
1973 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
1974 *Info))
1975 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00001976
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001977 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00001978 Token LoopHintTok;
1979 LoopHintTok.startToken();
1980 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001981 LoopHintTok.setLocation(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00001982 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
1983 TokenList.push_back(LoopHintTok);
1984 }
1985
1986 if (Tok.isNot(tok::eod)) {
1987 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1988 << "clang loop";
1989 return;
1990 }
1991
1992 Token *TokenArray = new Token[TokenList.size()];
1993 std::copy(TokenList.begin(), TokenList.end(), TokenArray);
1994
1995 PP.EnterTokenStream(TokenArray, TokenList.size(),
1996 /*DisableMacroExpansion=*/false,
1997 /*OwnsTokens=*/true);
1998}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001999
2000/// \brief Handle the loop unroll optimization pragmas.
2001/// #pragma unroll
2002/// #pragma unroll unroll-hint-value
2003/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002004/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002005///
2006/// unroll-hint-value:
2007/// constant-expression
2008///
Mark Heffernanc888e412014-07-24 18:09:38 +00002009/// Loop unrolling hints can be specified with '#pragma unroll' or
2010/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2011/// contained in parentheses. With no argument the directive instructs llvm to
2012/// try to unroll the loop completely. A positive integer argument can be
2013/// specified to indicate the number of times the loop should be unrolled. To
2014/// maximize compatibility with other compilers the unroll count argument can be
2015/// specified with or without parentheses. Specifying, '#pragma nounroll'
2016/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002017void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
2018 PragmaIntroducerKind Introducer,
2019 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002020 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2021 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002022 Token PragmaName = Tok;
2023 PP.Lex(Tok);
2024 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2025 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002026 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002027 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002028 Info->Option.startToken();
Mark Heffernanc888e412014-07-24 18:09:38 +00002029 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
2030 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2031 << "nounroll";
2032 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002033 } else {
2034 // Unroll pragma with an argument: "#pragma unroll N" or
2035 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002036 // Read '(' if it exists.
2037 bool ValueInParens = Tok.is(tok::l_paren);
2038 if (ValueInParens)
2039 PP.Lex(Tok);
2040
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002041 Token Option;
2042 Option.startToken();
2043 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002044 return;
2045
2046 // In CUDA, the argument to '#pragma unroll' should not be contained in
2047 // parentheses.
2048 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002049 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002050 diag::warn_pragma_unroll_cuda_value_in_parens);
2051
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002052 if (Tok.isNot(tok::eod)) {
2053 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2054 << "unroll";
2055 return;
2056 }
2057 }
2058
2059 // Generate the hint token.
2060 Token *TokenArray = new Token[1];
2061 TokenArray[0].startToken();
2062 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
2063 TokenArray[0].setLocation(PragmaName.getLocation());
2064 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
2065 PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
2066 /*OwnsTokens=*/true);
2067}