blob: 20b87d92b7831ab30f9eeab54e30ab47fee4eb83 [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
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000151struct PragmaUnrollHintHandler : public PragmaHandler {
152 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
153 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
154 Token &FirstToken) override;
155};
156
Eli Bendersky06a40422014-06-06 20:31:48 +0000157} // end namespace
158
159void Parser::initializePragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000160 AlignHandler.reset(new PragmaAlignHandler());
161 PP.AddPragmaHandler(AlignHandler.get());
162
163 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
164 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
165
166 OptionsHandler.reset(new PragmaOptionsHandler());
167 PP.AddPragmaHandler(OptionsHandler.get());
168
169 PackHandler.reset(new PragmaPackHandler());
170 PP.AddPragmaHandler(PackHandler.get());
171
172 MSStructHandler.reset(new PragmaMSStructHandler());
173 PP.AddPragmaHandler(MSStructHandler.get());
174
175 UnusedHandler.reset(new PragmaUnusedHandler());
176 PP.AddPragmaHandler(UnusedHandler.get());
177
178 WeakHandler.reset(new PragmaWeakHandler());
179 PP.AddPragmaHandler(WeakHandler.get());
180
181 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
182 PP.AddPragmaHandler(RedefineExtnameHandler.get());
183
184 FPContractHandler.reset(new PragmaFPContractHandler());
185 PP.AddPragmaHandler("STDC", FPContractHandler.get());
186
187 if (getLangOpts().OpenCL) {
188 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
189 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
190
191 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
192 }
193 if (getLangOpts().OpenMP)
194 OpenMPHandler.reset(new PragmaOpenMPHandler());
195 else
196 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
197 PP.AddPragmaHandler(OpenMPHandler.get());
198
199 if (getLangOpts().MicrosoftExt) {
200 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
201 PP.AddPragmaHandler(MSCommentHandler.get());
202 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
203 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
204 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
205 PP.AddPragmaHandler(MSPointersToMembers.get());
206 MSVtorDisp.reset(new PragmaMSVtorDisp());
207 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000208 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000209 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000210 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
211 PP.AddPragmaHandler(MSDataSeg.get());
212 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
213 PP.AddPragmaHandler(MSBSSSeg.get());
214 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
215 PP.AddPragmaHandler(MSConstSeg.get());
216 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
217 PP.AddPragmaHandler(MSCodeSeg.get());
218 MSSection.reset(new PragmaMSPragma("section"));
219 PP.AddPragmaHandler(MSSection.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000220 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000221
222 OptimizeHandler.reset(new PragmaOptimizeHandler(Actions));
223 PP.AddPragmaHandler("clang", OptimizeHandler.get());
224
225 LoopHintHandler.reset(new PragmaLoopHintHandler());
226 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000227
228 UnrollHintHandler.reset(new PragmaUnrollHintHandler("unroll"));
229 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000230
231 NoUnrollHintHandler.reset(new PragmaUnrollHintHandler("nounroll"));
232 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000233}
234
235void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000236 // Remove the pragma handlers we installed.
237 PP.RemovePragmaHandler(AlignHandler.get());
238 AlignHandler.reset();
239 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
240 GCCVisibilityHandler.reset();
241 PP.RemovePragmaHandler(OptionsHandler.get());
242 OptionsHandler.reset();
243 PP.RemovePragmaHandler(PackHandler.get());
244 PackHandler.reset();
245 PP.RemovePragmaHandler(MSStructHandler.get());
246 MSStructHandler.reset();
247 PP.RemovePragmaHandler(UnusedHandler.get());
248 UnusedHandler.reset();
249 PP.RemovePragmaHandler(WeakHandler.get());
250 WeakHandler.reset();
251 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
252 RedefineExtnameHandler.reset();
253
254 if (getLangOpts().OpenCL) {
255 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
256 OpenCLExtensionHandler.reset();
257 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
258 }
259 PP.RemovePragmaHandler(OpenMPHandler.get());
260 OpenMPHandler.reset();
261
262 if (getLangOpts().MicrosoftExt) {
263 PP.RemovePragmaHandler(MSCommentHandler.get());
264 MSCommentHandler.reset();
265 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
266 MSDetectMismatchHandler.reset();
267 PP.RemovePragmaHandler(MSPointersToMembers.get());
268 MSPointersToMembers.reset();
269 PP.RemovePragmaHandler(MSVtorDisp.get());
270 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000271 PP.RemovePragmaHandler(MSInitSeg.get());
272 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000273 PP.RemovePragmaHandler(MSDataSeg.get());
274 MSDataSeg.reset();
275 PP.RemovePragmaHandler(MSBSSSeg.get());
276 MSBSSSeg.reset();
277 PP.RemovePragmaHandler(MSConstSeg.get());
278 MSConstSeg.reset();
279 PP.RemovePragmaHandler(MSCodeSeg.get());
280 MSCodeSeg.reset();
281 PP.RemovePragmaHandler(MSSection.get());
282 MSSection.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000283 }
284
285 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
286 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000287
288 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
289 OptimizeHandler.reset();
290
291 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
292 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000293
294 PP.RemovePragmaHandler(UnrollHintHandler.get());
295 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000296
297 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
298 NoUnrollHintHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000299}
300
301/// \brief Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000302///
303/// Each annot_pragma_unused is followed by the argument token so e.g.
304/// "#pragma unused(x,y)" becomes:
305/// annot_pragma_unused 'x' annot_pragma_unused 'y'
306void Parser::HandlePragmaUnused() {
307 assert(Tok.is(tok::annot_pragma_unused));
308 SourceLocation UnusedLoc = ConsumeToken();
309 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
310 ConsumeToken(); // The argument token.
311}
Eli Friedman570024a2010-08-05 06:57:20 +0000312
Rafael Espindola273fd772012-01-26 02:02:57 +0000313void Parser::HandlePragmaVisibility() {
314 assert(Tok.is(tok::annot_pragma_vis));
315 const IdentifierInfo *VisType =
316 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
317 SourceLocation VisLoc = ConsumeToken();
318 Actions.ActOnPragmaVisibility(VisType, VisLoc);
319}
320
Eli Friedmanec52f922012-02-23 23:47:16 +0000321struct PragmaPackInfo {
322 Sema::PragmaPackKind Kind;
323 IdentifierInfo *Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000324 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000325 SourceLocation LParenLoc;
326 SourceLocation RParenLoc;
327};
328
329void Parser::HandlePragmaPack() {
330 assert(Tok.is(tok::annot_pragma_pack));
331 PragmaPackInfo *Info =
332 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
333 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000334 ExprResult Alignment;
335 if (Info->Alignment.is(tok::numeric_constant)) {
336 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
337 if (Alignment.isInvalid())
338 return;
339 }
340 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanec52f922012-02-23 23:47:16 +0000341 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +0000342}
343
Eli Friedman68be1642012-10-04 02:36:51 +0000344void Parser::HandlePragmaMSStruct() {
345 assert(Tok.is(tok::annot_pragma_msstruct));
346 Sema::PragmaMSStructKind Kind =
347 static_cast<Sema::PragmaMSStructKind>(
348 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
349 Actions.ActOnPragmaMSStruct(Kind);
350 ConsumeToken(); // The annotation token.
351}
352
353void Parser::HandlePragmaAlign() {
354 assert(Tok.is(tok::annot_pragma_align));
355 Sema::PragmaOptionsAlignKind Kind =
356 static_cast<Sema::PragmaOptionsAlignKind>(
357 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
358 SourceLocation PragmaLoc = ConsumeToken();
359 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
360}
361
362void Parser::HandlePragmaWeak() {
363 assert(Tok.is(tok::annot_pragma_weak));
364 SourceLocation PragmaLoc = ConsumeToken();
365 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
366 Tok.getLocation());
367 ConsumeToken(); // The weak name.
368}
369
370void Parser::HandlePragmaWeakAlias() {
371 assert(Tok.is(tok::annot_pragma_weakalias));
372 SourceLocation PragmaLoc = ConsumeToken();
373 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
374 SourceLocation WeakNameLoc = Tok.getLocation();
375 ConsumeToken();
376 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
377 SourceLocation AliasNameLoc = Tok.getLocation();
378 ConsumeToken();
379 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
380 WeakNameLoc, AliasNameLoc);
381
382}
383
384void Parser::HandlePragmaRedefineExtname() {
385 assert(Tok.is(tok::annot_pragma_redefine_extname));
386 SourceLocation RedefLoc = ConsumeToken();
387 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
388 SourceLocation RedefNameLoc = Tok.getLocation();
389 ConsumeToken();
390 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
391 SourceLocation AliasNameLoc = Tok.getLocation();
392 ConsumeToken();
393 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
394 RedefNameLoc, AliasNameLoc);
395}
396
397void Parser::HandlePragmaFPContract() {
398 assert(Tok.is(tok::annot_pragma_fp_contract));
399 tok::OnOffSwitch OOS =
400 static_cast<tok::OnOffSwitch>(
401 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
402 Actions.ActOnPragmaFPContract(OOS);
403 ConsumeToken(); // The annotation token.
404}
405
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000406StmtResult Parser::HandlePragmaCaptured()
407{
408 assert(Tok.is(tok::annot_pragma_captured));
409 ConsumeToken();
410
411 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000412 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000413 return StmtError();
414 }
415
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000416 SourceLocation Loc = Tok.getLocation();
417
418 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000419 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
420 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000421
422 StmtResult R = ParseCompoundStatement();
423 CapturedRegionScope.Exit();
424
425 if (R.isInvalid()) {
426 Actions.ActOnCapturedRegionError();
427 return StmtError();
428 }
429
430 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000431}
432
Eli Friedman68be1642012-10-04 02:36:51 +0000433namespace {
434 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
435}
436
437void Parser::HandlePragmaOpenCLExtension() {
438 assert(Tok.is(tok::annot_pragma_opencl_extension));
439 OpenCLExtData data =
440 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
441 unsigned state = data.getInt();
442 IdentifierInfo *ename = data.getPointer();
443 SourceLocation NameLoc = Tok.getLocation();
444 ConsumeToken(); // The annotation token.
445
446 OpenCLOptions &f = Actions.getOpenCLOptions();
447 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
448 // overriding all previously issued extension directives, but only if the
449 // behavior is set to disable."
450 if (state == 0 && ename->isStr("all")) {
451#define OPENCLEXT(nm) f.nm = 0;
452#include "clang/Basic/OpenCLExtensions.def"
453 }
454#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
455#include "clang/Basic/OpenCLExtensions.def"
456 else {
457 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
458 return;
459 }
460}
461
David Majnemer4bb09802014-02-10 19:50:15 +0000462void Parser::HandlePragmaMSPointersToMembers() {
463 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000464 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
465 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000466 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
467 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
468 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
469}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000470
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000471void Parser::HandlePragmaMSVtorDisp() {
472 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
473 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
474 Sema::PragmaVtorDispKind Kind =
475 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
476 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
477 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
478 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
479}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000480
Warren Huntc3b18962014-04-08 22:30:47 +0000481void Parser::HandlePragmaMSPragma() {
482 assert(Tok.is(tok::annot_pragma_ms_pragma));
483 // Grab the tokens out of the annotation and enter them into the stream.
484 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
485 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
486 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
487 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000488 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000489 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000490
Warren Huntc3b18962014-04-08 22:30:47 +0000491 // Figure out which #pragma we're dealing with. The switch has no default
492 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000493 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000494 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
495 .Case("data_seg", &Parser::HandlePragmaMSSegment)
496 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
497 .Case("const_seg", &Parser::HandlePragmaMSSegment)
498 .Case("code_seg", &Parser::HandlePragmaMSSegment)
499 .Case("section", &Parser::HandlePragmaMSSection)
500 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000501
502 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
503 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
504 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000505 while (Tok.isNot(tok::eof))
506 PP.Lex(Tok);
507 PP.Lex(Tok);
508 }
509}
510
Reid Kleckner722b1df2014-07-18 00:13:16 +0000511bool Parser::HandlePragmaMSSection(StringRef PragmaName,
512 SourceLocation PragmaLocation) {
513 if (Tok.isNot(tok::l_paren)) {
514 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
515 return false;
516 }
Warren Huntc3b18962014-04-08 22:30:47 +0000517 PP.Lex(Tok); // (
518 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000519 if (Tok.isNot(tok::string_literal)) {
520 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
521 << PragmaName;
522 return false;
523 }
524 ExprResult StringResult = ParseStringLiteralExpression();
525 if (StringResult.isInvalid())
526 return false; // Already diagnosed.
527 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
528 if (SegmentName->getCharByteWidth() != 1) {
529 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
530 << PragmaName;
531 return false;
532 }
Warren Huntc3b18962014-04-08 22:30:47 +0000533 int SectionFlags = 0;
534 while (Tok.is(tok::comma)) {
535 PP.Lex(Tok); // ,
Reid Kleckner722b1df2014-07-18 00:13:16 +0000536 if (!Tok.isAnyIdentifier()) {
537 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
538 << PragmaName;
539 return false;
540 }
Warren Huntc3b18962014-04-08 22:30:47 +0000541 Sema::PragmaSectionFlag Flag =
542 llvm::StringSwitch<Sema::PragmaSectionFlag>(
543 Tok.getIdentifierInfo()->getName())
544 .Case("read", Sema::PSF_Read)
545 .Case("write", Sema::PSF_Write)
546 .Case("execute", Sema::PSF_Execute)
547 .Case("shared", Sema::PSF_Invalid)
548 .Case("nopage", Sema::PSF_Invalid)
549 .Case("nocache", Sema::PSF_Invalid)
550 .Case("discard", Sema::PSF_Invalid)
551 .Case("remove", Sema::PSF_Invalid)
552 .Default(Sema::PSF_None);
553 if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000554 PP.Diag(PragmaLocation, Flag == Sema::PSF_None
555 ? diag::warn_pragma_invalid_specific_action
556 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000557 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000558 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000559 }
560 SectionFlags |= Flag;
561 PP.Lex(Tok); // Identifier
562 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000563 if (Tok.isNot(tok::r_paren)) {
564 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
565 return false;
566 }
Warren Huntc3b18962014-04-08 22:30:47 +0000567 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000568 if (Tok.isNot(tok::eof)) {
569 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
570 << PragmaName;
571 return false;
572 }
Warren Huntc3b18962014-04-08 22:30:47 +0000573 PP.Lex(Tok); // eof
574 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000575 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000576}
577
Reid Kleckner722b1df2014-07-18 00:13:16 +0000578bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
579 SourceLocation PragmaLocation) {
580 if (Tok.isNot(tok::l_paren)) {
581 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
582 return false;
583 }
Warren Huntc3b18962014-04-08 22:30:47 +0000584 PP.Lex(Tok); // (
585 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000586 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000587 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000588 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000589 if (PushPop == "push")
590 Action = Sema::PSK_Push;
591 else if (PushPop == "pop")
592 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000593 else {
594 PP.Diag(PragmaLocation,
595 diag::warn_pragma_expected_section_push_pop_or_name)
596 << PragmaName;
597 return false;
598 }
Warren Huntc3b18962014-04-08 22:30:47 +0000599 if (Action != Sema::PSK_Reset) {
600 PP.Lex(Tok); // push | pop
601 if (Tok.is(tok::comma)) {
602 PP.Lex(Tok); // ,
603 // If we've got a comma, we either need a label or a string.
604 if (Tok.isAnyIdentifier()) {
605 SlotLabel = Tok.getIdentifierInfo()->getName();
606 PP.Lex(Tok); // identifier
607 if (Tok.is(tok::comma))
608 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000609 else if (Tok.isNot(tok::r_paren)) {
610 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
611 << PragmaName;
612 return false;
613 }
Warren Huntc3b18962014-04-08 22:30:47 +0000614 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000615 } else if (Tok.isNot(tok::r_paren)) {
616 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
617 return false;
618 }
Warren Huntc3b18962014-04-08 22:30:47 +0000619 }
620 }
621 // Grab the string literal for our section name.
622 StringLiteral *SegmentName = nullptr;
623 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000624 if (Tok.isNot(tok::string_literal)) {
625 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000626 diag::warn_pragma_expected_section_name :
627 diag::warn_pragma_expected_section_label_or_name :
628 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000629 PP.Diag(PragmaLocation, DiagID) << PragmaName;
630 return false;
631 }
632 ExprResult StringResult = ParseStringLiteralExpression();
633 if (StringResult.isInvalid())
634 return false; // Already diagnosed.
635 SegmentName = cast<StringLiteral>(StringResult.get());
636 if (SegmentName->getCharByteWidth() != 1) {
637 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
638 << PragmaName;
639 return false;
640 }
Warren Huntc3b18962014-04-08 22:30:47 +0000641 // Setting section "" has no effect
642 if (SegmentName->getLength())
643 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
644 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000645 if (Tok.isNot(tok::r_paren)) {
646 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
647 return false;
648 }
Warren Huntc3b18962014-04-08 22:30:47 +0000649 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000650 if (Tok.isNot(tok::eof)) {
651 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
652 << PragmaName;
653 return false;
654 }
Warren Huntc3b18962014-04-08 22:30:47 +0000655 PP.Lex(Tok); // eof
656 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
657 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000658 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000659}
660
Reid Kleckner1a711b12014-07-22 00:53:05 +0000661// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000662bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
663 SourceLocation PragmaLocation) {
Reid Kleckner1a711b12014-07-22 00:53:05 +0000664 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
665 PragmaName))
666 return false;
667
668 // Parse either the known section names or the string section name.
669 StringLiteral *SegmentName = nullptr;
670 if (Tok.isAnyIdentifier()) {
671 auto *II = Tok.getIdentifierInfo();
672 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
673 .Case("compiler", "\".CRT$XCC\"")
674 .Case("lib", "\".CRT$XCL\"")
675 .Case("user", "\".CRT$XCU\"")
676 .Default("");
677
678 if (!Section.empty()) {
679 // Pretend the user wrote the appropriate string literal here.
680 Token Toks[1];
681 Toks[0].startToken();
682 Toks[0].setKind(tok::string_literal);
683 Toks[0].setLocation(Tok.getLocation());
684 Toks[0].setLiteralData(Section.data());
685 Toks[0].setLength(Section.size());
686 SegmentName =
687 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
688 PP.Lex(Tok);
689 }
690 } else if (Tok.is(tok::string_literal)) {
691 ExprResult StringResult = ParseStringLiteralExpression();
692 if (StringResult.isInvalid())
693 return false;
694 SegmentName = cast<StringLiteral>(StringResult.get());
695 if (SegmentName->getCharByteWidth() != 1) {
696 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
697 << PragmaName;
698 return false;
699 }
700 // FIXME: Add support for the '[, func-name]' part of the pragma.
701 }
702
703 if (!SegmentName) {
704 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
705 return false;
706 }
707
708 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
709 PragmaName) ||
710 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
711 PragmaName))
712 return false;
713
714 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
715 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000716}
717
718struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000719 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +0000720 Token Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000721 Token Value;
722 bool HasValue;
Eli Bendersky06a40422014-06-06 20:31:48 +0000723};
724
725LoopHint Parser::HandlePragmaLoopHint() {
726 assert(Tok.is(tok::annot_pragma_loop_hint));
727 PragmaLoopHintInfo *Info =
728 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
729
730 LoopHint Hint;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000731 Hint.PragmaNameLoc =
732 IdentifierLoc::create(Actions.Context, Info->PragmaName.getLocation(),
733 Info->PragmaName.getIdentifierInfo());
Eli Bendersky06a40422014-06-06 20:31:48 +0000734 Hint.OptionLoc =
735 IdentifierLoc::create(Actions.Context, Info->Option.getLocation(),
736 Info->Option.getIdentifierInfo());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000737 if (Info->HasValue) {
738 Hint.Range =
739 SourceRange(Info->Option.getLocation(), Info->Value.getLocation());
740 Hint.ValueLoc =
741 IdentifierLoc::create(Actions.Context, Info->Value.getLocation(),
742 Info->Value.getIdentifierInfo());
Eli Bendersky06a40422014-06-06 20:31:48 +0000743
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000744 // FIXME: We should allow non-type template parameters for the loop hint
745 // value. See bug report #19610
746 if (Info->Value.is(tok::numeric_constant))
747 Hint.ValueExpr = Actions.ActOnNumericConstant(Info->Value).get();
748 else
749 Hint.ValueExpr = nullptr;
750 } else {
751 Hint.Range = SourceRange(Info->PragmaName.getLocation());
752 Hint.ValueLoc = nullptr;
Eli Bendersky06a40422014-06-06 20:31:48 +0000753 Hint.ValueExpr = nullptr;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000754 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000755
756 return Hint;
757}
758
759// #pragma GCC visibility comes in two variants:
760// 'push' '(' [visibility] ')'
761// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000762void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
763 PragmaIntroducerKind Introducer,
764 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000765 SourceLocation VisLoc = VisTok.getLocation();
766
767 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000768 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000769
770 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
771
Eli Friedman570024a2010-08-05 06:57:20 +0000772 const IdentifierInfo *VisType;
773 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +0000774 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +0000775 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000776 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000777 if (Tok.isNot(tok::l_paren)) {
778 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
779 << "visibility";
780 return;
781 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000782 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000783 VisType = Tok.getIdentifierInfo();
784 if (!VisType) {
785 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
786 << "visibility";
787 return;
788 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000789 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000790 if (Tok.isNot(tok::r_paren)) {
791 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
792 << "visibility";
793 return;
794 }
795 } else {
796 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
797 << "visibility";
798 return;
799 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000800 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000801 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000802 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
803 << "visibility";
804 return;
805 }
806
Rafael Espindola273fd772012-01-26 02:02:57 +0000807 Token *Toks = new Token[1];
808 Toks[0].startToken();
809 Toks[0].setKind(tok::annot_pragma_vis);
810 Toks[0].setLocation(VisLoc);
811 Toks[0].setAnnotationValue(
812 const_cast<void*>(static_cast<const void*>(VisType)));
813 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
814 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000815}
816
Daniel Dunbar921b9682008-10-04 19:21:03 +0000817// #pragma pack(...) comes in the following delicious flavors:
818// pack '(' [integer] ')'
819// pack '(' 'show' ')'
820// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000821void PragmaPackHandler::HandlePragma(Preprocessor &PP,
822 PragmaIntroducerKind Introducer,
823 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000824 SourceLocation PackLoc = PackTok.getLocation();
825
826 Token Tok;
827 PP.Lex(Tok);
828 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000829 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000830 return;
831 }
832
John McCallfaf5fb42010-08-26 23:41:50 +0000833 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Craig Topper161e4db2014-05-21 06:02:52 +0000834 IdentifierInfo *Name = nullptr;
Eli Friedman68be1642012-10-04 02:36:51 +0000835 Token Alignment;
836 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000837 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000838 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000839 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000840 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000841
842 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000843
844 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
845 // the push/pop stack.
846 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000847 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000848 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000849 } else if (Tok.is(tok::identifier)) {
850 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000851 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000852 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000853 PP.Lex(Tok);
854 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000855 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000856 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000857 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000858 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000859 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000860 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000861 return;
Mike Stump11289f42009-09-09 15:08:12 +0000862 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000863 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000864
Daniel Dunbar921b9682008-10-04 19:21:03 +0000865 if (Tok.is(tok::comma)) {
866 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000867
Daniel Dunbar921b9682008-10-04 19:21:03 +0000868 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000869 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000870
871 PP.Lex(Tok);
872 } else if (Tok.is(tok::identifier)) {
873 Name = Tok.getIdentifierInfo();
874 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000875
Daniel Dunbar921b9682008-10-04 19:21:03 +0000876 if (Tok.is(tok::comma)) {
877 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000878
Daniel Dunbar921b9682008-10-04 19:21:03 +0000879 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000880 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000881 return;
882 }
Mike Stump11289f42009-09-09 15:08:12 +0000883
Eli Friedman68be1642012-10-04 02:36:51 +0000884 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000885
886 PP.Lex(Tok);
887 }
888 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000889 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000890 return;
891 }
892 }
893 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000894 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000895 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
896 // the push/pop stack.
897 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
898 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000899 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000900
901 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000902 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000903 return;
904 }
905
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000906 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000907 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000908 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000909 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
910 return;
911 }
912
Daniel Dunbar340cf242012-02-29 01:38:22 +0000913 PragmaPackInfo *Info =
914 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
915 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
916 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +0000917 Info->Kind = Kind;
918 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000919 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000920 Info->LParenLoc = LParenLoc;
921 Info->RParenLoc = RParenLoc;
922
Daniel Dunbar340cf242012-02-29 01:38:22 +0000923 Token *Toks =
924 (Token*) PP.getPreprocessorAllocator().Allocate(
925 sizeof(Token) * 1, llvm::alignOf<Token>());
926 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +0000927 Toks[0].startToken();
928 Toks[0].setKind(tok::annot_pragma_pack);
929 Toks[0].setLocation(PackLoc);
930 Toks[0].setAnnotationValue(static_cast<void*>(Info));
931 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +0000932 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000933}
934
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000935// #pragma ms_struct on
936// #pragma ms_struct off
937void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
938 PragmaIntroducerKind Introducer,
939 Token &MSStructTok) {
940 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
941
942 Token Tok;
943 PP.Lex(Tok);
944 if (Tok.isNot(tok::identifier)) {
945 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
946 return;
947 }
948 const IdentifierInfo *II = Tok.getIdentifierInfo();
949 if (II->isStr("on")) {
950 Kind = Sema::PMSST_ON;
951 PP.Lex(Tok);
952 }
953 else if (II->isStr("off") || II->isStr("reset"))
954 PP.Lex(Tok);
955 else {
956 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
957 return;
958 }
959
960 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +0000961 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
962 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000963 return;
964 }
Eli Friedman68be1642012-10-04 02:36:51 +0000965
966 Token *Toks =
967 (Token*) PP.getPreprocessorAllocator().Allocate(
968 sizeof(Token) * 1, llvm::alignOf<Token>());
969 new (Toks) Token();
970 Toks[0].startToken();
971 Toks[0].setKind(tok::annot_pragma_msstruct);
972 Toks[0].setLocation(MSStructTok.getLocation());
973 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
974 static_cast<uintptr_t>(Kind)));
975 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
976 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000977}
978
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000979// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
980// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +0000981static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000982 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000983 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000984
985 if (IsOptions) {
986 PP.Lex(Tok);
987 if (Tok.isNot(tok::identifier) ||
988 !Tok.getIdentifierInfo()->isStr("align")) {
989 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
990 return;
991 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000992 }
Daniel Dunbar663e8092010-05-27 18:42:09 +0000993
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000994 PP.Lex(Tok);
995 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000996 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
997 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000998 return;
999 }
1000
1001 PP.Lex(Tok);
1002 if (Tok.isNot(tok::identifier)) {
1003 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001004 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001005 return;
1006 }
1007
John McCallfaf5fb42010-08-26 23:41:50 +00001008 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001009 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001010 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001011 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001012 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001013 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001014 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001015 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001016 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001017 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001018 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001019 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001020 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001021 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001022 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001023 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1024 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001025 return;
1026 }
1027
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001028 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001029 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001030 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001031 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001032 return;
1033 }
1034
Eli Friedman68be1642012-10-04 02:36:51 +00001035 Token *Toks =
1036 (Token*) PP.getPreprocessorAllocator().Allocate(
1037 sizeof(Token) * 1, llvm::alignOf<Token>());
1038 new (Toks) Token();
1039 Toks[0].startToken();
1040 Toks[0].setKind(tok::annot_pragma_align);
1041 Toks[0].setLocation(FirstTok.getLocation());
1042 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1043 static_cast<uintptr_t>(Kind)));
1044 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1045 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001046}
1047
Douglas Gregorc7d65762010-09-09 22:45:38 +00001048void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
1049 PragmaIntroducerKind Introducer,
1050 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001051 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001052}
1053
Douglas Gregorc7d65762010-09-09 22:45:38 +00001054void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
1055 PragmaIntroducerKind Introducer,
1056 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001057 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001058}
1059
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001060// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +00001061void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
1062 PragmaIntroducerKind Introducer,
1063 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001064 // FIXME: Should we be expanding macros here? My guess is no.
1065 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001066
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001067 // Lex the left '('.
1068 Token Tok;
1069 PP.Lex(Tok);
1070 if (Tok.isNot(tok::l_paren)) {
1071 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1072 return;
1073 }
Mike Stump11289f42009-09-09 15:08:12 +00001074
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001075 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001076 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001077 SourceLocation RParenLoc;
1078 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001079
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001080 while (true) {
1081 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001082
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001083 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001084 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001085 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001086 LexID = false;
1087 continue;
1088 }
1089
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001090 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001091 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1092 return;
1093 }
Mike Stump11289f42009-09-09 15:08:12 +00001094
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001095 // We are execting a ')' or a ','.
1096 if (Tok.is(tok::comma)) {
1097 LexID = true;
1098 continue;
1099 }
Mike Stump11289f42009-09-09 15:08:12 +00001100
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001101 if (Tok.is(tok::r_paren)) {
1102 RParenLoc = Tok.getLocation();
1103 break;
1104 }
Mike Stump11289f42009-09-09 15:08:12 +00001105
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001106 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001107 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001108 return;
1109 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001110
1111 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001112 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001113 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1114 "unused";
1115 return;
1116 }
1117
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001118 // Verify that we have a location for the right parenthesis.
1119 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001120 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001121
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001122 // For each identifier token, insert into the token stream a
1123 // annot_pragma_unused token followed by the identifier token.
1124 // This allows us to cache a "#pragma unused" that occurs inside an inline
1125 // C++ member function.
1126
Daniel Dunbar340cf242012-02-29 01:38:22 +00001127 Token *Toks =
1128 (Token*) PP.getPreprocessorAllocator().Allocate(
1129 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001130 for (unsigned i=0; i != Identifiers.size(); i++) {
1131 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1132 pragmaUnusedTok.startToken();
1133 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1134 pragmaUnusedTok.setLocation(UnusedLoc);
1135 idTok = Identifiers[i];
1136 }
Daniel Dunbar340cf242012-02-29 01:38:22 +00001137 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
1138 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001139}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001140
1141// #pragma weak identifier
1142// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +00001143void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
1144 PragmaIntroducerKind Introducer,
1145 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001146 SourceLocation WeakLoc = WeakTok.getLocation();
1147
1148 Token Tok;
1149 PP.Lex(Tok);
1150 if (Tok.isNot(tok::identifier)) {
1151 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
1152 return;
1153 }
1154
Eli Friedman68be1642012-10-04 02:36:51 +00001155 Token WeakName = Tok;
1156 bool HasAlias = false;
1157 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001158
1159 PP.Lex(Tok);
1160 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001161 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001162 PP.Lex(Tok);
1163 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00001164 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001165 << "weak";
1166 return;
1167 }
Eli Friedman68be1642012-10-04 02:36:51 +00001168 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001169 PP.Lex(Tok);
1170 }
1171
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001172 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001173 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
1174 return;
1175 }
1176
Eli Friedman68be1642012-10-04 02:36:51 +00001177 if (HasAlias) {
1178 Token *Toks =
1179 (Token*) PP.getPreprocessorAllocator().Allocate(
1180 sizeof(Token) * 3, llvm::alignOf<Token>());
1181 Token &pragmaUnusedTok = Toks[0];
1182 pragmaUnusedTok.startToken();
1183 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
1184 pragmaUnusedTok.setLocation(WeakLoc);
1185 Toks[1] = WeakName;
1186 Toks[2] = AliasName;
1187 PP.EnterTokenStream(Toks, 3,
1188 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001189 } else {
Eli Friedman68be1642012-10-04 02:36:51 +00001190 Token *Toks =
1191 (Token*) PP.getPreprocessorAllocator().Allocate(
1192 sizeof(Token) * 2, llvm::alignOf<Token>());
1193 Token &pragmaUnusedTok = Toks[0];
1194 pragmaUnusedTok.startToken();
1195 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1196 pragmaUnusedTok.setLocation(WeakLoc);
1197 Toks[1] = WeakName;
1198 PP.EnterTokenStream(Toks, 2,
1199 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001200 }
1201}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001202
David Chisnall0867d9c2012-02-18 16:12:34 +00001203// #pragma redefine_extname identifier identifier
1204void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1205 PragmaIntroducerKind Introducer,
1206 Token &RedefToken) {
1207 SourceLocation RedefLoc = RedefToken.getLocation();
1208
1209 Token Tok;
1210 PP.Lex(Tok);
1211 if (Tok.isNot(tok::identifier)) {
1212 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1213 "redefine_extname";
1214 return;
1215 }
1216
Eli Friedman68be1642012-10-04 02:36:51 +00001217 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001218 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001219
David Chisnall0867d9c2012-02-18 16:12:34 +00001220 if (Tok.isNot(tok::identifier)) {
1221 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1222 << "redefine_extname";
1223 return;
1224 }
Eli Friedman68be1642012-10-04 02:36:51 +00001225
1226 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001227 PP.Lex(Tok);
1228
1229 if (Tok.isNot(tok::eod)) {
1230 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1231 "redefine_extname";
1232 return;
1233 }
1234
Eli Friedman68be1642012-10-04 02:36:51 +00001235 Token *Toks =
1236 (Token*) PP.getPreprocessorAllocator().Allocate(
1237 sizeof(Token) * 3, llvm::alignOf<Token>());
1238 Token &pragmaRedefTok = Toks[0];
1239 pragmaRedefTok.startToken();
1240 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1241 pragmaRedefTok.setLocation(RedefLoc);
1242 Toks[1] = RedefName;
1243 Toks[2] = AliasName;
1244 PP.EnterTokenStream(Toks, 3,
1245 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00001246}
1247
1248
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001249void
1250PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1251 PragmaIntroducerKind Introducer,
1252 Token &Tok) {
1253 tok::OnOffSwitch OOS;
1254 if (PP.LexOnOffSwitch(OOS))
1255 return;
1256
Eli Friedman68be1642012-10-04 02:36:51 +00001257 Token *Toks =
1258 (Token*) PP.getPreprocessorAllocator().Allocate(
1259 sizeof(Token) * 1, llvm::alignOf<Token>());
1260 new (Toks) Token();
1261 Toks[0].startToken();
1262 Toks[0].setKind(tok::annot_pragma_fp_contract);
1263 Toks[0].setLocation(Tok.getLocation());
1264 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1265 static_cast<uintptr_t>(OOS)));
1266 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1267 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001268}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001269
1270void
1271PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1272 PragmaIntroducerKind Introducer,
1273 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001274 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001275 if (Tok.isNot(tok::identifier)) {
1276 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1277 "OPENCL";
1278 return;
1279 }
1280 IdentifierInfo *ename = Tok.getIdentifierInfo();
1281 SourceLocation NameLoc = Tok.getLocation();
1282
1283 PP.Lex(Tok);
1284 if (Tok.isNot(tok::colon)) {
1285 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1286 return;
1287 }
1288
1289 PP.Lex(Tok);
1290 if (Tok.isNot(tok::identifier)) {
1291 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1292 return;
1293 }
1294 IdentifierInfo *op = Tok.getIdentifierInfo();
1295
1296 unsigned state;
1297 if (op->isStr("enable")) {
1298 state = 1;
1299 } else if (op->isStr("disable")) {
1300 state = 0;
1301 } else {
1302 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1303 return;
1304 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001305 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001306
Eli Friedman68be1642012-10-04 02:36:51 +00001307 PP.Lex(Tok);
1308 if (Tok.isNot(tok::eod)) {
1309 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1310 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001311 return;
1312 }
Eli Friedman68be1642012-10-04 02:36:51 +00001313
1314 OpenCLExtData data(ename, state);
1315 Token *Toks =
1316 (Token*) PP.getPreprocessorAllocator().Allocate(
1317 sizeof(Token) * 1, llvm::alignOf<Token>());
1318 new (Toks) Token();
1319 Toks[0].startToken();
1320 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1321 Toks[0].setLocation(NameLoc);
1322 Toks[0].setAnnotationValue(data.getOpaqueValue());
1323 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1324 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001325
1326 if (PP.getPPCallbacks())
1327 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1328 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001329}
1330
Alexey Bataeva769e072013-03-22 06:34:35 +00001331/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1332///
1333void
1334PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1335 PragmaIntroducerKind Introducer,
1336 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00001337 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
1338 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00001339 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00001340 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
1341 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00001342 }
1343 PP.DiscardUntilEndOfDirective();
1344}
1345
1346/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1347///
1348void
1349PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1350 PragmaIntroducerKind Introducer,
1351 Token &FirstTok) {
1352 SmallVector<Token, 16> Pragma;
1353 Token Tok;
1354 Tok.startToken();
1355 Tok.setKind(tok::annot_pragma_openmp);
1356 Tok.setLocation(FirstTok.getLocation());
1357
1358 while (Tok.isNot(tok::eod)) {
1359 Pragma.push_back(Tok);
1360 PP.Lex(Tok);
1361 }
1362 SourceLocation EodLoc = Tok.getLocation();
1363 Tok.startToken();
1364 Tok.setKind(tok::annot_pragma_openmp_end);
1365 Tok.setLocation(EodLoc);
1366 Pragma.push_back(Tok);
1367
1368 Token *Toks = new Token[Pragma.size()];
1369 std::copy(Pragma.begin(), Pragma.end(), Toks);
1370 PP.EnterTokenStream(Toks, Pragma.size(),
1371 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1372}
Reid Kleckner002562a2013-05-06 21:02:12 +00001373
David Majnemer4bb09802014-02-10 19:50:15 +00001374/// \brief Handle '#pragma pointers_to_members'
1375// The grammar for this pragma is as follows:
1376//
1377// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1378//
1379// #pragma pointers_to_members '(' 'best_case' ')'
1380// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1381// #pragma pointers_to_members '(' inheritance-model ')'
1382void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1383 PragmaIntroducerKind Introducer,
1384 Token &Tok) {
1385 SourceLocation PointersToMembersLoc = Tok.getLocation();
1386 PP.Lex(Tok);
1387 if (Tok.isNot(tok::l_paren)) {
1388 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1389 << "pointers_to_members";
1390 return;
1391 }
1392 PP.Lex(Tok);
1393 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1394 if (!Arg) {
1395 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1396 << "pointers_to_members";
1397 return;
1398 }
1399 PP.Lex(Tok);
1400
David Majnemer86c318f2014-02-11 21:05:00 +00001401 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001402 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001403 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001404 } else {
1405 if (Arg->isStr("full_generality")) {
1406 if (Tok.is(tok::comma)) {
1407 PP.Lex(Tok);
1408
1409 Arg = Tok.getIdentifierInfo();
1410 if (!Arg) {
1411 PP.Diag(Tok.getLocation(),
1412 diag::err_pragma_pointers_to_members_unknown_kind)
1413 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1414 return;
1415 }
1416 PP.Lex(Tok);
1417 } else if (Tok.is(tok::r_paren)) {
1418 // #pragma pointers_to_members(full_generality) implicitly specifies
1419 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00001420 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00001421 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001422 } else {
1423 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1424 << "full_generality";
1425 return;
1426 }
1427 }
1428
1429 if (Arg) {
1430 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001431 RepresentationMethod =
1432 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001433 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001434 RepresentationMethod =
1435 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001436 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001437 RepresentationMethod =
1438 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001439 } else {
1440 PP.Diag(Tok.getLocation(),
1441 diag::err_pragma_pointers_to_members_unknown_kind)
1442 << Arg << /*HasPointerDeclaration*/ 1;
1443 return;
1444 }
1445 }
1446 }
1447
1448 if (Tok.isNot(tok::r_paren)) {
1449 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1450 << (Arg ? Arg->getName() : "full_generality");
1451 return;
1452 }
1453
1454 PP.Lex(Tok);
1455 if (Tok.isNot(tok::eod)) {
1456 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1457 << "pointers_to_members";
1458 return;
1459 }
1460
1461 Token AnnotTok;
1462 AnnotTok.startToken();
1463 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1464 AnnotTok.setLocation(PointersToMembersLoc);
1465 AnnotTok.setAnnotationValue(
1466 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1467 PP.EnterToken(AnnotTok);
1468}
1469
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001470/// \brief Handle '#pragma vtordisp'
1471// The grammar for this pragma is as follows:
1472//
1473// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1474//
1475// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1476// #pragma vtordisp '(' 'pop' ')'
1477// #pragma vtordisp '(' ')'
1478void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1479 PragmaIntroducerKind Introducer,
1480 Token &Tok) {
1481 SourceLocation VtorDispLoc = Tok.getLocation();
1482 PP.Lex(Tok);
1483 if (Tok.isNot(tok::l_paren)) {
1484 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1485 return;
1486 }
1487 PP.Lex(Tok);
1488
1489 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1490 const IdentifierInfo *II = Tok.getIdentifierInfo();
1491 if (II) {
1492 if (II->isStr("push")) {
1493 // #pragma vtordisp(push, mode)
1494 PP.Lex(Tok);
1495 if (Tok.isNot(tok::comma)) {
1496 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1497 return;
1498 }
1499 PP.Lex(Tok);
1500 Kind = Sema::PVDK_Push;
1501 // not push, could be on/off
1502 } else if (II->isStr("pop")) {
1503 // #pragma vtordisp(pop)
1504 PP.Lex(Tok);
1505 Kind = Sema::PVDK_Pop;
1506 }
1507 // not push or pop, could be on/off
1508 } else {
1509 if (Tok.is(tok::r_paren)) {
1510 // #pragma vtordisp()
1511 Kind = Sema::PVDK_Reset;
1512 }
1513 }
1514
1515
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001516 uint64_t Value = 0;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001517 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1518 const IdentifierInfo *II = Tok.getIdentifierInfo();
1519 if (II && II->isStr("off")) {
1520 PP.Lex(Tok);
1521 Value = 0;
1522 } else if (II && II->isStr("on")) {
1523 PP.Lex(Tok);
1524 Value = 1;
1525 } else if (Tok.is(tok::numeric_constant) &&
1526 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1527 if (Value > 2) {
1528 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1529 << 0 << 2 << "vtordisp";
1530 return;
1531 }
1532 } else {
1533 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1534 << "vtordisp";
1535 return;
1536 }
1537 }
1538
1539 // Finish the pragma: ')' $
1540 if (Tok.isNot(tok::r_paren)) {
1541 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1542 return;
1543 }
1544 PP.Lex(Tok);
1545 if (Tok.isNot(tok::eod)) {
1546 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1547 << "vtordisp";
1548 return;
1549 }
1550
1551 // Enter the annotation.
1552 Token AnnotTok;
1553 AnnotTok.startToken();
1554 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1555 AnnotTok.setLocation(VtorDispLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001556 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1557 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001558 PP.EnterToken(AnnotTok);
1559}
1560
Warren Huntc3b18962014-04-08 22:30:47 +00001561/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1562/// an annotation token.
1563void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1564 PragmaIntroducerKind Introducer,
1565 Token &Tok) {
1566 Token EoF, AnnotTok;
1567 EoF.startToken();
1568 EoF.setKind(tok::eof);
1569 AnnotTok.startToken();
1570 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1571 AnnotTok.setLocation(Tok.getLocation());
1572 SmallVector<Token, 8> TokenVector;
1573 // Suck up all of the tokens before the eod.
1574 for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1575 TokenVector.push_back(Tok);
1576 // Add a sentinal EoF token to the end of the list.
1577 TokenVector.push_back(EoF);
1578 // We must allocate this array with new because EnterTokenStream is going to
1579 // delete it later.
1580 Token *TokenArray = new Token[TokenVector.size()];
1581 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1582 auto Value = new (PP.getPreprocessorAllocator())
1583 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1584 AnnotTok.setAnnotationValue(Value);
1585 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001586}
1587
Aaron Ballman5d041be2013-06-04 02:07:14 +00001588/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1589///
1590/// The syntax is:
1591/// \code
1592/// #pragma detect_mismatch("name", "value")
1593/// \endcode
1594/// Where 'name' and 'value' are quoted strings. The values are embedded in
1595/// the object file and passed along to the linker. If the linker detects a
1596/// mismatch in the object file's values for the given name, a LNK2038 error
1597/// is emitted. See MSDN for more details.
1598void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1599 PragmaIntroducerKind Introducer,
1600 Token &Tok) {
1601 SourceLocation CommentLoc = Tok.getLocation();
1602 PP.Lex(Tok);
1603 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001604 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001605 return;
1606 }
1607
1608 // Read the name to embed, which must be a string literal.
1609 std::string NameString;
1610 if (!PP.LexStringLiteral(Tok, NameString,
1611 "pragma detect_mismatch",
1612 /*MacroExpansion=*/true))
1613 return;
1614
1615 // Read the comma followed by a second string literal.
1616 std::string ValueString;
1617 if (Tok.isNot(tok::comma)) {
1618 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1619 return;
1620 }
1621
1622 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1623 /*MacroExpansion=*/true))
1624 return;
1625
1626 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001627 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001628 return;
1629 }
1630 PP.Lex(Tok); // Eat the r_paren.
1631
1632 if (Tok.isNot(tok::eod)) {
1633 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1634 return;
1635 }
1636
Reid Kleckner71966c92014-02-20 23:37:45 +00001637 // If the pragma is lexically sound, notify any interested PPCallbacks.
1638 if (PP.getPPCallbacks())
1639 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1640 ValueString);
1641
Aaron Ballman5d041be2013-06-04 02:07:14 +00001642 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1643}
1644
Reid Kleckner002562a2013-05-06 21:02:12 +00001645/// \brief Handle the microsoft \#pragma comment extension.
1646///
1647/// The syntax is:
1648/// \code
1649/// #pragma comment(linker, "foo")
1650/// \endcode
1651/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1652/// "foo" is a string, which is fully macro expanded, and permits string
1653/// concatenation, embedded escape characters etc. See MSDN for more details.
1654void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1655 PragmaIntroducerKind Introducer,
1656 Token &Tok) {
1657 SourceLocation CommentLoc = Tok.getLocation();
1658 PP.Lex(Tok);
1659 if (Tok.isNot(tok::l_paren)) {
1660 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1661 return;
1662 }
1663
1664 // Read the identifier.
1665 PP.Lex(Tok);
1666 if (Tok.isNot(tok::identifier)) {
1667 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1668 return;
1669 }
1670
1671 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001672 IdentifierInfo *II = Tok.getIdentifierInfo();
1673 Sema::PragmaMSCommentKind Kind =
1674 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1675 .Case("linker", Sema::PCK_Linker)
1676 .Case("lib", Sema::PCK_Lib)
1677 .Case("compiler", Sema::PCK_Compiler)
1678 .Case("exestr", Sema::PCK_ExeStr)
1679 .Case("user", Sema::PCK_User)
1680 .Default(Sema::PCK_Unknown);
1681 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001682 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1683 return;
1684 }
1685
1686 // Read the optional string if present.
1687 PP.Lex(Tok);
1688 std::string ArgumentString;
1689 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1690 "pragma comment",
1691 /*MacroExpansion=*/true))
1692 return;
1693
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001694 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001695 // FIXME: If the kind is "compiler" warn if the string is present (it is
1696 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001697 // The MSDN docs say that "lib" and "linker" require a string and have a short
1698 // whitelist of linker options they support, but in practice MSVC doesn't
1699 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001700
1701 if (Tok.isNot(tok::r_paren)) {
1702 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1703 return;
1704 }
1705 PP.Lex(Tok); // eat the r_paren.
1706
1707 if (Tok.isNot(tok::eod)) {
1708 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1709 return;
1710 }
1711
Reid Kleckner71966c92014-02-20 23:37:45 +00001712 // If the pragma is lexically sound, notify any interested PPCallbacks.
1713 if (PP.getPPCallbacks())
1714 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1715
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001716 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001717}
Dario Domizioli13a0a382014-05-23 12:13:25 +00001718
1719// #pragma clang optimize off
1720// #pragma clang optimize on
1721void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
1722 PragmaIntroducerKind Introducer,
1723 Token &FirstToken) {
1724 Token Tok;
1725 PP.Lex(Tok);
1726 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001727 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00001728 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00001729 return;
1730 }
1731 if (Tok.isNot(tok::identifier)) {
1732 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1733 << PP.getSpelling(Tok);
1734 return;
1735 }
1736 const IdentifierInfo *II = Tok.getIdentifierInfo();
1737 // The only accepted values are 'on' or 'off'.
1738 bool IsOn = false;
1739 if (II->isStr("on")) {
1740 IsOn = true;
1741 } else if (!II->isStr("off")) {
1742 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
1743 << PP.getSpelling(Tok);
1744 return;
1745 }
1746 PP.Lex(Tok);
1747
1748 if (Tok.isNot(tok::eod)) {
1749 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
1750 << PP.getSpelling(Tok);
1751 return;
1752 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001753
1754 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
1755}
1756
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001757/// \brief Parses loop or unroll pragma hint value and fills in Info.
1758static bool ParseLoopHintValue(Preprocessor &PP, Token Tok, Token &PragmaName,
1759 Token &Option, bool &ValueInParens,
1760 PragmaLoopHintInfo &Info) {
1761 ValueInParens = Tok.is(tok::l_paren);
1762 if (ValueInParens) {
1763 PP.Lex(Tok);
1764 if (Tok.is(tok::r_paren)) {
1765 // Nothing between the parentheses.
1766 std::string PragmaString;
1767 if (PragmaName.getIdentifierInfo()->getName() == "loop") {
1768 PragmaString = "clang loop ";
1769 PragmaString += Option.getIdentifierInfo()->getName();
1770 } else {
1771 assert(PragmaName.getIdentifierInfo()->getName() == "unroll" &&
1772 "Unexpected pragma name");
1773 PragmaString = "unroll";
1774 }
Mark Heffernan450c2382014-07-23 17:31:31 +00001775 // Don't try to emit what the pragma is expecting with the diagnostic
1776 // because the logic is non-trivial and we give expected values in sema
1777 // diagnostics if an invalid argument is given. Here, just note that the
1778 // pragma is missing an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001779 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00001780 << PragmaString << /*Expected=*/false;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001781 return true;
1782 }
1783 }
1784
1785 // FIXME: Value should be stored and parsed as a constant expression.
1786 Token Value = Tok;
1787
1788 if (ValueInParens) {
1789 PP.Lex(Tok);
1790 if (Tok.isNot(tok::r_paren)) {
1791 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
1792 return true;
1793 }
1794 }
1795
1796 Info.PragmaName = PragmaName;
1797 Info.Option = Option;
1798 Info.Value = Value;
1799 Info.HasValue = true;
1800 return false;
1801}
1802
Eli Bendersky06a40422014-06-06 20:31:48 +00001803/// \brief Handle the \#pragma clang loop directive.
1804/// #pragma clang 'loop' loop-hints
1805///
1806/// loop-hints:
1807/// loop-hint loop-hints[opt]
1808///
1809/// loop-hint:
1810/// 'vectorize' '(' loop-hint-keyword ')'
1811/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00001812/// 'unroll' '(' unroll-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001813/// 'vectorize_width' '(' loop-hint-value ')'
1814/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00001815/// 'unroll_count' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00001816///
1817/// loop-hint-keyword:
1818/// 'enable'
1819/// 'disable'
1820///
Mark Heffernan450c2382014-07-23 17:31:31 +00001821/// unroll-hint-keyword:
1822/// 'full'
1823/// 'disable'
1824///
Eli Bendersky06a40422014-06-06 20:31:48 +00001825/// loop-hint-value:
1826/// constant-expression
1827///
1828/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
1829/// try vectorizing the instructions of the loop it precedes. Specifying
1830/// interleave(enable) or interleave_count(_value_) instructs llvm to try
1831/// interleaving multiple iterations of the loop it precedes. The width of the
1832/// vector instructions is specified by vectorize_width() and the number of
1833/// interleaved loop iterations is specified by interleave_count(). Specifying a
1834/// value of 1 effectively disables vectorization/interleaving, even if it is
1835/// possible and profitable, and 0 is invalid. The loop vectorizer currently
1836/// only works on inner loops.
1837///
Eli Bendersky86483b32014-06-11 17:56:26 +00001838/// The unroll and unroll_count directives control the concatenation
Mark Heffernan450c2382014-07-23 17:31:31 +00001839/// unroller. Specifying unroll(full) instructs llvm to try to
Eli Bendersky86483b32014-06-11 17:56:26 +00001840/// unroll the loop completely, and unroll(disable) disables unrolling
1841/// for the loop. Specifying unroll_count(_value_) instructs llvm to
1842/// try to unroll the loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00001843void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
1844 PragmaIntroducerKind Introducer,
1845 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001846 // Incoming token is "loop" from "#pragma clang loop".
1847 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00001848 SmallVector<Token, 1> TokenList;
1849
1850 // Lex the optimization option and verify it is an identifier.
1851 PP.Lex(Tok);
1852 if (Tok.isNot(tok::identifier)) {
1853 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1854 << /*MissingOption=*/true << "";
1855 return;
1856 }
1857
1858 while (Tok.is(tok::identifier)) {
1859 Token Option = Tok;
1860 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
1861
Eli Bendersky86483b32014-06-11 17:56:26 +00001862 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001863 .Case("vectorize", true)
1864 .Case("interleave", true)
1865 .Case("unroll", true)
1866 .Case("vectorize_width", true)
1867 .Case("interleave_count", true)
1868 .Case("unroll_count", true)
1869 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00001870 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001871 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
1872 << /*MissingOption=*/false << OptionInfo;
1873 return;
1874 }
1875
Eli Bendersky06a40422014-06-06 20:31:48 +00001876 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001877 PP.Lex(Tok);
1878 bool ValueInParens;
1879 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
1880 return;
Eli Bendersky06a40422014-06-06 20:31:48 +00001881
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001882 if (!ValueInParens) {
1883 PP.Diag(Info->Value.getLocation(), diag::err_expected) << tok::l_paren;
1884 return;
1885 }
1886
1887 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00001888 Token LoopHintTok;
1889 LoopHintTok.startToken();
1890 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001891 LoopHintTok.setLocation(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00001892 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
1893 TokenList.push_back(LoopHintTok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001894
1895 // Get next optimization option.
1896 PP.Lex(Tok);
Eli Bendersky06a40422014-06-06 20:31:48 +00001897 }
1898
1899 if (Tok.isNot(tok::eod)) {
1900 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1901 << "clang loop";
1902 return;
1903 }
1904
1905 Token *TokenArray = new Token[TokenList.size()];
1906 std::copy(TokenList.begin(), TokenList.end(), TokenArray);
1907
1908 PP.EnterTokenStream(TokenArray, TokenList.size(),
1909 /*DisableMacroExpansion=*/false,
1910 /*OwnsTokens=*/true);
1911}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001912
1913/// \brief Handle the loop unroll optimization pragmas.
1914/// #pragma unroll
1915/// #pragma unroll unroll-hint-value
1916/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00001917/// #pragma nounroll
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001918///
1919/// unroll-hint-value:
1920/// constant-expression
1921///
Mark Heffernanc888e412014-07-24 18:09:38 +00001922/// Loop unrolling hints can be specified with '#pragma unroll' or
1923/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
1924/// contained in parentheses. With no argument the directive instructs llvm to
1925/// try to unroll the loop completely. A positive integer argument can be
1926/// specified to indicate the number of times the loop should be unrolled. To
1927/// maximize compatibility with other compilers the unroll count argument can be
1928/// specified with or without parentheses. Specifying, '#pragma nounroll'
1929/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001930void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
1931 PragmaIntroducerKind Introducer,
1932 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00001933 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
1934 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001935 Token PragmaName = Tok;
1936 PP.Lex(Tok);
1937 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
1938 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00001939 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001940 Info->PragmaName = PragmaName;
1941 Info->Option = PragmaName;
1942 Info->HasValue = false;
Mark Heffernanc888e412014-07-24 18:09:38 +00001943 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll") {
1944 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1945 << "nounroll";
1946 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001947 } else {
1948 // Unroll pragma with an argument: "#pragma unroll N" or
1949 // "#pragma unroll(N)".
1950 bool ValueInParens;
1951 if (ParseLoopHintValue(PP, Tok, PragmaName, PragmaName, ValueInParens,
1952 *Info))
1953 return;
1954
1955 // In CUDA, the argument to '#pragma unroll' should not be contained in
1956 // parentheses.
1957 if (PP.getLangOpts().CUDA && ValueInParens)
1958 PP.Diag(Info->Value.getLocation(),
1959 diag::warn_pragma_unroll_cuda_value_in_parens);
1960
1961 PP.Lex(Tok);
1962 if (Tok.isNot(tok::eod)) {
1963 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1964 << "unroll";
1965 return;
1966 }
1967 }
1968
1969 // Generate the hint token.
1970 Token *TokenArray = new Token[1];
1971 TokenArray[0].startToken();
1972 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
1973 TokenArray[0].setLocation(PragmaName.getLocation());
1974 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
1975 PP.EnterTokenStream(TokenArray, 1, /*DisableMacroExpansion=*/false,
1976 /*OwnsTokens=*/true);
1977}