blob: 133c0e028f510b5beecde6a63d35907ba6305b92 [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"
Chandler Carruth3a022472012-12-04 09:13:33 +000015#include "clang/Lex/Preprocessor.h"
Chris Lattner60f36222009-01-29 05:15:15 +000016#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenekfd14fad2009-03-23 22:28:25 +000017#include "clang/Parse/Parser.h"
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +000018#include "clang/Sema/Scope.h"
Reid Kleckner002562a2013-05-06 21:02:12 +000019#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar921b9682008-10-04 19:21:03 +000020using namespace clang;
21
Reid Kleckner5b086462014-02-20 22:52:09 +000022namespace {
23
24struct PragmaAlignHandler : public PragmaHandler {
25 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000026 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
27 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000028};
29
30struct PragmaGCCVisibilityHandler : public PragmaHandler {
31 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000032 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
33 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000034};
35
36struct PragmaOptionsHandler : public PragmaHandler {
37 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000038 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
39 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000040};
41
42struct PragmaPackHandler : public PragmaHandler {
43 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000044 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
45 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000046};
47
48struct PragmaMSStructHandler : public PragmaHandler {
49 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000050 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
51 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000052};
53
54struct PragmaUnusedHandler : public PragmaHandler {
55 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000056 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
57 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000058};
59
60struct PragmaWeakHandler : public PragmaHandler {
61 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000062 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
63 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000064};
65
66struct PragmaRedefineExtnameHandler : public PragmaHandler {
67 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000068 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
69 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000070};
71
72struct PragmaOpenCLExtensionHandler : public PragmaHandler {
73 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000074 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
75 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000076};
77
78
79struct PragmaFPContractHandler : public PragmaHandler {
80 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000081 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
82 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000083};
84
85struct PragmaNoOpenMPHandler : public PragmaHandler {
86 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000087 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
88 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000089};
90
91struct PragmaOpenMPHandler : public PragmaHandler {
92 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000093 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
94 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000095};
96
97/// PragmaCommentHandler - "\#pragma comment ...".
98struct PragmaCommentHandler : public PragmaHandler {
99 PragmaCommentHandler(Sema &Actions)
100 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000101 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
102 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000103private:
104 Sema &Actions;
105};
106
107struct PragmaDetectMismatchHandler : public PragmaHandler {
108 PragmaDetectMismatchHandler(Sema &Actions)
109 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000110 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
111 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000112private:
113 Sema &Actions;
114};
115
116struct PragmaMSPointersToMembers : public PragmaHandler {
117 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000118 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
119 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000120};
121
122struct PragmaMSVtorDisp : public PragmaHandler {
123 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000124 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
125 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000126};
127
Warren Huntc3b18962014-04-08 22:30:47 +0000128struct PragmaMSPragma : public PragmaHandler {
129 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000130 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
131 Token &FirstToken) override;
132};
133
Reid Kleckner5b086462014-02-20 22:52:09 +0000134} // end namespace
135
136void Parser::initializePragmaHandlers() {
137 AlignHandler.reset(new PragmaAlignHandler());
138 PP.AddPragmaHandler(AlignHandler.get());
139
140 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
141 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
142
143 OptionsHandler.reset(new PragmaOptionsHandler());
144 PP.AddPragmaHandler(OptionsHandler.get());
145
146 PackHandler.reset(new PragmaPackHandler());
147 PP.AddPragmaHandler(PackHandler.get());
148
149 MSStructHandler.reset(new PragmaMSStructHandler());
150 PP.AddPragmaHandler(MSStructHandler.get());
151
152 UnusedHandler.reset(new PragmaUnusedHandler());
153 PP.AddPragmaHandler(UnusedHandler.get());
154
155 WeakHandler.reset(new PragmaWeakHandler());
156 PP.AddPragmaHandler(WeakHandler.get());
157
158 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
159 PP.AddPragmaHandler(RedefineExtnameHandler.get());
160
161 FPContractHandler.reset(new PragmaFPContractHandler());
162 PP.AddPragmaHandler("STDC", FPContractHandler.get());
163
164 if (getLangOpts().OpenCL) {
165 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
166 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
167
168 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
169 }
170 if (getLangOpts().OpenMP)
171 OpenMPHandler.reset(new PragmaOpenMPHandler());
172 else
173 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
174 PP.AddPragmaHandler(OpenMPHandler.get());
175
176 if (getLangOpts().MicrosoftExt) {
177 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
178 PP.AddPragmaHandler(MSCommentHandler.get());
179 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
180 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
181 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
182 PP.AddPragmaHandler(MSPointersToMembers.get());
183 MSVtorDisp.reset(new PragmaMSVtorDisp());
184 PP.AddPragmaHandler(MSVtorDisp.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000185 MSInitSeg.reset(new PragmaMSPragma("init_seg"));
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000186 PP.AddPragmaHandler(MSInitSeg.get());
Warren Huntc3b18962014-04-08 22:30:47 +0000187 MSDataSeg.reset(new PragmaMSPragma("data_seg"));
188 PP.AddPragmaHandler(MSDataSeg.get());
189 MSBSSSeg.reset(new PragmaMSPragma("bss_seg"));
190 PP.AddPragmaHandler(MSBSSSeg.get());
191 MSConstSeg.reset(new PragmaMSPragma("const_seg"));
192 PP.AddPragmaHandler(MSConstSeg.get());
193 MSCodeSeg.reset(new PragmaMSPragma("code_seg"));
194 PP.AddPragmaHandler(MSCodeSeg.get());
195 MSSection.reset(new PragmaMSPragma("section"));
196 PP.AddPragmaHandler(MSSection.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000197 }
198}
199
200void Parser::resetPragmaHandlers() {
201 // Remove the pragma handlers we installed.
202 PP.RemovePragmaHandler(AlignHandler.get());
203 AlignHandler.reset();
204 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
205 GCCVisibilityHandler.reset();
206 PP.RemovePragmaHandler(OptionsHandler.get());
207 OptionsHandler.reset();
208 PP.RemovePragmaHandler(PackHandler.get());
209 PackHandler.reset();
210 PP.RemovePragmaHandler(MSStructHandler.get());
211 MSStructHandler.reset();
212 PP.RemovePragmaHandler(UnusedHandler.get());
213 UnusedHandler.reset();
214 PP.RemovePragmaHandler(WeakHandler.get());
215 WeakHandler.reset();
216 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
217 RedefineExtnameHandler.reset();
218
219 if (getLangOpts().OpenCL) {
220 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
221 OpenCLExtensionHandler.reset();
222 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
223 }
224 PP.RemovePragmaHandler(OpenMPHandler.get());
225 OpenMPHandler.reset();
226
227 if (getLangOpts().MicrosoftExt) {
228 PP.RemovePragmaHandler(MSCommentHandler.get());
229 MSCommentHandler.reset();
230 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
231 MSDetectMismatchHandler.reset();
232 PP.RemovePragmaHandler(MSPointersToMembers.get());
233 MSPointersToMembers.reset();
234 PP.RemovePragmaHandler(MSVtorDisp.get());
235 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000236 PP.RemovePragmaHandler(MSInitSeg.get());
237 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000238 PP.RemovePragmaHandler(MSDataSeg.get());
239 MSDataSeg.reset();
240 PP.RemovePragmaHandler(MSBSSSeg.get());
241 MSBSSSeg.reset();
242 PP.RemovePragmaHandler(MSConstSeg.get());
243 MSConstSeg.reset();
244 PP.RemovePragmaHandler(MSCodeSeg.get());
245 MSCodeSeg.reset();
246 PP.RemovePragmaHandler(MSSection.get());
247 MSSection.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000248 }
249
250 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
251 FPContractHandler.reset();
252}
253
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000254/// \brief Handle the annotation token produced for #pragma unused(...)
255///
256/// Each annot_pragma_unused is followed by the argument token so e.g.
257/// "#pragma unused(x,y)" becomes:
258/// annot_pragma_unused 'x' annot_pragma_unused 'y'
259void Parser::HandlePragmaUnused() {
260 assert(Tok.is(tok::annot_pragma_unused));
261 SourceLocation UnusedLoc = ConsumeToken();
262 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
263 ConsumeToken(); // The argument token.
264}
Eli Friedman570024a2010-08-05 06:57:20 +0000265
Rafael Espindola273fd772012-01-26 02:02:57 +0000266void Parser::HandlePragmaVisibility() {
267 assert(Tok.is(tok::annot_pragma_vis));
268 const IdentifierInfo *VisType =
269 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
270 SourceLocation VisLoc = ConsumeToken();
271 Actions.ActOnPragmaVisibility(VisType, VisLoc);
272}
273
Eli Friedmanec52f922012-02-23 23:47:16 +0000274struct PragmaPackInfo {
275 Sema::PragmaPackKind Kind;
276 IdentifierInfo *Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000277 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000278 SourceLocation LParenLoc;
279 SourceLocation RParenLoc;
280};
281
282void Parser::HandlePragmaPack() {
283 assert(Tok.is(tok::annot_pragma_pack));
284 PragmaPackInfo *Info =
285 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
286 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000287 ExprResult Alignment;
288 if (Info->Alignment.is(tok::numeric_constant)) {
289 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
290 if (Alignment.isInvalid())
291 return;
292 }
293 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanec52f922012-02-23 23:47:16 +0000294 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +0000295}
296
Eli Friedman68be1642012-10-04 02:36:51 +0000297void Parser::HandlePragmaMSStruct() {
298 assert(Tok.is(tok::annot_pragma_msstruct));
299 Sema::PragmaMSStructKind Kind =
300 static_cast<Sema::PragmaMSStructKind>(
301 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
302 Actions.ActOnPragmaMSStruct(Kind);
303 ConsumeToken(); // The annotation token.
304}
305
306void Parser::HandlePragmaAlign() {
307 assert(Tok.is(tok::annot_pragma_align));
308 Sema::PragmaOptionsAlignKind Kind =
309 static_cast<Sema::PragmaOptionsAlignKind>(
310 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
311 SourceLocation PragmaLoc = ConsumeToken();
312 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
313}
314
315void Parser::HandlePragmaWeak() {
316 assert(Tok.is(tok::annot_pragma_weak));
317 SourceLocation PragmaLoc = ConsumeToken();
318 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
319 Tok.getLocation());
320 ConsumeToken(); // The weak name.
321}
322
323void Parser::HandlePragmaWeakAlias() {
324 assert(Tok.is(tok::annot_pragma_weakalias));
325 SourceLocation PragmaLoc = ConsumeToken();
326 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
327 SourceLocation WeakNameLoc = Tok.getLocation();
328 ConsumeToken();
329 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
330 SourceLocation AliasNameLoc = Tok.getLocation();
331 ConsumeToken();
332 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
333 WeakNameLoc, AliasNameLoc);
334
335}
336
337void Parser::HandlePragmaRedefineExtname() {
338 assert(Tok.is(tok::annot_pragma_redefine_extname));
339 SourceLocation RedefLoc = ConsumeToken();
340 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
341 SourceLocation RedefNameLoc = Tok.getLocation();
342 ConsumeToken();
343 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
344 SourceLocation AliasNameLoc = Tok.getLocation();
345 ConsumeToken();
346 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
347 RedefNameLoc, AliasNameLoc);
348}
349
350void Parser::HandlePragmaFPContract() {
351 assert(Tok.is(tok::annot_pragma_fp_contract));
352 tok::OnOffSwitch OOS =
353 static_cast<tok::OnOffSwitch>(
354 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
355 Actions.ActOnPragmaFPContract(OOS);
356 ConsumeToken(); // The annotation token.
357}
358
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000359StmtResult Parser::HandlePragmaCaptured()
360{
361 assert(Tok.is(tok::annot_pragma_captured));
362 ConsumeToken();
363
364 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000365 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000366 return StmtError();
367 }
368
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000369 SourceLocation Loc = Tok.getLocation();
370
371 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000372 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
373 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000374
375 StmtResult R = ParseCompoundStatement();
376 CapturedRegionScope.Exit();
377
378 if (R.isInvalid()) {
379 Actions.ActOnCapturedRegionError();
380 return StmtError();
381 }
382
383 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000384}
385
Eli Friedman68be1642012-10-04 02:36:51 +0000386namespace {
387 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
388}
389
390void Parser::HandlePragmaOpenCLExtension() {
391 assert(Tok.is(tok::annot_pragma_opencl_extension));
392 OpenCLExtData data =
393 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
394 unsigned state = data.getInt();
395 IdentifierInfo *ename = data.getPointer();
396 SourceLocation NameLoc = Tok.getLocation();
397 ConsumeToken(); // The annotation token.
398
399 OpenCLOptions &f = Actions.getOpenCLOptions();
400 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
401 // overriding all previously issued extension directives, but only if the
402 // behavior is set to disable."
403 if (state == 0 && ename->isStr("all")) {
404#define OPENCLEXT(nm) f.nm = 0;
405#include "clang/Basic/OpenCLExtensions.def"
406 }
407#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
408#include "clang/Basic/OpenCLExtensions.def"
409 else {
410 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
411 return;
412 }
413}
414
David Majnemer4bb09802014-02-10 19:50:15 +0000415void Parser::HandlePragmaMSPointersToMembers() {
416 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000417 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
418 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000419 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
420 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
421 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
422}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000423
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000424void Parser::HandlePragmaMSVtorDisp() {
425 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
426 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
427 Sema::PragmaVtorDispKind Kind =
428 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
429 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
430 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
431 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
432}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000433
Warren Huntc3b18962014-04-08 22:30:47 +0000434void Parser::HandlePragmaMSPragma() {
435 assert(Tok.is(tok::annot_pragma_ms_pragma));
436 // Grab the tokens out of the annotation and enter them into the stream.
437 auto TheTokens = (std::pair<Token*, size_t> *)Tok.getAnnotationValue();
438 PP.EnterTokenStream(TheTokens->first, TheTokens->second, true, true);
439 SourceLocation PragmaLocation = ConsumeToken(); // The annotation token.
440 assert(Tok.isAnyIdentifier());
441 llvm::StringRef PragmaName = Tok.getIdentifierInfo()->getName();
442 PP.Lex(Tok); // pragma kind
443 // Figure out which #pragma we're dealing with. The switch has no default
444 // because lex shouldn't emit the annotation token for unrecognized pragmas.
445 typedef unsigned (Parser::*PragmaHandler)(llvm::StringRef, SourceLocation);
446 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
447 .Case("data_seg", &Parser::HandlePragmaMSSegment)
448 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
449 .Case("const_seg", &Parser::HandlePragmaMSSegment)
450 .Case("code_seg", &Parser::HandlePragmaMSSegment)
451 .Case("section", &Parser::HandlePragmaMSSection)
452 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
453 if (auto DiagID = (this->*Handler)(PragmaName, PragmaLocation)) {
454 PP.Diag(PragmaLocation, DiagID) << PragmaName;
455 while (Tok.isNot(tok::eof))
456 PP.Lex(Tok);
457 PP.Lex(Tok);
458 }
459}
460
461unsigned Parser::HandlePragmaMSSection(llvm::StringRef PragmaName,
462 SourceLocation PragmaLocation) {
463 if (Tok.isNot(tok::l_paren))
464 return diag::warn_pragma_expected_lparen;
465 PP.Lex(Tok); // (
466 // Parsing code for pragma section
467 if (Tok.isNot(tok::string_literal))
468 return diag::warn_pragma_expected_section_name;
469 StringLiteral *SegmentName =
470 cast<StringLiteral>(ParseStringLiteralExpression().get());
471 int SectionFlags = 0;
472 while (Tok.is(tok::comma)) {
473 PP.Lex(Tok); // ,
474 if (!Tok.isAnyIdentifier())
475 return diag::warn_pragma_expected_action_or_r_paren;
476 Sema::PragmaSectionFlag Flag =
477 llvm::StringSwitch<Sema::PragmaSectionFlag>(
478 Tok.getIdentifierInfo()->getName())
479 .Case("read", Sema::PSF_Read)
480 .Case("write", Sema::PSF_Write)
481 .Case("execute", Sema::PSF_Execute)
482 .Case("shared", Sema::PSF_Invalid)
483 .Case("nopage", Sema::PSF_Invalid)
484 .Case("nocache", Sema::PSF_Invalid)
485 .Case("discard", Sema::PSF_Invalid)
486 .Case("remove", Sema::PSF_Invalid)
487 .Default(Sema::PSF_None);
488 if (Flag == Sema::PSF_None || Flag == Sema::PSF_Invalid) {
489 PP.Diag(PragmaLocation, Flag == Sema::PSF_None ?
490 diag::warn_pragma_invalid_specific_action :
491 diag::warn_pragma_unsupported_action)
492 << PragmaName << Tok.getIdentifierInfo()->getName();
493 while (Tok.isNot(tok::eof))
494 PP.Lex(Tok);
495 PP.Lex(Tok);
496 return 0;
497 }
498 SectionFlags |= Flag;
499 PP.Lex(Tok); // Identifier
500 }
501 if (Tok.isNot(tok::r_paren))
502 return diag::warn_pragma_expected_rparen;
503 PP.Lex(Tok); // )
504 if (Tok.isNot(tok::eof))
505 return diag::warn_pragma_extra_tokens_at_eol;
506 PP.Lex(Tok); // eof
507 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
508 return 0;
509}
510
511unsigned Parser::HandlePragmaMSSegment(llvm::StringRef PragmaName,
512 SourceLocation PragmaLocation) {
513 if (Tok.isNot(tok::l_paren))
514 return diag::warn_pragma_expected_lparen;
515 PP.Lex(Tok); // (
516 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
517 llvm::StringRef SlotLabel;
518 if (Tok.isAnyIdentifier()) {
519 llvm::StringRef PushPop = Tok.getIdentifierInfo()->getName();
520 if (PushPop == "push")
521 Action = Sema::PSK_Push;
522 else if (PushPop == "pop")
523 Action = Sema::PSK_Pop;
524 else
525 return diag::warn_pragma_expected_section_push_pop_or_name;
526 if (Action != Sema::PSK_Reset) {
527 PP.Lex(Tok); // push | pop
528 if (Tok.is(tok::comma)) {
529 PP.Lex(Tok); // ,
530 // If we've got a comma, we either need a label or a string.
531 if (Tok.isAnyIdentifier()) {
532 SlotLabel = Tok.getIdentifierInfo()->getName();
533 PP.Lex(Tok); // identifier
534 if (Tok.is(tok::comma))
535 PP.Lex(Tok);
536 else if (Tok.isNot(tok::r_paren))
537 return diag::warn_pragma_expected_punc;
538 }
539 } else if (Tok.isNot(tok::r_paren))
540 return diag::warn_pragma_expected_punc;
541 }
542 }
543 // Grab the string literal for our section name.
544 StringLiteral *SegmentName = nullptr;
545 if (Tok.isNot(tok::r_paren)) {
546 if (Tok.isNot(tok::string_literal))
547 return Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
548 diag::warn_pragma_expected_section_name :
549 diag::warn_pragma_expected_section_label_or_name :
550 diag::warn_pragma_expected_section_push_pop_or_name;
551 SegmentName = cast<StringLiteral>(ParseStringLiteralExpression().get());
552 // Setting section "" has no effect
553 if (SegmentName->getLength())
554 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
555 }
556 if (Tok.isNot(tok::r_paren))
557 return diag::warn_pragma_expected_rparen;
558 PP.Lex(Tok); // )
559 if (Tok.isNot(tok::eof))
560 return diag::warn_pragma_extra_tokens_at_eol;
561 PP.Lex(Tok); // eof
562 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
563 SegmentName, PragmaName);
564 return 0;
565}
566
567unsigned Parser::HandlePragmaMSInitSeg(llvm::StringRef PragmaName,
568 SourceLocation PragmaLocation) {
569 return PP.getDiagnostics().getCustomDiagID(
570 DiagnosticsEngine::Error, "'#pragma %0' not implemented.");
571}
572
Eli Friedman570024a2010-08-05 06:57:20 +0000573// #pragma GCC visibility comes in two variants:
574// 'push' '(' [visibility] ')'
575// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000576void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
577 PragmaIntroducerKind Introducer,
578 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000579 SourceLocation VisLoc = VisTok.getLocation();
580
581 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000582 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000583
584 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
585
Eli Friedman570024a2010-08-05 06:57:20 +0000586 const IdentifierInfo *VisType;
587 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +0000588 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +0000589 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000590 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000591 if (Tok.isNot(tok::l_paren)) {
592 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
593 << "visibility";
594 return;
595 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000596 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000597 VisType = Tok.getIdentifierInfo();
598 if (!VisType) {
599 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
600 << "visibility";
601 return;
602 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000603 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000604 if (Tok.isNot(tok::r_paren)) {
605 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
606 << "visibility";
607 return;
608 }
609 } else {
610 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
611 << "visibility";
612 return;
613 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000614 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000615 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000616 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
617 << "visibility";
618 return;
619 }
620
Rafael Espindola273fd772012-01-26 02:02:57 +0000621 Token *Toks = new Token[1];
622 Toks[0].startToken();
623 Toks[0].setKind(tok::annot_pragma_vis);
624 Toks[0].setLocation(VisLoc);
625 Toks[0].setAnnotationValue(
626 const_cast<void*>(static_cast<const void*>(VisType)));
627 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
628 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000629}
630
Daniel Dunbar921b9682008-10-04 19:21:03 +0000631// #pragma pack(...) comes in the following delicious flavors:
632// pack '(' [integer] ')'
633// pack '(' 'show' ')'
634// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000635void PragmaPackHandler::HandlePragma(Preprocessor &PP,
636 PragmaIntroducerKind Introducer,
637 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000638 SourceLocation PackLoc = PackTok.getLocation();
639
640 Token Tok;
641 PP.Lex(Tok);
642 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000643 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000644 return;
645 }
646
John McCallfaf5fb42010-08-26 23:41:50 +0000647 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Craig Topper161e4db2014-05-21 06:02:52 +0000648 IdentifierInfo *Name = nullptr;
Eli Friedman68be1642012-10-04 02:36:51 +0000649 Token Alignment;
650 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000651 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000652 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000653 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000654 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000655
656 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000657
658 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
659 // the push/pop stack.
660 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000661 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000662 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000663 } else if (Tok.is(tok::identifier)) {
664 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000665 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000666 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000667 PP.Lex(Tok);
668 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000669 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000670 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000671 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000672 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000673 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000674 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000675 return;
Mike Stump11289f42009-09-09 15:08:12 +0000676 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000677 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000678
Daniel Dunbar921b9682008-10-04 19:21:03 +0000679 if (Tok.is(tok::comma)) {
680 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000681
Daniel Dunbar921b9682008-10-04 19:21:03 +0000682 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000683 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000684
685 PP.Lex(Tok);
686 } else if (Tok.is(tok::identifier)) {
687 Name = Tok.getIdentifierInfo();
688 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000689
Daniel Dunbar921b9682008-10-04 19:21:03 +0000690 if (Tok.is(tok::comma)) {
691 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000692
Daniel Dunbar921b9682008-10-04 19:21:03 +0000693 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000694 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000695 return;
696 }
Mike Stump11289f42009-09-09 15:08:12 +0000697
Eli Friedman68be1642012-10-04 02:36:51 +0000698 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000699
700 PP.Lex(Tok);
701 }
702 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000703 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000704 return;
705 }
706 }
707 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000708 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000709 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
710 // the push/pop stack.
711 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
712 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000713 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000714
715 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000716 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000717 return;
718 }
719
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000720 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000721 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000722 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000723 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
724 return;
725 }
726
Daniel Dunbar340cf242012-02-29 01:38:22 +0000727 PragmaPackInfo *Info =
728 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
729 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
730 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +0000731 Info->Kind = Kind;
732 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000733 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000734 Info->LParenLoc = LParenLoc;
735 Info->RParenLoc = RParenLoc;
736
Daniel Dunbar340cf242012-02-29 01:38:22 +0000737 Token *Toks =
738 (Token*) PP.getPreprocessorAllocator().Allocate(
739 sizeof(Token) * 1, llvm::alignOf<Token>());
740 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +0000741 Toks[0].startToken();
742 Toks[0].setKind(tok::annot_pragma_pack);
743 Toks[0].setLocation(PackLoc);
744 Toks[0].setAnnotationValue(static_cast<void*>(Info));
745 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +0000746 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000747}
748
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000749// #pragma ms_struct on
750// #pragma ms_struct off
751void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
752 PragmaIntroducerKind Introducer,
753 Token &MSStructTok) {
754 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
755
756 Token Tok;
757 PP.Lex(Tok);
758 if (Tok.isNot(tok::identifier)) {
759 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
760 return;
761 }
762 const IdentifierInfo *II = Tok.getIdentifierInfo();
763 if (II->isStr("on")) {
764 Kind = Sema::PMSST_ON;
765 PP.Lex(Tok);
766 }
767 else if (II->isStr("off") || II->isStr("reset"))
768 PP.Lex(Tok);
769 else {
770 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
771 return;
772 }
773
774 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +0000775 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
776 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000777 return;
778 }
Eli Friedman68be1642012-10-04 02:36:51 +0000779
780 Token *Toks =
781 (Token*) PP.getPreprocessorAllocator().Allocate(
782 sizeof(Token) * 1, llvm::alignOf<Token>());
783 new (Toks) Token();
784 Toks[0].startToken();
785 Toks[0].setKind(tok::annot_pragma_msstruct);
786 Toks[0].setLocation(MSStructTok.getLocation());
787 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
788 static_cast<uintptr_t>(Kind)));
789 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
790 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000791}
792
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000793// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
794// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +0000795static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000796 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000797 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000798
799 if (IsOptions) {
800 PP.Lex(Tok);
801 if (Tok.isNot(tok::identifier) ||
802 !Tok.getIdentifierInfo()->isStr("align")) {
803 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
804 return;
805 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000806 }
Daniel Dunbar663e8092010-05-27 18:42:09 +0000807
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000808 PP.Lex(Tok);
809 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000810 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
811 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000812 return;
813 }
814
815 PP.Lex(Tok);
816 if (Tok.isNot(tok::identifier)) {
817 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000818 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000819 return;
820 }
821
John McCallfaf5fb42010-08-26 23:41:50 +0000822 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000823 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +0000824 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +0000825 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +0000826 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +0000827 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +0000828 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +0000829 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000830 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +0000831 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000832 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +0000833 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000834 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +0000835 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000836 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000837 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
838 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000839 return;
840 }
841
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000842 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000843 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000844 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000845 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000846 return;
847 }
848
Eli Friedman68be1642012-10-04 02:36:51 +0000849 Token *Toks =
850 (Token*) PP.getPreprocessorAllocator().Allocate(
851 sizeof(Token) * 1, llvm::alignOf<Token>());
852 new (Toks) Token();
853 Toks[0].startToken();
854 Toks[0].setKind(tok::annot_pragma_align);
855 Toks[0].setLocation(FirstTok.getLocation());
856 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
857 static_cast<uintptr_t>(Kind)));
858 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
859 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000860}
861
Douglas Gregorc7d65762010-09-09 22:45:38 +0000862void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
863 PragmaIntroducerKind Introducer,
864 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000865 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000866}
867
Douglas Gregorc7d65762010-09-09 22:45:38 +0000868void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
869 PragmaIntroducerKind Introducer,
870 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000871 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000872}
873
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000874// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +0000875void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
876 PragmaIntroducerKind Introducer,
877 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000878 // FIXME: Should we be expanding macros here? My guess is no.
879 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000880
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000881 // Lex the left '('.
882 Token Tok;
883 PP.Lex(Tok);
884 if (Tok.isNot(tok::l_paren)) {
885 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
886 return;
887 }
Mike Stump11289f42009-09-09 15:08:12 +0000888
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000889 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000890 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000891 SourceLocation RParenLoc;
892 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +0000893
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000894 while (true) {
895 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000896
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000897 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +0000898 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000899 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000900 LexID = false;
901 continue;
902 }
903
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000904 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000905 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
906 return;
907 }
Mike Stump11289f42009-09-09 15:08:12 +0000908
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000909 // We are execting a ')' or a ','.
910 if (Tok.is(tok::comma)) {
911 LexID = true;
912 continue;
913 }
Mike Stump11289f42009-09-09 15:08:12 +0000914
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000915 if (Tok.is(tok::r_paren)) {
916 RParenLoc = Tok.getLocation();
917 break;
918 }
Mike Stump11289f42009-09-09 15:08:12 +0000919
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000920 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +0000921 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000922 return;
923 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000924
925 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000926 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000927 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
928 "unused";
929 return;
930 }
931
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000932 // Verify that we have a location for the right parenthesis.
933 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000934 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000935
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000936 // For each identifier token, insert into the token stream a
937 // annot_pragma_unused token followed by the identifier token.
938 // This allows us to cache a "#pragma unused" that occurs inside an inline
939 // C++ member function.
940
Daniel Dunbar340cf242012-02-29 01:38:22 +0000941 Token *Toks =
942 (Token*) PP.getPreprocessorAllocator().Allocate(
943 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000944 for (unsigned i=0; i != Identifiers.size(); i++) {
945 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
946 pragmaUnusedTok.startToken();
947 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
948 pragmaUnusedTok.setLocation(UnusedLoc);
949 idTok = Identifiers[i];
950 }
Daniel Dunbar340cf242012-02-29 01:38:22 +0000951 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
952 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000953}
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000954
955// #pragma weak identifier
956// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +0000957void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
958 PragmaIntroducerKind Introducer,
959 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000960 SourceLocation WeakLoc = WeakTok.getLocation();
961
962 Token Tok;
963 PP.Lex(Tok);
964 if (Tok.isNot(tok::identifier)) {
965 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
966 return;
967 }
968
Eli Friedman68be1642012-10-04 02:36:51 +0000969 Token WeakName = Tok;
970 bool HasAlias = false;
971 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000972
973 PP.Lex(Tok);
974 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000975 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000976 PP.Lex(Tok);
977 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +0000978 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000979 << "weak";
980 return;
981 }
Eli Friedman68be1642012-10-04 02:36:51 +0000982 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000983 PP.Lex(Tok);
984 }
985
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000986 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000987 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
988 return;
989 }
990
Eli Friedman68be1642012-10-04 02:36:51 +0000991 if (HasAlias) {
992 Token *Toks =
993 (Token*) PP.getPreprocessorAllocator().Allocate(
994 sizeof(Token) * 3, llvm::alignOf<Token>());
995 Token &pragmaUnusedTok = Toks[0];
996 pragmaUnusedTok.startToken();
997 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
998 pragmaUnusedTok.setLocation(WeakLoc);
999 Toks[1] = WeakName;
1000 Toks[2] = AliasName;
1001 PP.EnterTokenStream(Toks, 3,
1002 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001003 } else {
Eli Friedman68be1642012-10-04 02:36:51 +00001004 Token *Toks =
1005 (Token*) PP.getPreprocessorAllocator().Allocate(
1006 sizeof(Token) * 2, llvm::alignOf<Token>());
1007 Token &pragmaUnusedTok = Toks[0];
1008 pragmaUnusedTok.startToken();
1009 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
1010 pragmaUnusedTok.setLocation(WeakLoc);
1011 Toks[1] = WeakName;
1012 PP.EnterTokenStream(Toks, 2,
1013 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001014 }
1015}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001016
David Chisnall0867d9c2012-02-18 16:12:34 +00001017// #pragma redefine_extname identifier identifier
1018void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
1019 PragmaIntroducerKind Introducer,
1020 Token &RedefToken) {
1021 SourceLocation RedefLoc = RedefToken.getLocation();
1022
1023 Token Tok;
1024 PP.Lex(Tok);
1025 if (Tok.isNot(tok::identifier)) {
1026 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1027 "redefine_extname";
1028 return;
1029 }
1030
Eli Friedman68be1642012-10-04 02:36:51 +00001031 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001032 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00001033
David Chisnall0867d9c2012-02-18 16:12:34 +00001034 if (Tok.isNot(tok::identifier)) {
1035 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1036 << "redefine_extname";
1037 return;
1038 }
Eli Friedman68be1642012-10-04 02:36:51 +00001039
1040 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00001041 PP.Lex(Tok);
1042
1043 if (Tok.isNot(tok::eod)) {
1044 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1045 "redefine_extname";
1046 return;
1047 }
1048
Eli Friedman68be1642012-10-04 02:36:51 +00001049 Token *Toks =
1050 (Token*) PP.getPreprocessorAllocator().Allocate(
1051 sizeof(Token) * 3, llvm::alignOf<Token>());
1052 Token &pragmaRedefTok = Toks[0];
1053 pragmaRedefTok.startToken();
1054 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
1055 pragmaRedefTok.setLocation(RedefLoc);
1056 Toks[1] = RedefName;
1057 Toks[2] = AliasName;
1058 PP.EnterTokenStream(Toks, 3,
1059 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00001060}
1061
1062
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001063void
1064PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
1065 PragmaIntroducerKind Introducer,
1066 Token &Tok) {
1067 tok::OnOffSwitch OOS;
1068 if (PP.LexOnOffSwitch(OOS))
1069 return;
1070
Eli Friedman68be1642012-10-04 02:36:51 +00001071 Token *Toks =
1072 (Token*) PP.getPreprocessorAllocator().Allocate(
1073 sizeof(Token) * 1, llvm::alignOf<Token>());
1074 new (Toks) Token();
1075 Toks[0].startToken();
1076 Toks[0].setKind(tok::annot_pragma_fp_contract);
1077 Toks[0].setLocation(Tok.getLocation());
1078 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1079 static_cast<uintptr_t>(OOS)));
1080 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1081 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00001082}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001083
1084void
1085PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
1086 PragmaIntroducerKind Introducer,
1087 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00001088 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001089 if (Tok.isNot(tok::identifier)) {
1090 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
1091 "OPENCL";
1092 return;
1093 }
1094 IdentifierInfo *ename = Tok.getIdentifierInfo();
1095 SourceLocation NameLoc = Tok.getLocation();
1096
1097 PP.Lex(Tok);
1098 if (Tok.isNot(tok::colon)) {
1099 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
1100 return;
1101 }
1102
1103 PP.Lex(Tok);
1104 if (Tok.isNot(tok::identifier)) {
1105 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1106 return;
1107 }
1108 IdentifierInfo *op = Tok.getIdentifierInfo();
1109
1110 unsigned state;
1111 if (op->isStr("enable")) {
1112 state = 1;
1113 } else if (op->isStr("disable")) {
1114 state = 0;
1115 } else {
1116 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
1117 return;
1118 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001119 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001120
Eli Friedman68be1642012-10-04 02:36:51 +00001121 PP.Lex(Tok);
1122 if (Tok.isNot(tok::eod)) {
1123 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1124 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001125 return;
1126 }
Eli Friedman68be1642012-10-04 02:36:51 +00001127
1128 OpenCLExtData data(ename, state);
1129 Token *Toks =
1130 (Token*) PP.getPreprocessorAllocator().Allocate(
1131 sizeof(Token) * 1, llvm::alignOf<Token>());
1132 new (Toks) Token();
1133 Toks[0].startToken();
1134 Toks[0].setKind(tok::annot_pragma_opencl_extension);
1135 Toks[0].setLocation(NameLoc);
1136 Toks[0].setAnnotationValue(data.getOpaqueValue());
1137 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
1138 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00001139
1140 if (PP.getPPCallbacks())
1141 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
1142 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00001143}
1144
Alexey Bataeva769e072013-03-22 06:34:35 +00001145/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
1146///
1147void
1148PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
1149 PragmaIntroducerKind Introducer,
1150 Token &FirstTok) {
1151 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
1152 FirstTok.getLocation()) !=
1153 DiagnosticsEngine::Ignored) {
1154 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
1155 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
1156 diag::MAP_IGNORE,
1157 SourceLocation());
1158 }
1159 PP.DiscardUntilEndOfDirective();
1160}
1161
1162/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1163///
1164void
1165PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1166 PragmaIntroducerKind Introducer,
1167 Token &FirstTok) {
1168 SmallVector<Token, 16> Pragma;
1169 Token Tok;
1170 Tok.startToken();
1171 Tok.setKind(tok::annot_pragma_openmp);
1172 Tok.setLocation(FirstTok.getLocation());
1173
1174 while (Tok.isNot(tok::eod)) {
1175 Pragma.push_back(Tok);
1176 PP.Lex(Tok);
1177 }
1178 SourceLocation EodLoc = Tok.getLocation();
1179 Tok.startToken();
1180 Tok.setKind(tok::annot_pragma_openmp_end);
1181 Tok.setLocation(EodLoc);
1182 Pragma.push_back(Tok);
1183
1184 Token *Toks = new Token[Pragma.size()];
1185 std::copy(Pragma.begin(), Pragma.end(), Toks);
1186 PP.EnterTokenStream(Toks, Pragma.size(),
1187 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1188}
Reid Kleckner002562a2013-05-06 21:02:12 +00001189
David Majnemer4bb09802014-02-10 19:50:15 +00001190/// \brief Handle '#pragma pointers_to_members'
1191// The grammar for this pragma is as follows:
1192//
1193// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1194//
1195// #pragma pointers_to_members '(' 'best_case' ')'
1196// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1197// #pragma pointers_to_members '(' inheritance-model ')'
1198void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1199 PragmaIntroducerKind Introducer,
1200 Token &Tok) {
1201 SourceLocation PointersToMembersLoc = Tok.getLocation();
1202 PP.Lex(Tok);
1203 if (Tok.isNot(tok::l_paren)) {
1204 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1205 << "pointers_to_members";
1206 return;
1207 }
1208 PP.Lex(Tok);
1209 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1210 if (!Arg) {
1211 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1212 << "pointers_to_members";
1213 return;
1214 }
1215 PP.Lex(Tok);
1216
David Majnemer86c318f2014-02-11 21:05:00 +00001217 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001218 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001219 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001220 } else {
1221 if (Arg->isStr("full_generality")) {
1222 if (Tok.is(tok::comma)) {
1223 PP.Lex(Tok);
1224
1225 Arg = Tok.getIdentifierInfo();
1226 if (!Arg) {
1227 PP.Diag(Tok.getLocation(),
1228 diag::err_pragma_pointers_to_members_unknown_kind)
1229 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1230 return;
1231 }
1232 PP.Lex(Tok);
1233 } else if (Tok.is(tok::r_paren)) {
1234 // #pragma pointers_to_members(full_generality) implicitly specifies
1235 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00001236 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00001237 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001238 } else {
1239 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1240 << "full_generality";
1241 return;
1242 }
1243 }
1244
1245 if (Arg) {
1246 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001247 RepresentationMethod =
1248 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001249 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001250 RepresentationMethod =
1251 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001252 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001253 RepresentationMethod =
1254 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001255 } else {
1256 PP.Diag(Tok.getLocation(),
1257 diag::err_pragma_pointers_to_members_unknown_kind)
1258 << Arg << /*HasPointerDeclaration*/ 1;
1259 return;
1260 }
1261 }
1262 }
1263
1264 if (Tok.isNot(tok::r_paren)) {
1265 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1266 << (Arg ? Arg->getName() : "full_generality");
1267 return;
1268 }
1269
1270 PP.Lex(Tok);
1271 if (Tok.isNot(tok::eod)) {
1272 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1273 << "pointers_to_members";
1274 return;
1275 }
1276
1277 Token AnnotTok;
1278 AnnotTok.startToken();
1279 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1280 AnnotTok.setLocation(PointersToMembersLoc);
1281 AnnotTok.setAnnotationValue(
1282 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1283 PP.EnterToken(AnnotTok);
1284}
1285
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001286/// \brief Handle '#pragma vtordisp'
1287// The grammar for this pragma is as follows:
1288//
1289// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1290//
1291// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1292// #pragma vtordisp '(' 'pop' ')'
1293// #pragma vtordisp '(' ')'
1294void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1295 PragmaIntroducerKind Introducer,
1296 Token &Tok) {
1297 SourceLocation VtorDispLoc = Tok.getLocation();
1298 PP.Lex(Tok);
1299 if (Tok.isNot(tok::l_paren)) {
1300 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1301 return;
1302 }
1303 PP.Lex(Tok);
1304
1305 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1306 const IdentifierInfo *II = Tok.getIdentifierInfo();
1307 if (II) {
1308 if (II->isStr("push")) {
1309 // #pragma vtordisp(push, mode)
1310 PP.Lex(Tok);
1311 if (Tok.isNot(tok::comma)) {
1312 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1313 return;
1314 }
1315 PP.Lex(Tok);
1316 Kind = Sema::PVDK_Push;
1317 // not push, could be on/off
1318 } else if (II->isStr("pop")) {
1319 // #pragma vtordisp(pop)
1320 PP.Lex(Tok);
1321 Kind = Sema::PVDK_Pop;
1322 }
1323 // not push or pop, could be on/off
1324 } else {
1325 if (Tok.is(tok::r_paren)) {
1326 // #pragma vtordisp()
1327 Kind = Sema::PVDK_Reset;
1328 }
1329 }
1330
1331
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001332 uint64_t Value = 0;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001333 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1334 const IdentifierInfo *II = Tok.getIdentifierInfo();
1335 if (II && II->isStr("off")) {
1336 PP.Lex(Tok);
1337 Value = 0;
1338 } else if (II && II->isStr("on")) {
1339 PP.Lex(Tok);
1340 Value = 1;
1341 } else if (Tok.is(tok::numeric_constant) &&
1342 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1343 if (Value > 2) {
1344 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1345 << 0 << 2 << "vtordisp";
1346 return;
1347 }
1348 } else {
1349 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1350 << "vtordisp";
1351 return;
1352 }
1353 }
1354
1355 // Finish the pragma: ')' $
1356 if (Tok.isNot(tok::r_paren)) {
1357 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1358 return;
1359 }
1360 PP.Lex(Tok);
1361 if (Tok.isNot(tok::eod)) {
1362 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1363 << "vtordisp";
1364 return;
1365 }
1366
1367 // Enter the annotation.
1368 Token AnnotTok;
1369 AnnotTok.startToken();
1370 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1371 AnnotTok.setLocation(VtorDispLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001372 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1373 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001374 PP.EnterToken(AnnotTok);
1375}
1376
Warren Huntc3b18962014-04-08 22:30:47 +00001377/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting
1378/// an annotation token.
1379void PragmaMSPragma::HandlePragma(Preprocessor &PP,
1380 PragmaIntroducerKind Introducer,
1381 Token &Tok) {
1382 Token EoF, AnnotTok;
1383 EoF.startToken();
1384 EoF.setKind(tok::eof);
1385 AnnotTok.startToken();
1386 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
1387 AnnotTok.setLocation(Tok.getLocation());
1388 SmallVector<Token, 8> TokenVector;
1389 // Suck up all of the tokens before the eod.
1390 for (; Tok.isNot(tok::eod); PP.Lex(Tok))
1391 TokenVector.push_back(Tok);
1392 // Add a sentinal EoF token to the end of the list.
1393 TokenVector.push_back(EoF);
1394 // We must allocate this array with new because EnterTokenStream is going to
1395 // delete it later.
1396 Token *TokenArray = new Token[TokenVector.size()];
1397 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray);
1398 auto Value = new (PP.getPreprocessorAllocator())
1399 std::pair<Token*, size_t>(std::make_pair(TokenArray, TokenVector.size()));
1400 AnnotTok.setAnnotationValue(Value);
1401 PP.EnterToken(AnnotTok);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001402}
1403
Aaron Ballman5d041be2013-06-04 02:07:14 +00001404/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1405///
1406/// The syntax is:
1407/// \code
1408/// #pragma detect_mismatch("name", "value")
1409/// \endcode
1410/// Where 'name' and 'value' are quoted strings. The values are embedded in
1411/// the object file and passed along to the linker. If the linker detects a
1412/// mismatch in the object file's values for the given name, a LNK2038 error
1413/// is emitted. See MSDN for more details.
1414void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1415 PragmaIntroducerKind Introducer,
1416 Token &Tok) {
1417 SourceLocation CommentLoc = Tok.getLocation();
1418 PP.Lex(Tok);
1419 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001420 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001421 return;
1422 }
1423
1424 // Read the name to embed, which must be a string literal.
1425 std::string NameString;
1426 if (!PP.LexStringLiteral(Tok, NameString,
1427 "pragma detect_mismatch",
1428 /*MacroExpansion=*/true))
1429 return;
1430
1431 // Read the comma followed by a second string literal.
1432 std::string ValueString;
1433 if (Tok.isNot(tok::comma)) {
1434 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1435 return;
1436 }
1437
1438 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1439 /*MacroExpansion=*/true))
1440 return;
1441
1442 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001443 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001444 return;
1445 }
1446 PP.Lex(Tok); // Eat the r_paren.
1447
1448 if (Tok.isNot(tok::eod)) {
1449 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1450 return;
1451 }
1452
Reid Kleckner71966c92014-02-20 23:37:45 +00001453 // If the pragma is lexically sound, notify any interested PPCallbacks.
1454 if (PP.getPPCallbacks())
1455 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1456 ValueString);
1457
Aaron Ballman5d041be2013-06-04 02:07:14 +00001458 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1459}
1460
Reid Kleckner002562a2013-05-06 21:02:12 +00001461/// \brief Handle the microsoft \#pragma comment extension.
1462///
1463/// The syntax is:
1464/// \code
1465/// #pragma comment(linker, "foo")
1466/// \endcode
1467/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1468/// "foo" is a string, which is fully macro expanded, and permits string
1469/// concatenation, embedded escape characters etc. See MSDN for more details.
1470void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1471 PragmaIntroducerKind Introducer,
1472 Token &Tok) {
1473 SourceLocation CommentLoc = Tok.getLocation();
1474 PP.Lex(Tok);
1475 if (Tok.isNot(tok::l_paren)) {
1476 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1477 return;
1478 }
1479
1480 // Read the identifier.
1481 PP.Lex(Tok);
1482 if (Tok.isNot(tok::identifier)) {
1483 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1484 return;
1485 }
1486
1487 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001488 IdentifierInfo *II = Tok.getIdentifierInfo();
1489 Sema::PragmaMSCommentKind Kind =
1490 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1491 .Case("linker", Sema::PCK_Linker)
1492 .Case("lib", Sema::PCK_Lib)
1493 .Case("compiler", Sema::PCK_Compiler)
1494 .Case("exestr", Sema::PCK_ExeStr)
1495 .Case("user", Sema::PCK_User)
1496 .Default(Sema::PCK_Unknown);
1497 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001498 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1499 return;
1500 }
1501
1502 // Read the optional string if present.
1503 PP.Lex(Tok);
1504 std::string ArgumentString;
1505 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1506 "pragma comment",
1507 /*MacroExpansion=*/true))
1508 return;
1509
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001510 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001511 // FIXME: If the kind is "compiler" warn if the string is present (it is
1512 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001513 // The MSDN docs say that "lib" and "linker" require a string and have a short
1514 // whitelist of linker options they support, but in practice MSVC doesn't
1515 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001516
1517 if (Tok.isNot(tok::r_paren)) {
1518 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1519 return;
1520 }
1521 PP.Lex(Tok); // eat the r_paren.
1522
1523 if (Tok.isNot(tok::eod)) {
1524 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1525 return;
1526 }
1527
Reid Kleckner71966c92014-02-20 23:37:45 +00001528 // If the pragma is lexically sound, notify any interested PPCallbacks.
1529 if (PP.getPPCallbacks())
1530 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1531
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001532 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001533}