blob: 1b343b4291b90a81626236ad6f7f186bbdfb0c8f [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"
Eli Bendersky06a40422014-06-06 20:31:48 +000015#include "clang/Lex/Preprocessor.h"
16#include "clang/Parse/ParseDiagnostic.h"
17#include "clang/Parse/Parser.h"
18#include "clang/Sema/LoopHint.h"
19#include "clang/Sema/Scope.h"
20#include "llvm/ADT/StringSwitch.h"
21using namespace clang;
Daniel Dunbar921b9682008-10-04 19:21:03 +000022
Reid Kleckner5b086462014-02-20 22:52:09 +000023namespace {
24
25struct PragmaAlignHandler : public PragmaHandler {
26 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000027 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
28 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000029};
30
31struct PragmaGCCVisibilityHandler : public PragmaHandler {
32 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000033 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
34 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000035};
36
37struct PragmaOptionsHandler : public PragmaHandler {
38 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000039 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
40 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000041};
42
43struct PragmaPackHandler : public PragmaHandler {
44 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000045 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
46 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000047};
48
49struct PragmaMSStructHandler : public PragmaHandler {
50 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000051 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
52 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000053};
54
55struct PragmaUnusedHandler : public PragmaHandler {
56 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000057 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
58 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000059};
60
61struct PragmaWeakHandler : public PragmaHandler {
62 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
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 PragmaRedefineExtnameHandler : public PragmaHandler {
68 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
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 PragmaOpenCLExtensionHandler : public PragmaHandler {
74 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
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
79
80struct PragmaFPContractHandler : public PragmaHandler {
81 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000082 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
83 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000084};
85
86struct PragmaNoOpenMPHandler : public PragmaHandler {
87 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000088 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
89 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000090};
91
92struct PragmaOpenMPHandler : public PragmaHandler {
93 PragmaOpenMPHandler() : PragmaHandler("omp") { }
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
98/// PragmaCommentHandler - "\#pragma comment ...".
99struct PragmaCommentHandler : public PragmaHandler {
100 PragmaCommentHandler(Sema &Actions)
101 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000102 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
103 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000104private:
105 Sema &Actions;
106};
107
108struct PragmaDetectMismatchHandler : public PragmaHandler {
109 PragmaDetectMismatchHandler(Sema &Actions)
110 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000111 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
112 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000113private:
114 Sema &Actions;
115};
116
117struct PragmaMSPointersToMembers : public PragmaHandler {
118 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000119 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
120 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000121};
122
123struct PragmaMSVtorDisp : public PragmaHandler {
124 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000125 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
126 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000127};
128
Warren Huntc3b18962014-04-08 22:30:47 +0000129struct PragmaMSPragma : public PragmaHandler {
130 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000131 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
132 Token &FirstToken) override;
133};
134
Dario Domizioli13a0a382014-05-23 12:13:25 +0000135/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
136struct PragmaOptimizeHandler : public PragmaHandler {
137 PragmaOptimizeHandler(Sema &S)
138 : PragmaHandler("optimize"), Actions(S) {}
139 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
140 Token &FirstToken) override;
141private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000142 Sema &Actions;
143};
144
145struct PragmaLoopHintHandler : public PragmaHandler {
146 PragmaLoopHintHandler() : PragmaHandler("loop") {}
147 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
148 Token &FirstToken) override;
149};
150
151} // end namespace
152
153void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000154 AlignHandler.reset(new PragmaAlignHandler());
155 PP.AddPragmaHandler(AlignHandler.get());
156
157 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
158 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
159
160 OptionsHandler.reset(new PragmaOptionsHandler());
161 PP.AddPragmaHandler(OptionsHandler.get());
162
163 PackHandler.reset(new PragmaPackHandler());
164 PP.AddPragmaHandler(PackHandler.get());
165
166 MSStructHandler.reset(new PragmaMSStructHandler());
167 PP.AddPragmaHandler(MSStructHandler.get());
168
169 UnusedHandler.reset(new PragmaUnusedHandler());
170 PP.AddPragmaHandler(UnusedHandler.get());
171
172 WeakHandler.reset(new PragmaWeakHandler());
173 PP.AddPragmaHandler(WeakHandler.get());
174
175 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
176 PP.AddPragmaHandler(RedefineExtnameHandler.get());
177
178 FPContractHandler.reset(new PragmaFPContractHandler());
179 PP.AddPragmaHandler("STDC", FPContractHandler.get());
180
181 if (getLangOpts().OpenCL) {
182 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
183 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
184
185 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
186 }
187 if (getLangOpts().OpenMP)
188 OpenMPHandler.reset(new PragmaOpenMPHandler());
189 else
190 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
191 PP.AddPragmaHandler(OpenMPHandler.get());
192
193 if (getLangOpts().MicrosoftExt) {
194 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
195 PP.AddPragmaHandler(MSCommentHandler.get());
196 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
197 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
198 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
199 PP.AddPragmaHandler(MSPointersToMembers.get());
200 MSVtorDisp.reset(new PragmaMSVtorDisp());
201 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000202 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000203 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000204 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
205 PP.AddPragmaHandler(MSDataSeg.get());
206 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
207 PP.AddPragmaHandler(MSBSSSeg.get());
208 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
209 PP.AddPragmaHandler(MSConstSeg.get());
210 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
211 PP.AddPragmaHandler(MSCodeSeg.get());
212 MSSection.reset(new PragmaMSPragma("section"));
213 PP.AddPragmaHandler(MSSection.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000214 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000215
216 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
217 PP.AddPragmaHandler("clang", OptimizeHandler.get());
218
219 LoopHintHandler.reset(new PragmaLoopHintHandler());
220 PP.AddPragmaHandler("clang", LoopHintHandler.get());
221}
222
223void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000224 // Remove the pragma handlers we installed.
225 PP.RemovePragmaHandler(AlignHandler.get());
226 AlignHandler.reset();
227 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
228 GCCVisibilityHandler.reset();
229 PP.RemovePragmaHandler(OptionsHandler.get());
230 OptionsHandler.reset();
231 PP.RemovePragmaHandler(PackHandler.get());
232 PackHandler.reset();
233 PP.RemovePragmaHandler(MSStructHandler.get());
234 MSStructHandler.reset();
235 PP.RemovePragmaHandler(UnusedHandler.get());
236 UnusedHandler.reset();
237 PP.RemovePragmaHandler(WeakHandler.get());
238 WeakHandler.reset();
239 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
240 RedefineExtnameHandler.reset();
241
242 if (getLangOpts().OpenCL) {
243 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
244 OpenCLExtensionHandler.reset();
245 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
246 }
247 PP.RemovePragmaHandler(OpenMPHandler.get());
248 OpenMPHandler.reset();
249
250 if (getLangOpts().MicrosoftExt) {
251 PP.RemovePragmaHandler(MSCommentHandler.get());
252 MSCommentHandler.reset();
253 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
254 MSDetectMismatchHandler.reset();
255 PP.RemovePragmaHandler(MSPointersToMembers.get());
256 MSPointersToMembers.reset();
257 PP.RemovePragmaHandler(MSVtorDisp.get());
258 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000259 PP.RemovePragmaHandler(MSInitSeg.get());
260 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000261 PP.RemovePragmaHandler(MSDataSeg.get());
262 MSDataSeg.reset();
263 PP.RemovePragmaHandler(MSBSSSeg.get());
264 MSBSSSeg.reset();
265 PP.RemovePragmaHandler(MSConstSeg.get());
266 MSConstSeg.reset();
267 PP.RemovePragmaHandler(MSCodeSeg.get());
268 MSCodeSeg.reset();
269 PP.RemovePragmaHandler(MSSection.get());
270 MSSection.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000271 }
272
273 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
274 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000275
276 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
277 OptimizeHandler.reset();
278
279 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
280 LoopHintHandler.reset();
281}
282
283/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000284///
285/// Each annot_pragma_unused is followed by the argument token so e.g.
286/// "#pragma unused(x,y)" becomes:
287/// annot_pragma_unused 'x' annot_pragma_unused 'y'
288void Parser::HandlePragmaUnused() {
289 assert(Tok.is(tok::annot_pragma_unused));
290 SourceLocation UnusedLoc = ConsumeToken();
291 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
292 ConsumeToken(); // The argument token.
293}
Eli Friedman570024a2010-08-05 06:57:20 +0000294
Rafael Espindola273fd772012-01-26 02:02:57 +0000295void Parser::HandlePragmaVisibility() {
296 assert(Tok.is(tok::annot_pragma_vis));
297 const IdentifierInfo *VisType =
298 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
299 SourceLocation VisLoc = ConsumeToken();
300 Actions.ActOnPragmaVisibility(VisType, VisLoc);
301}
302
Eli Friedmanec52f922012-02-23 23:47:16 +0000303struct PragmaPackInfo {
304 Sema::PragmaPackKind Kind;
305 IdentifierInfo *Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000306 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000307 SourceLocation LParenLoc;
308 SourceLocation RParenLoc;
309};
310
311void Parser::HandlePragmaPack() {
312 assert(Tok.is(tok::annot_pragma_pack));
313 PragmaPackInfo *Info =
314 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
315 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000316 ExprResult Alignment;
317 if (Info->Alignment.is(tok::numeric_constant)) {
318 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
319 if (Alignment.isInvalid())
320 return;
321 }
322 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanec52f922012-02-23 23:47:16 +0000323 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +0000324}
325
Eli Friedman68be1642012-10-04 02:36:51 +0000326void Parser::HandlePragmaMSStruct() {
327 assert(Tok.is(tok::annot_pragma_msstruct));
328 Sema::PragmaMSStructKind Kind =
329 static_cast<Sema::PragmaMSStructKind>(
330 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
331 Actions.ActOnPragmaMSStruct(Kind);
332 ConsumeToken(); // The annotation token.
333}
334
335void Parser::HandlePragmaAlign() {
336 assert(Tok.is(tok::annot_pragma_align));
337 Sema::PragmaOptionsAlignKind Kind =
338 static_cast<Sema::PragmaOptionsAlignKind>(
339 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
340 SourceLocation PragmaLoc = ConsumeToken();
341 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
342}
343
344void Parser::HandlePragmaWeak() {
345 assert(Tok.is(tok::annot_pragma_weak));
346 SourceLocation PragmaLoc = ConsumeToken();
347 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
348 Tok.getLocation());
349 ConsumeToken(); // The weak name.
350}
351
352void Parser::HandlePragmaWeakAlias() {
353 assert(Tok.is(tok::annot_pragma_weakalias));
354 SourceLocation PragmaLoc = ConsumeToken();
355 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
356 SourceLocation WeakNameLoc = Tok.getLocation();
357 ConsumeToken();
358 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
359 SourceLocation AliasNameLoc = Tok.getLocation();
360 ConsumeToken();
361 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
362 WeakNameLoc, AliasNameLoc);
363
364}
365
366void Parser::HandlePragmaRedefineExtname() {
367 assert(Tok.is(tok::annot_pragma_redefine_extname));
368 SourceLocation RedefLoc = ConsumeToken();
369 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
370 SourceLocation RedefNameLoc = Tok.getLocation();
371 ConsumeToken();
372 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
373 SourceLocation AliasNameLoc = Tok.getLocation();
374 ConsumeToken();
375 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
376 RedefNameLoc, AliasNameLoc);
377}
378
379void Parser::HandlePragmaFPContract() {
380 assert(Tok.is(tok::annot_pragma_fp_contract));
381 tok::OnOffSwitch OOS =
382 static_cast<tok::OnOffSwitch>(
383 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
384 Actions.ActOnPragmaFPContract(OOS);
385 ConsumeToken(); // The annotation token.
386}
387
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000388StmtResult Parser::HandlePragmaCaptured()
389{
390 assert(Tok.is(tok::annot_pragma_captured));
391 ConsumeToken();
392
393 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000394 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000395 return StmtError();
396 }
397
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000398 SourceLocation Loc = Tok.getLocation();
399
400 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000401 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
402 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000403
404 StmtResult R = ParseCompoundStatement();
405 CapturedRegionScope.Exit();
406
407 if (R.isInvalid()) {
408 Actions.ActOnCapturedRegionError();
409 return StmtError();
410 }
411
412 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000413}
414
Eli Friedman68be1642012-10-04 02:36:51 +0000415namespace {
416 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
417}
418
419void Parser::HandlePragmaOpenCLExtension() {
420 assert(Tok.is(tok::annot_pragma_opencl_extension));
421 OpenCLExtData data =
422 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
423 unsigned state = data.getInt();
424 IdentifierInfo *ename = data.getPointer();
425 SourceLocation NameLoc = Tok.getLocation();
426 ConsumeToken(); // The annotation token.
427
428 OpenCLOptions &f = Actions.getOpenCLOptions();
429 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
430 // overriding all previously issued extension directives, but only if the
431 // behavior is set to disable."
432 if (state == 0 && ename->isStr("all")) {
433#define OPENCLEXT(nm) f.nm = 0;
434#include "clang/Basic/OpenCLExtensions.def"
435 }
436#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
437#include "clang/Basic/OpenCLExtensions.def"
438 else {
439 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
440 return;
441 }
442}
443
David Majnemer4bb09802014-02-10 19:50:15 +0000444void Parser::HandlePragmaMSPointersToMembers() {
445 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000446 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
447 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000448 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
449 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
450 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
451}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000452
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000453void Parser::HandlePragmaMSVtorDisp() {
454 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
455 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
456 Sema::PragmaVtorDispKind Kind =
457 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
458 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
459 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
460 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
461}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000462
Warren Huntc3b18962014-04-08 22:30:47 +0000463void Parser::HandlePragmaMSPragma() {
464 assert(Tok.is(tok::annot_pragma_ms_pragma));
465 // Grab the tokens out of the annotation and enter them into the stream.
466 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
467 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
468 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
469 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000470 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000471 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000472
Warren Huntc3b18962014-04-08 22:30:47 +0000473 // Figure out which #pragma we're dealing with. The switch has no default
474 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000475 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000476 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
477 .Case("data_seg", &Parser::HandlePragmaMSSegment)
478 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
479 .Case("const_seg", &Parser::HandlePragmaMSSegment)
480 .Case("code_seg", &Parser::HandlePragmaMSSegment)
481 .Case("section", &Parser::HandlePragmaMSSection)
482 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000483
484 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
485 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
486 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000487 while (Tok.isNot(tok::eof))
488 PP.Lex(Tok);
489 PP.Lex(Tok);
490 }
491}
492
Reid Kleckner722b1df2014-07-18 00:13:16 +0000493bool Parser::HandlePragmaMSSection(StringRef PragmaName,
494 SourceLocation PragmaLocation) {
495 if (Tok.isNot(tok::l_paren)) {
496 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
497 return false;
498 }
Warren Huntc3b18962014-04-08 22:30:47 +0000499 PP.Lex(Tok); // (
500 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000501 if (Tok.isNot(tok::string_literal)) {
502 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
503 << PragmaName;
504 return false;
505 }
506 ExprResult StringResult = ParseStringLiteralExpression();
507 if (StringResult.isInvalid())
508 return false; // Already diagnosed.
509 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
510 if (SegmentName->getCharByteWidth() != 1) {
511 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
512 << PragmaName;
513 return false;
514 }
Warren Huntc3b18962014-04-08 22:30:47 +0000515 int SectionFlags = 0;
516 while (Tok.is(tok::comma)) {
517 PP.Lex(Tok); // ,
Reid Kleckner722b1df2014-07-18 00:13:16 +0000518 if (!Tok.isAnyIdentifier()) {
519 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
520 << PragmaName;
521 return false;
522 }
Warren Huntc3b18962014-04-08 22:30:47 +0000523 Sema::PragmaSectionFlag Flag =
524 llvm::StringSwitch<Sema::PragmaSectionFlag>(
525 Tok.getIdentifierInfo()->getName())
526 .Case("read", Sema::PSF_Read)
527 .Case("write", Sema::PSF_Write)
528 .Case("execute", Sema::PSF_Execute)
529 .Case("shared", Sema::PSF_Invalid)
530 .Case("nopage", Sema::PSF_Invalid)
531 .Case("nocache", Sema::PSF_Invalid)
532 .Case("discard", Sema::PSF_Invalid)
533 .Case("remove", Sema::PSF_Invalid)
534 .Default(Sema::PSF_None);
535 if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000536 PP.Diag(PragmaLocation, Flag == Sema::PSF_None
537 ? diag::warn_pragma_invalid_specific_action
538 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000539 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000540 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000541 }
542 SectionFlags |= Flag;
543 PP.Lex(Tok); // Identifier
544 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000545 if (Tok.isNot(tok::r_paren)) {
546 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
547 return false;
548 }
Warren Huntc3b18962014-04-08 22:30:47 +0000549 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000550 if (Tok.isNot(tok::eof)) {
551 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
552 << PragmaName;
553 return false;
554 }
Warren Huntc3b18962014-04-08 22:30:47 +0000555 PP.Lex(Tok); // eof
556 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000557 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000558}
559
Reid Kleckner722b1df2014-07-18 00:13:16 +0000560bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
561 SourceLocation PragmaLocation) {
562 if (Tok.isNot(tok::l_paren)) {
563 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
564 return false;
565 }
Warren Huntc3b18962014-04-08 22:30:47 +0000566 PP.Lex(Tok); // (
567 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000568 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000569 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000570 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000571 if (PushPop == "push")
572 Action = Sema::PSK_Push;
573 else if (PushPop == "pop")
574 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000575 else {
576 PP.Diag(PragmaLocation,
577 diag::warn_pragma_expected_section_push_pop_or_name)
578 << PragmaName;
579 return false;
580 }
Warren Huntc3b18962014-04-08 22:30:47 +0000581 if (Action != Sema::PSK_Reset) {
582 PP.Lex(Tok); // push | pop
583 if (Tok.is(tok::comma)) {
584 PP.Lex(Tok); // ,
585 // If we've got a comma, we either need a label or a string.
586 if (Tok.isAnyIdentifier()) {
587 SlotLabel = Tok.getIdentifierInfo()->getName();
588 PP.Lex(Tok); // identifier
589 if (Tok.is(tok::comma))
590 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000591 else if (Tok.isNot(tok::r_paren)) {
592 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
593 << PragmaName;
594 return false;
595 }
Warren Huntc3b18962014-04-08 22:30:47 +0000596 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000597 } else if (Tok.isNot(tok::r_paren)) {
598 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
599 return false;
600 }
Warren Huntc3b18962014-04-08 22:30:47 +0000601 }
602 }
603 // Grab the string literal for our section name.
604 StringLiteral *SegmentName = nullptr;
605 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000606 if (Tok.isNot(tok::string_literal)) {
607 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000608 diag::warn_pragma_expected_section_name :
609 diag::warn_pragma_expected_section_label_or_name :
610 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000611 PP.Diag(PragmaLocation, DiagID) << PragmaName;
612 return false;
613 }
614 ExprResult StringResult = ParseStringLiteralExpression();
615 if (StringResult.isInvalid())
616 return false; // Already diagnosed.
617 SegmentName = cast<StringLiteral>(StringResult.get());
618 if (SegmentName->getCharByteWidth() != 1) {
619 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
620 << PragmaName;
621 return false;
622 }
Warren Huntc3b18962014-04-08 22:30:47 +0000623 // Setting section "" has no effect
624 if (SegmentName->getLength())
625 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
626 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000627 if (Tok.isNot(tok::r_paren)) {
628 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
629 return false;
630 }
Warren Huntc3b18962014-04-08 22:30:47 +0000631 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000632 if (Tok.isNot(tok::eof)) {
633 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
634 << PragmaName;
635 return false;
636 }
Warren Huntc3b18962014-04-08 22:30:47 +0000637 PP.Lex(Tok); // eof
638 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
639 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000640 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000641}
642
Reid Kleckner722b1df2014-07-18 00:13:16 +0000643bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
644 SourceLocation PragmaLocation) {
645 PP.Diag(PragmaLocation,
646 PP.getDiagnostics().getCustomDiagID(
647 DiagnosticsEngine::Error, "'#pragma init_seg' not implemented."));
648 return false;
Eli Bendersky06a40422014-06-06 20:31:48 +0000649}
650
651struct PragmaLoopHintInfo {
652 Token Loop;
653 Token Value;
654 Token Option;
655};
656
657LoopHint Parser::HandlePragmaLoopHint() {
658 assert(Tok.is(tok::annot_pragma_loop_hint));
659 PragmaLoopHintInfo *Info =
660 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
661
662 LoopHint Hint;
663 Hint.LoopLoc =
664 IdentifierLoc::create(Actions.Context, Info->Loop.getLocation(),
665 Info->Loop.getIdentifierInfo());
666 Hint.OptionLoc =
667 IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
668 Info->Option.getIdentifierInfo());
669 Hint.ValueLoc =
670 IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
671 Info->Value.getIdentifierInfo());
672 Hint.Range =
673 SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
674
Tyler Nowickif54bda62014-06-13 17:15:27 +0000675 // FIXME: We should allow non-type template parameters for the loop hint
676 // value. See bug report #19610
Eli Bendersky06a40422014-06-06 20:31:48 +0000677 if (Info->Value.is(tok::numeric_constant))
678 Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
679 else
680 Hint.ValueExpr = nullptr;
681
682 return Hint;
683}
684
685// #pragma GCC visibility comes in two variants:
686// 'push' '(' [visibility] ')'
687// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000688void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
689 PragmaIntroducerKind Introducer,
690 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000691 SourceLocation VisLoc = VisTok.getLocation();
692
693 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000694 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000695
696 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
697
Eli Friedman570024a2010-08-05 06:57:20 +0000698 const IdentifierInfo *VisType;
699 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +0000700 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +0000701 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000702 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000703 if (Tok.isNot(tok::l_paren)) {
704 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
705 << "visibility";
706 return;
707 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000708 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000709 VisType = Tok.getIdentifierInfo();
710 if (!VisType) {
711 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
712 << "visibility";
713 return;
714 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000715 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000716 if (Tok.isNot(tok::r_paren)) {
717 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
718 << "visibility";
719 return;
720 }
721 } else {
722 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
723 << "visibility";
724 return;
725 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000726 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000727 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000728 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
729 << "visibility";
730 return;
731 }
732
Rafael Espindola273fd772012-01-26 02:02:57 +0000733 Token *Toks = new Token[1];
734 Toks[0].startToken();
735 Toks[0].setKind(tok::annot_pragma_vis);
736 Toks[0].setLocation(VisLoc);
737 Toks[0].setAnnotationValue(
738 const_cast<void*>(static_cast<const void*>(VisType)));
739 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
740 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000741}
742
Daniel Dunbar921b9682008-10-04 19:21:03 +0000743// #pragma pack(...) comes in the following delicious flavors:
744// pack '(' [integer] ')'
745// pack '(' 'show' ')'
746// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000747void PragmaPackHandler::HandlePragma(Preprocessor &PP,
748 PragmaIntroducerKind Introducer,
749 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000750 SourceLocation PackLoc = PackTok.getLocation();
751
752 Token Tok;
753 PP.Lex(Tok);
754 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000755 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000756 return;
757 }
758
John McCallfaf5fb42010-08-26 23:41:50 +0000759 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Craig Topper161e4db2014-05-21 06:02:52 +0000760 IdentifierInfo *Name = nullptr;
Eli Friedman68be1642012-10-04 02:36:51 +0000761 Token Alignment;
762 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000763 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000764 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000765 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000766 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000767
768 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000769
770 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
771 // the push/pop stack.
772 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000773 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000774 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000775 } else if (Tok.is(tok::identifier)) {
776 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000777 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000778 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000779 PP.Lex(Tok);
780 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000781 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000782 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000783 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000784 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000785 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000786 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000787 return;
Mike Stump11289f42009-09-09 15:08:12 +0000788 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000789 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000790
Daniel Dunbar921b9682008-10-04 19:21:03 +0000791 if (Tok.is(tok::comma)) {
792 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000793
Daniel Dunbar921b9682008-10-04 19:21:03 +0000794 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000795 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000796
797 PP.Lex(Tok);
798 } else if (Tok.is(tok::identifier)) {
799 Name = Tok.getIdentifierInfo();
800 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000801
Daniel Dunbar921b9682008-10-04 19:21:03 +0000802 if (Tok.is(tok::comma)) {
803 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000804
Daniel Dunbar921b9682008-10-04 19:21:03 +0000805 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000806 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000807 return;
808 }
Mike Stump11289f42009-09-09 15:08:12 +0000809
Eli Friedman68be1642012-10-04 02:36:51 +0000810 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000811
812 PP.Lex(Tok);
813 }
814 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000815 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000816 return;
817 }
818 }
819 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000820 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000821 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
822 // the push/pop stack.
823 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
824 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000825 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000826
827 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000828 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000829 return;
830 }
831
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000832 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000833 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000834 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000835 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
836 return;
837 }
838
Daniel Dunbar340cf242012-02-29 01:38:22 +0000839 PragmaPackInfo *Info =
840 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
841 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
842 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +0000843 Info->Kind = Kind;
844 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000845 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000846 Info->LParenLoc = LParenLoc;
847 Info->RParenLoc = RParenLoc;
848
Daniel Dunbar340cf242012-02-29 01:38:22 +0000849 Token *Toks =
850 (Token*) PP.getPreprocessorAllocator().Allocate(
851 sizeof(Token) * 1, llvm::alignOf<Token>());
852 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +0000853 Toks[0].startToken();
854 Toks[0].setKind(tok::annot_pragma_pack);
855 Toks[0].setLocation(PackLoc);
856 Toks[0].setAnnotationValue(static_cast<void*>(Info));
857 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +0000858 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000859}
860
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000861// #pragma ms_struct on
862// #pragma ms_struct off
863void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
864 PragmaIntroducerKind Introducer,
865 Token &MSStructTok) {
866 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
867
868 Token Tok;
869 PP.Lex(Tok);
870 if (Tok.isNot(tok::identifier)) {
871 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
872 return;
873 }
874 const IdentifierInfo *II = Tok.getIdentifierInfo();
875 if (II->isStr("on")) {
876 Kind = Sema::PMSST_ON;
877 PP.Lex(Tok);
878 }
879 else if (II->isStr("off") || II->isStr("reset"))
880 PP.Lex(Tok);
881 else {
882 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
883 return;
884 }
885
886 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +0000887 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
888 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000889 return;
890 }
Eli Friedman68be1642012-10-04 02:36:51 +0000891
892 Token *Toks =
893 (Token*) PP.getPreprocessorAllocator().Allocate(
894 sizeof(Token) * 1, llvm::alignOf<Token>());
895 new (Toks) Token();
896 Toks[0].startToken();
897 Toks[0].setKind(tok::annot_pragma_msstruct);
898 Toks[0].setLocation(MSStructTok.getLocation());
899 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
900 static_cast<uintptr_t>(Kind)));
901 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
902 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000903}
904
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000905// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
906// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +0000907static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000908 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000909 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000910
911 if (IsOptions) {
912 PP.Lex(Tok);
913 if (Tok.isNot(tok::identifier) ||
914 !Tok.getIdentifierInfo()->isStr("align")) {
915 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
916 return;
917 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000918 }
Daniel Dunbar663e8092010-05-27 18:42:09 +0000919
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000920 PP.Lex(Tok);
921 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000922 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
923 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000924 return;
925 }
926
927 PP.Lex(Tok);
928 if (Tok.isNot(tok::identifier)) {
929 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000930 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000931 return;
932 }
933
John McCallfaf5fb42010-08-26 23:41:50 +0000934 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000935 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +0000936 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +0000937 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +0000938 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +0000939 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +0000940 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +0000941 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000942 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +0000943 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000944 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +0000945 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000946 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +0000947 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000948 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000949 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
950 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000951 return;
952 }
953
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000954 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000955 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000956 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000957 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000958 return;
959 }
960
Eli Friedman68be1642012-10-04 02:36:51 +0000961 Token *Toks =
962 (Token*) PP.getPreprocessorAllocator().Allocate(
963 sizeof(Token) * 1, llvm::alignOf<Token>());
964 new (Toks) Token();
965 Toks[0].startToken();
966 Toks[0].setKind(tok::annot_pragma_align);
967 Toks[0].setLocation(FirstTok.getLocation());
968 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
969 static_cast<uintptr_t>(Kind)));
970 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
971 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000972}
973
Douglas Gregorc7d65762010-09-09 22:45:38 +0000974void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
975 PragmaIntroducerKind Introducer,
976 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000977 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000978}
979
Douglas Gregorc7d65762010-09-09 22:45:38 +0000980void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
981 PragmaIntroducerKind Introducer,
982 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000983 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000984}
985
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000986// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +0000987void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
988 PragmaIntroducerKind Introducer,
989 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000990 // FIXME: Should we be expanding macros here? My guess is no.
991 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000992
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000993 // Lex the left '('.
994 Token Tok;
995 PP.Lex(Tok);
996 if (Tok.isNot(tok::l_paren)) {
997 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
998 return;
999 }
Mike Stump11289f42009-09-09 15:08:12 +00001000
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001001 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001002 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001003 SourceLocation RParenLoc;
1004 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001005
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001006 while (true) {
1007 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001008
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001009 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001010 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001011 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001012 LexID = false;
1013 continue;
1014 }
1015
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001016 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001017 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1018 return;
1019 }
Mike Stump11289f42009-09-09 15:08:12 +00001020
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001021 // We are execting a ')' or a ','.
1022 if (Tok.is(tok::comma)) {
1023 LexID = true;
1024 continue;
1025 }
Mike Stump11289f42009-09-09 15:08:12 +00001026
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001027 if (Tok.is(tok::r_paren)) {
1028 RParenLoc = Tok.getLocation();
1029 break;
1030 }
Mike Stump11289f42009-09-09 15:08:12 +00001031
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001032 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001033 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001034 return;
1035 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001036
1037 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001038 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001039 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1040 "unused";
1041 return;
1042 }
1043
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001044 // Verify that we have a location for the right parenthesis.
1045 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001046 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001047
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001048 // For each identifier token, insert into the token stream a
1049 // annot_pragma_unused token followed by the identifier token.
1050 // This allows us to cache a "#pragma unused" that occurs inside an inline
1051 // C++ member function.
1052
Daniel Dunbar340cf242012-02-29 01:38:22 +00001053 Token *Toks =
1054 (Token*) PP.getPreprocessorAllocator().Allocate(
1055 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001056 for (unsigned i=0; i != Identifiers.size(); i++) {
1057 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1058 pragmaUnusedTok.startToken();
1059 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1060 pragmaUnusedTok.setLocation(UnusedLoc);
1061 idTok = Identifiers[i];
1062 }
Daniel Dunbar340cf242012-02-29 01:38:22 +00001063 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1064 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001065}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001066
1067// #pragma weak identifier
1068// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001069void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1070 PragmaIntroducerKind Introducer,
1071 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001072 SourceLocation WeakLoc = WeakTok.getLocation();
1073
1074 Token Tok;
1075 PP.Lex(Tok);
1076 if (Tok.isNot(tok::identifier)) {
1077 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1078 return;
1079 }
1080
Eli Friedman68be1642012-10-04 02:36:51 +00001081 Token WeakName = Tok;
1082 bool HasAlias = false;
1083 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001084
1085 PP.Lex(Tok);
1086 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001087 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001088 PP.Lex(Tok);
1089 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001090 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001091 << "weak";
1092 return;
1093 }
Eli Friedman68be1642012-10-04 02:36:51 +00001094 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001095 PP.Lex(Tok);
1096 }
1097
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001098 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001099 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1100 return;
1101 }
1102
Eli Friedman68be1642012-10-04 02:36:51 +00001103 if (HasAlias) {
1104 Token *Toks =
1105 (Token*) PP.getPreprocessorAllocator().Allocate(
1106 sizeof(Token) * 3, llvm::alignOf<Token>());
1107 Token &pragmaUnusedTok = Toks[0];
1108 pragmaUnusedTok.startToken();
1109 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1110 pragmaUnusedTok.setLocation(WeakLoc);
1111 Toks[1] = WeakName;
1112 Toks[2] = AliasName;
1113 PP.EnterTokenStream(Toks, 3,
1114 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001115 } else {
Eli Friedman68be1642012-10-04 02:36:51 +00001116 Token *Toks =
1117 (Token*) PP.getPreprocessorAllocator().Allocate(
1118 sizeof(Token) * 2, llvm::alignOf<Token>());
1119 Token &pragmaUnusedTok = Toks[0];
1120 pragmaUnusedTok.startToken();
1121 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1122 pragmaUnusedTok.setLocation(WeakLoc);
1123 Toks[1] = WeakName;
1124 PP.EnterTokenStream(Toks, 2,
1125 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001126 }
1127}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001128
David Chisnall0867d9c2012-02-18 16:12:34 +00001129// #pragma redefine_extname identifier identifier
1130void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1131 PragmaIntroducerKind Introducer,
1132 Token &RedefToken) {
1133 SourceLocation RedefLoc = RedefToken.getLocation();
1134
1135 Token Tok;
1136 PP.Lex(Tok);
1137 if (Tok.isNot(tok::identifier)) {
1138 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1139 "redefine_extname";
1140 return;
1141 }
1142
Eli Friedman68be1642012-10-04 02:36:51 +00001143 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001144 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001145
David Chisnall0867d9c2012-02-18 16:12:34 +00001146 if (Tok.isNot(tok::identifier)) {
1147 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1148 << "redefine_extname";
1149 return;
1150 }
Eli Friedman68be1642012-10-04 02:36:51 +00001151
1152 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001153 PP.Lex(Tok);
1154
1155 if (Tok.isNot(tok::eod)) {
1156 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1157 "redefine_extname";
1158 return;
1159 }
1160
Eli Friedman68be1642012-10-04 02:36:51 +00001161 Token *Toks =
1162 (Token*) PP.getPreprocessorAllocator().Allocate(
1163 sizeof(Token) * 3, llvm::alignOf<Token>());
1164 Token &pragmaRedefTok = Toks[0];
1165 pragmaRedefTok.startToken();
1166 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1167 pragmaRedefTok.setLocation(RedefLoc);
1168 Toks[1] = RedefName;
1169 Toks[2] = AliasName;
1170 PP.EnterTokenStream(Toks, 3,
1171 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00001172}
1173
1174
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001175void
1176PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1177 PragmaIntroducerKind Introducer,
1178 Token &Tok) {
1179 tok::OnOffSwitch OOS;
1180 if (PP.LexOnOffSwitch(OOS))
1181 return;
1182
Eli Friedman68be1642012-10-04 02:36:51 +00001183 Token *Toks =
1184 (Token*) PP.getPreprocessorAllocator().Allocate(
1185 sizeof(Token) * 1, llvm::alignOf<Token>());
1186 new (Toks) Token();
1187 Toks[0].startToken();
1188 Toks[0].setKind(tok::annot_pragma_fp_contract);
1189 Toks[0].setLocation(Tok.getLocation());
1190 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1191 static_cast<uintptr_t>(OOS)));
1192 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1193 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001194}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001195
1196void
1197PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1198 PragmaIntroducerKind Introducer,
1199 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001200 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001201 if (Tok.isNot(tok::identifier)) {
1202 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1203 "OPENCL";
1204 return;
1205 }
1206 IdentifierInfo *ename = Tok.getIdentifierInfo();
1207 SourceLocation NameLoc = Tok.getLocation();
1208
1209 PP.Lex(Tok);
1210 if (Tok.isNot(tok::colon)) {
1211 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1212 return;
1213 }
1214
1215 PP.Lex(Tok);
1216 if (Tok.isNot(tok::identifier)) {
1217 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1218 return;
1219 }
1220 IdentifierInfo *op = Tok.getIdentifierInfo();
1221
1222 unsigned state;
1223 if (op->isStr("enable")) {
1224 state = 1;
1225 } else if (op->isStr("disable")) {
1226 state = 0;
1227 } else {
1228 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1229 return;
1230 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001231 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001232
Eli Friedman68be1642012-10-04 02:36:51 +00001233 PP.Lex(Tok);
1234 if (Tok.isNot(tok::eod)) {
1235 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1236 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001237 return;
1238 }
Eli Friedman68be1642012-10-04 02:36:51 +00001239
1240 OpenCLExtData data(ename, state);
1241 Token *Toks =
1242 (Token*) PP.getPreprocessorAllocator().Allocate(
1243 sizeof(Token) * 1, llvm::alignOf<Token>());
1244 new (Toks) Token();
1245 Toks[0].startToken();
1246 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1247 Toks[0].setLocation(NameLoc);
1248 Toks[0].setAnnotationValue(data.getOpaqueValue());
1249 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1250 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001251
1252 if (PP.getPPCallbacks())
1253 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1254 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001255}
1256
Alexey Bataeva769e072013-03-22 06:34:35 +00001257/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1258///
1259void
1260PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1261 PragmaIntroducerKind Introducer,
1262 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00001263 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1264 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00001265 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00001266 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1267 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00001268 }
1269 PP.DiscardUntilEndOfDirective();
1270}
1271
1272/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1273///
1274void
1275PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1276 PragmaIntroducerKind Introducer,
1277 Token &FirstTok) {
1278 SmallVector<Token, 16> Pragma;
1279 Token Tok;
1280 Tok.startToken();
1281 Tok.setKind(tok::annot_pragma_openmp);
1282 Tok.setLocation(FirstTok.getLocation());
1283
1284 while (Tok.isNot(tok::eod)) {
1285 Pragma.push_back(Tok);
1286 PP.Lex(Tok);
1287 }
1288 SourceLocation EodLoc = Tok.getLocation();
1289 Tok.startToken();
1290 Tok.setKind(tok::annot_pragma_openmp_end);
1291 Tok.setLocation(EodLoc);
1292 Pragma.push_back(Tok);
1293
1294 Token *Toks = new Token[Pragma.size()];
1295 std::copy(Pragma.begin(), Pragma.end(), Toks);
1296 PP.EnterTokenStream(Toks, Pragma.size(),
1297 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1298}
Reid Kleckner002562a2013-05-06 21:02:12 +00001299
David Majnemer4bb09802014-02-10 19:50:15 +00001300/// \brief Handle '#pragma pointers_to_members'
1301// The grammar for this pragma is as follows:
1302//
1303// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1304//
1305// #pragma pointers_to_members '(' 'best_case' ')'
1306// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1307// #pragma pointers_to_members '(' inheritance-model ')'
1308void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1309 PragmaIntroducerKind Introducer,
1310 Token &Tok) {
1311 SourceLocation PointersToMembersLoc = Tok.getLocation();
1312 PP.Lex(Tok);
1313 if (Tok.isNot(tok::l_paren)) {
1314 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1315 << "pointers_to_members";
1316 return;
1317 }
1318 PP.Lex(Tok);
1319 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1320 if (!Arg) {
1321 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1322 << "pointers_to_members";
1323 return;
1324 }
1325 PP.Lex(Tok);
1326
David Majnemer86c318f2014-02-11 21:05:00 +00001327 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001328 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001329 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001330 } else {
1331 if (Arg->isStr("full_generality")) {
1332 if (Tok.is(tok::comma)) {
1333 PP.Lex(Tok);
1334
1335 Arg = Tok.getIdentifierInfo();
1336 if (!Arg) {
1337 PP.Diag(Tok.getLocation(),
1338 diag::err_pragma_pointers_to_members_unknown_kind)
1339 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1340 return;
1341 }
1342 PP.Lex(Tok);
1343 } else if (Tok.is(tok::r_paren)) {
1344 // #pragma pointers_to_members(full_generality) implicitly specifies
1345 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00001346 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00001347 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001348 } else {
1349 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1350 << "full_generality";
1351 return;
1352 }
1353 }
1354
1355 if (Arg) {
1356 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001357 RepresentationMethod =
1358 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001359 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001360 RepresentationMethod =
1361 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001362 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001363 RepresentationMethod =
1364 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001365 } else {
1366 PP.Diag(Tok.getLocation(),
1367 diag::err_pragma_pointers_to_members_unknown_kind)
1368 << Arg << /*HasPointerDeclaration*/ 1;
1369 return;
1370 }
1371 }
1372 }
1373
1374 if (Tok.isNot(tok::r_paren)) {
1375 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1376 << (Arg ? Arg->getName() : "full_generality");
1377 return;
1378 }
1379
1380 PP.Lex(Tok);
1381 if (Tok.isNot(tok::eod)) {
1382 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1383 << "pointers_to_members";
1384 return;
1385 }
1386
1387 Token AnnotTok;
1388 AnnotTok.startToken();
1389 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1390 AnnotTok.setLocation(PointersToMembersLoc);
1391 AnnotTok.setAnnotationValue(
1392 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1393 PP.EnterToken(AnnotTok);
1394}
1395
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001396/// \brief Handle '#pragma vtordisp'
1397// The grammar for this pragma is as follows:
1398//
1399// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1400//
1401// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1402// #pragma vtordisp '(' 'pop' ')'
1403// #pragma vtordisp '(' ')'
1404void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1405 PragmaIntroducerKind Introducer,
1406 Token &Tok) {
1407 SourceLocation VtorDispLoc = Tok.getLocation();
1408 PP.Lex(Tok);
1409 if (Tok.isNot(tok::l_paren)) {
1410 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1411 return;
1412 }
1413 PP.Lex(Tok);
1414
1415 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1416 const IdentifierInfo *II = Tok.getIdentifierInfo();
1417 if (II) {
1418 if (II->isStr("push")) {
1419 // #pragma vtordisp(push, mode)
1420 PP.Lex(Tok);
1421 if (Tok.isNot(tok::comma)) {
1422 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1423 return;
1424 }
1425 PP.Lex(Tok);
1426 Kind = Sema::PVDK_Push;
1427 // not push, could be on/off
1428 } else if (II->isStr("pop")) {
1429 // #pragma vtordisp(pop)
1430 PP.Lex(Tok);
1431 Kind = Sema::PVDK_Pop;
1432 }
1433 // not push or pop, could be on/off
1434 } else {
1435 if (Tok.is(tok::r_paren)) {
1436 // #pragma vtordisp()
1437 Kind = Sema::PVDK_Reset;
1438 }
1439 }
1440
1441
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001442 uint64_t Value = 0;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001443 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1444 const IdentifierInfo *II = Tok.getIdentifierInfo();
1445 if (II && II->isStr("off")) {
1446 PP.Lex(Tok);
1447 Value = 0;
1448 } else if (II && II->isStr("on")) {
1449 PP.Lex(Tok);
1450 Value = 1;
1451 } else if (Tok.is(tok::numeric_constant) &&
1452 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1453 if (Value > 2) {
1454 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1455 << 0 << 2 << "vtordisp";
1456 return;
1457 }
1458 } else {
1459 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1460 << "vtordisp";
1461 return;
1462 }
1463 }
1464
1465 // Finish the pragma: ')' $
1466 if (Tok.isNot(tok::r_paren)) {
1467 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1468 return;
1469 }
1470 PP.Lex(Tok);
1471 if (Tok.isNot(tok::eod)) {
1472 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1473 << "vtordisp";
1474 return;
1475 }
1476
1477 // Enter the annotation.
1478 Token AnnotTok;
1479 AnnotTok.startToken();
1480 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1481 AnnotTok.setLocation(VtorDispLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001482 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1483 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001484 PP.EnterToken(AnnotTok);
1485}
1486
Warren Huntc3b18962014-04-08 22:30:47 +00001487/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1488/// an annotation token.
1489void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1490 PragmaIntroducerKind Introducer,
1491 Token &Tok) {
1492 Token EoF, AnnotTok;
1493 EoF.startToken();
1494 EoF.setKind(tok::eof);
1495 AnnotTok.startToken();
1496 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1497 AnnotTok.setLocation(Tok.getLocation());
1498 SmallVector<Token, 8> TokenVector;
1499 // Suck up all of the tokens before the eod.
1500 for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1501 TokenVector.push_back(Tok);
1502 // Add a sentinal EoF token to the end of the list.
1503 TokenVector.push_back(EoF);
1504 // We must allocate this array with new because EnterTokenStream is going to
1505 // delete it later.
1506 Token *TokenArray = new Token[TokenVector.size()];
1507 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1508 auto Value = new (PP.getPreprocessorAllocator())
1509 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1510 AnnotTok.setAnnotationValue(Value);
1511 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001512}
1513
Aaron Ballman5d041be2013-06-04 02:07:14 +00001514/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1515///
1516/// The syntax is:
1517/// \code
1518/// #pragma detect_mismatch("name", "value")
1519/// \endcode
1520/// Where 'name' and 'value' are quoted strings. The values are embedded in
1521/// the object file and passed along to the linker. If the linker detects a
1522/// mismatch in the object file's values for the given name, a LNK2038 error
1523/// is emitted. See MSDN for more details.
1524void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1525 PragmaIntroducerKind Introducer,
1526 Token &Tok) {
1527 SourceLocation CommentLoc = Tok.getLocation();
1528 PP.Lex(Tok);
1529 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001530 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001531 return;
1532 }
1533
1534 // Read the name to embed, which must be a string literal.
1535 std::string NameString;
1536 if (!PP.LexStringLiteral(Tok, NameString,
1537 "pragma detect_mismatch",
1538 /*MacroExpansion=*/true))
1539 return;
1540
1541 // Read the comma followed by a second string literal.
1542 std::string ValueString;
1543 if (Tok.isNot(tok::comma)) {
1544 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1545 return;
1546 }
1547
1548 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1549 /*MacroExpansion=*/true))
1550 return;
1551
1552 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001553 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001554 return;
1555 }
1556 PP.Lex(Tok); // Eat the r_paren.
1557
1558 if (Tok.isNot(tok::eod)) {
1559 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1560 return;
1561 }
1562
Reid Kleckner71966c92014-02-20 23:37:45 +00001563 // If the pragma is lexically sound, notify any interested PPCallbacks.
1564 if (PP.getPPCallbacks())
1565 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1566 ValueString);
1567
Aaron Ballman5d041be2013-06-04 02:07:14 +00001568 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1569}
1570
Reid Kleckner002562a2013-05-06 21:02:12 +00001571/// \brief Handle the microsoft \#pragma comment extension.
1572///
1573/// The syntax is:
1574/// \code
1575/// #pragma comment(linker, "foo")
1576/// \endcode
1577/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1578/// "foo" is a string, which is fully macro expanded, and permits string
1579/// concatenation, embedded escape characters etc. See MSDN for more details.
1580void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1581 PragmaIntroducerKind Introducer,
1582 Token &Tok) {
1583 SourceLocation CommentLoc = Tok.getLocation();
1584 PP.Lex(Tok);
1585 if (Tok.isNot(tok::l_paren)) {
1586 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1587 return;
1588 }
1589
1590 // Read the identifier.
1591 PP.Lex(Tok);
1592 if (Tok.isNot(tok::identifier)) {
1593 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1594 return;
1595 }
1596
1597 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001598 IdentifierInfo *II = Tok.getIdentifierInfo();
1599 Sema::PragmaMSCommentKind Kind =
1600 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1601 .Case("linker", Sema::PCK_Linker)
1602 .Case("lib", Sema::PCK_Lib)
1603 .Case("compiler", Sema::PCK_Compiler)
1604 .Case("exestr", Sema::PCK_ExeStr)
1605 .Case("user", Sema::PCK_User)
1606 .Default(Sema::PCK_Unknown);
1607 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001608 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1609 return;
1610 }
1611
1612 // Read the optional string if present.
1613 PP.Lex(Tok);
1614 std::string ArgumentString;
1615 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1616 "pragma comment",
1617 /*MacroExpansion=*/true))
1618 return;
1619
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001620 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001621 // FIXME: If the kind is "compiler" warn if the string is present (it is
1622 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001623 // The MSDN docs say that "lib" and "linker" require a string and have a short
1624 // whitelist of linker options they support, but in practice MSVC doesn't
1625 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001626
1627 if (Tok.isNot(tok::r_paren)) {
1628 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1629 return;
1630 }
1631 PP.Lex(Tok); // eat the r_paren.
1632
1633 if (Tok.isNot(tok::eod)) {
1634 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1635 return;
1636 }
1637
Reid Kleckner71966c92014-02-20 23:37:45 +00001638 // If the pragma is lexically sound, notify any interested PPCallbacks.
1639 if (PP.getPPCallbacks())
1640 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1641
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001642 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001643}
Dario Domizioli13a0a382014-05-23 12:13:25 +00001644
1645// #pragma clang optimize off
1646// #pragma clang optimize on
1647void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1648 PragmaIntroducerKind Introducer,
1649 Token &FirstToken) {
1650 Token Tok;
1651 PP.Lex(Tok);
1652 if (Tok.is(tok::eod)) {
1653 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_missing_argument);
1654 return;
1655 }
1656 if (Tok.isNot(tok::identifier)) {
1657 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1658 << PP.getSpelling(Tok);
1659 return;
1660 }
1661 const IdentifierInfo *II = Tok.getIdentifierInfo();
1662 // The only accepted values are 'on' or 'off'.
1663 bool IsOn = false;
1664 if (II->isStr("on")) {
1665 IsOn = true;
1666 } else if (!II->isStr("off")) {
1667 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1668 << PP.getSpelling(Tok);
1669 return;
1670 }
1671 PP.Lex(Tok);
1672
1673 if (Tok.isNot(tok::eod)) {
1674 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1675 << PP.getSpelling(Tok);
1676 return;
1677 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001678
1679 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1680}
1681
1682/// \brief Handle the \#pragma clang loop directive.
1683/// #pragma clang 'loop' loop-hints
1684///
1685/// loop-hints:
1686/// loop-hint loop-hints[opt]
1687///
1688/// loop-hint:
1689/// 'vectorize' '(' loop-hint-keyword ')'
1690/// 'interleave' '(' loop-hint-keyword ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00001691/// 'unroll' '(' loop-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001692/// 'vectorize_width' '(' loop-hint-value ')'
1693/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00001694/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001695///
1696/// loop-hint-keyword:
1697/// 'enable'
1698/// 'disable'
1699///
1700/// loop-hint-value:
1701/// constant-expression
1702///
1703/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1704/// try vectorizing the instructions of the loop it precedes. Specifying
1705/// interleave(enable) or interleave_count(_value_) instructs llvm to try
1706/// interleaving multiple iterations of the loop it precedes. The width of the
1707/// vector instructions is specified by vectorize_width() and the number of
1708/// interleaved loop iterations is specified by interleave_count(). Specifying a
1709/// value of 1 effectively disables vectorization/interleaving, even if it is
1710/// possible and profitable, and 0 is invalid. The loop vectorizer currently
1711/// only works on inner loops.
1712///
Eli Bendersky86483b32014-06-11 17:56:26 +00001713/// The unroll and unroll_count directives control the concatenation
1714/// unroller. Specifying unroll(enable) instructs llvm to try to
1715/// unroll the loop completely, and unroll(disable) disables unrolling
1716/// for the loop. Specifying unroll_count(_value_) instructs llvm to
1717/// try to unroll the loop the number of times indicated by the value.
1718/// If unroll(enable) and unroll_count are both specified only
1719/// unroll_count takes effect.
Eli Bendersky06a40422014-06-06 20:31:48 +00001720void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1721 PragmaIntroducerKind Introducer,
1722 Token &Tok) {
1723 Token Loop = Tok;
1724 SmallVector<Token, 1> TokenList;
1725
1726 // Lex the optimization option and verify it is an identifier.
1727 PP.Lex(Tok);
1728 if (Tok.isNot(tok::identifier)) {
1729 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1730 << /*MissingOption=*/true << "";
1731 return;
1732 }
1733
1734 while (Tok.is(tok::identifier)) {
1735 Token Option = Tok;
1736 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
1737
Eli Bendersky86483b32014-06-11 17:56:26 +00001738 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
1739 .Case("vectorize", true)
1740 .Case("interleave", true)
1741 .Case("unroll", true)
1742 .Case("vectorize_width", true)
1743 .Case("interleave_count", true)
1744 .Case("unroll_count", true)
1745 .Default(false);
1746 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001747 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1748 << /*MissingOption=*/false << OptionInfo;
1749 return;
1750 }
1751
1752 // Read '('
1753 PP.Lex(Tok);
1754 if (Tok.isNot(tok::l_paren)) {
1755 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
1756 return;
1757 }
1758
1759 // FIXME: All tokens between '(' and ')' should be stored and parsed as a
1760 // constant expression.
1761 PP.Lex(Tok);
Eli Benderskyf6377902014-06-19 18:30:15 +00001762 if (Tok.is(tok::r_paren)) {
1763 // Nothing between the parentheses.
1764 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_missing_argument)
1765 << OptionInfo;
1766 return;
1767 }
1768 Token Value = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00001769
1770 // Read ')'
1771 PP.Lex(Tok);
1772 if (Tok.isNot(tok::r_paren)) {
1773 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1774 return;
1775 }
1776
1777 // Get next optimization option.
1778 PP.Lex(Tok);
1779
1780 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
1781 Info->Loop = Loop;
1782 Info->Option = Option;
1783 Info->Value = Value;
1784
1785 // Generate the vectorization hint token.
1786 Token LoopHintTok;
1787 LoopHintTok.startToken();
1788 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
1789 LoopHintTok.setLocation(Loop.getLocation());
1790 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
1791 TokenList.push_back(LoopHintTok);
1792 }
1793
1794 if (Tok.isNot(tok::eod)) {
1795 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1796 << "clang loop";
1797 return;
1798 }
1799
1800 Token *TokenArray = new Token[TokenList.size()];
1801 std::copy(TokenList.begin(), TokenList.end(), TokenArray);
1802
1803 PP.EnterTokenStream(TokenArray, TokenList.size(),
1804 /*DisableMacroExpansion=*/false,
1805 /*OwnsTokens=*/true);
1806}