blob: 33c1f0b628fb47b23e65589a7a41ef61644e8209 [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
Chandler Carruth3a022472012-12-04 09:13:33 +000014#include "clang/Lex/Preprocessor.h"
Chris Lattner60f36222009-01-29 05:15:15 +000015#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenekfd14fad2009-03-23 22:28:25 +000016#include "clang/Parse/Parser.h"
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +000017#include "clang/Sema/Scope.h"
Reid Kleckner002562a2013-05-06 21:02:12 +000018#include "llvm/ADT/StringSwitch.h"
Daniel Dunbar921b9682008-10-04 19:21:03 +000019using namespace clang;
20
Reid Kleckner5b086462014-02-20 22:52:09 +000021namespace {
22
23struct PragmaAlignHandler : public PragmaHandler {
24 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Craig Topper2b07f022014-03-12 05:09:18 +000025 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
26 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000027};
28
29struct PragmaGCCVisibilityHandler : public PragmaHandler {
30 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Craig Topper2b07f022014-03-12 05:09:18 +000031 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
32 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000033};
34
35struct PragmaOptionsHandler : public PragmaHandler {
36 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Craig Topper2b07f022014-03-12 05:09:18 +000037 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
38 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000039};
40
41struct PragmaPackHandler : public PragmaHandler {
42 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Craig Topper2b07f022014-03-12 05:09:18 +000043 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
44 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000045};
46
47struct PragmaMSStructHandler : public PragmaHandler {
48 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Craig Topper2b07f022014-03-12 05:09:18 +000049 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
50 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000051};
52
53struct PragmaUnusedHandler : public PragmaHandler {
54 PragmaUnusedHandler() : PragmaHandler("unused") {}
Craig Topper2b07f022014-03-12 05:09:18 +000055 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
56 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000057};
58
59struct PragmaWeakHandler : public PragmaHandler {
60 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Craig Topper2b07f022014-03-12 05:09:18 +000061 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
62 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000063};
64
65struct PragmaRedefineExtnameHandler : public PragmaHandler {
66 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Craig Topper2b07f022014-03-12 05:09:18 +000067 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
68 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000069};
70
71struct PragmaOpenCLExtensionHandler : public PragmaHandler {
72 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Craig Topper2b07f022014-03-12 05:09:18 +000073 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
74 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000075};
76
77
78struct PragmaFPContractHandler : public PragmaHandler {
79 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Craig Topper2b07f022014-03-12 05:09:18 +000080 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
81 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000082};
83
84struct PragmaNoOpenMPHandler : public PragmaHandler {
85 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000086 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
87 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000088};
89
90struct PragmaOpenMPHandler : public PragmaHandler {
91 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Craig Topper2b07f022014-03-12 05:09:18 +000092 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
93 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000094};
95
96/// PragmaCommentHandler - "\#pragma comment ...".
97struct PragmaCommentHandler : public PragmaHandler {
98 PragmaCommentHandler(Sema &Actions)
99 : PragmaHandler("comment"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000100 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
101 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000102private:
103 Sema &Actions;
104};
105
106struct PragmaDetectMismatchHandler : public PragmaHandler {
107 PragmaDetectMismatchHandler(Sema &Actions)
108 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Craig Topper2b07f022014-03-12 05:09:18 +0000109 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
110 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000111private:
112 Sema &Actions;
113};
114
115struct PragmaMSPointersToMembers : public PragmaHandler {
116 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000117 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
118 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000119};
120
121struct PragmaMSVtorDisp : public PragmaHandler {
122 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Craig Topper2b07f022014-03-12 05:09:18 +0000123 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
124 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000125};
126
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000127struct PragmaMSInitSeg : public PragmaHandler {
128 explicit PragmaMSInitSeg() : PragmaHandler("init_seg") {}
129 void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
130 Token &FirstToken) override;
131};
132
Reid Kleckner5b086462014-02-20 22:52:09 +0000133} // end namespace
134
135void Parser::initializePragmaHandlers() {
136 AlignHandler.reset(new PragmaAlignHandler());
137 PP.AddPragmaHandler(AlignHandler.get());
138
139 GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler());
140 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
141
142 OptionsHandler.reset(new PragmaOptionsHandler());
143 PP.AddPragmaHandler(OptionsHandler.get());
144
145 PackHandler.reset(new PragmaPackHandler());
146 PP.AddPragmaHandler(PackHandler.get());
147
148 MSStructHandler.reset(new PragmaMSStructHandler());
149 PP.AddPragmaHandler(MSStructHandler.get());
150
151 UnusedHandler.reset(new PragmaUnusedHandler());
152 PP.AddPragmaHandler(UnusedHandler.get());
153
154 WeakHandler.reset(new PragmaWeakHandler());
155 PP.AddPragmaHandler(WeakHandler.get());
156
157 RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler());
158 PP.AddPragmaHandler(RedefineExtnameHandler.get());
159
160 FPContractHandler.reset(new PragmaFPContractHandler());
161 PP.AddPragmaHandler("STDC", FPContractHandler.get());
162
163 if (getLangOpts().OpenCL) {
164 OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler());
165 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
166
167 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
168 }
169 if (getLangOpts().OpenMP)
170 OpenMPHandler.reset(new PragmaOpenMPHandler());
171 else
172 OpenMPHandler.reset(new PragmaNoOpenMPHandler());
173 PP.AddPragmaHandler(OpenMPHandler.get());
174
175 if (getLangOpts().MicrosoftExt) {
176 MSCommentHandler.reset(new PragmaCommentHandler(Actions));
177 PP.AddPragmaHandler(MSCommentHandler.get());
178 MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(Actions));
179 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
180 MSPointersToMembers.reset(new PragmaMSPointersToMembers());
181 PP.AddPragmaHandler(MSPointersToMembers.get());
182 MSVtorDisp.reset(new PragmaMSVtorDisp());
183 PP.AddPragmaHandler(MSVtorDisp.get());
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000184 MSInitSeg.reset(new PragmaMSInitSeg());
185 PP.AddPragmaHandler(MSInitSeg.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000186 }
187}
188
189void Parser::resetPragmaHandlers() {
190 // Remove the pragma handlers we installed.
191 PP.RemovePragmaHandler(AlignHandler.get());
192 AlignHandler.reset();
193 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
194 GCCVisibilityHandler.reset();
195 PP.RemovePragmaHandler(OptionsHandler.get());
196 OptionsHandler.reset();
197 PP.RemovePragmaHandler(PackHandler.get());
198 PackHandler.reset();
199 PP.RemovePragmaHandler(MSStructHandler.get());
200 MSStructHandler.reset();
201 PP.RemovePragmaHandler(UnusedHandler.get());
202 UnusedHandler.reset();
203 PP.RemovePragmaHandler(WeakHandler.get());
204 WeakHandler.reset();
205 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
206 RedefineExtnameHandler.reset();
207
208 if (getLangOpts().OpenCL) {
209 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
210 OpenCLExtensionHandler.reset();
211 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
212 }
213 PP.RemovePragmaHandler(OpenMPHandler.get());
214 OpenMPHandler.reset();
215
216 if (getLangOpts().MicrosoftExt) {
217 PP.RemovePragmaHandler(MSCommentHandler.get());
218 MSCommentHandler.reset();
219 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
220 MSDetectMismatchHandler.reset();
221 PP.RemovePragmaHandler(MSPointersToMembers.get());
222 MSPointersToMembers.reset();
223 PP.RemovePragmaHandler(MSVtorDisp.get());
224 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000225 PP.RemovePragmaHandler(MSInitSeg.get());
226 MSInitSeg.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000227 }
228
229 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
230 FPContractHandler.reset();
231}
232
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000233/// \brief Handle the annotation token produced for #pragma unused(...)
234///
235/// Each annot_pragma_unused is followed by the argument token so e.g.
236/// "#pragma unused(x,y)" becomes:
237/// annot_pragma_unused 'x' annot_pragma_unused 'y'
238void Parser::HandlePragmaUnused() {
239 assert(Tok.is(tok::annot_pragma_unused));
240 SourceLocation UnusedLoc = ConsumeToken();
241 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
242 ConsumeToken(); // The argument token.
243}
Eli Friedman570024a2010-08-05 06:57:20 +0000244
Rafael Espindola273fd772012-01-26 02:02:57 +0000245void Parser::HandlePragmaVisibility() {
246 assert(Tok.is(tok::annot_pragma_vis));
247 const IdentifierInfo *VisType =
248 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
249 SourceLocation VisLoc = ConsumeToken();
250 Actions.ActOnPragmaVisibility(VisType, VisLoc);
251}
252
Eli Friedmanec52f922012-02-23 23:47:16 +0000253struct PragmaPackInfo {
254 Sema::PragmaPackKind Kind;
255 IdentifierInfo *Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000256 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000257 SourceLocation LParenLoc;
258 SourceLocation RParenLoc;
259};
260
261void Parser::HandlePragmaPack() {
262 assert(Tok.is(tok::annot_pragma_pack));
263 PragmaPackInfo *Info =
264 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
265 SourceLocation PragmaLoc = ConsumeToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000266 ExprResult Alignment;
267 if (Info->Alignment.is(tok::numeric_constant)) {
268 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
269 if (Alignment.isInvalid())
270 return;
271 }
272 Actions.ActOnPragmaPack(Info->Kind, Info->Name, Alignment.get(), PragmaLoc,
Eli Friedmanec52f922012-02-23 23:47:16 +0000273 Info->LParenLoc, Info->RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +0000274}
275
Eli Friedman68be1642012-10-04 02:36:51 +0000276void Parser::HandlePragmaMSStruct() {
277 assert(Tok.is(tok::annot_pragma_msstruct));
278 Sema::PragmaMSStructKind Kind =
279 static_cast<Sema::PragmaMSStructKind>(
280 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
281 Actions.ActOnPragmaMSStruct(Kind);
282 ConsumeToken(); // The annotation token.
283}
284
285void Parser::HandlePragmaAlign() {
286 assert(Tok.is(tok::annot_pragma_align));
287 Sema::PragmaOptionsAlignKind Kind =
288 static_cast<Sema::PragmaOptionsAlignKind>(
289 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
290 SourceLocation PragmaLoc = ConsumeToken();
291 Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc);
292}
293
294void Parser::HandlePragmaWeak() {
295 assert(Tok.is(tok::annot_pragma_weak));
296 SourceLocation PragmaLoc = ConsumeToken();
297 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
298 Tok.getLocation());
299 ConsumeToken(); // The weak name.
300}
301
302void Parser::HandlePragmaWeakAlias() {
303 assert(Tok.is(tok::annot_pragma_weakalias));
304 SourceLocation PragmaLoc = ConsumeToken();
305 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
306 SourceLocation WeakNameLoc = Tok.getLocation();
307 ConsumeToken();
308 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
309 SourceLocation AliasNameLoc = Tok.getLocation();
310 ConsumeToken();
311 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
312 WeakNameLoc, AliasNameLoc);
313
314}
315
316void Parser::HandlePragmaRedefineExtname() {
317 assert(Tok.is(tok::annot_pragma_redefine_extname));
318 SourceLocation RedefLoc = ConsumeToken();
319 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
320 SourceLocation RedefNameLoc = Tok.getLocation();
321 ConsumeToken();
322 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
323 SourceLocation AliasNameLoc = Tok.getLocation();
324 ConsumeToken();
325 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
326 RedefNameLoc, AliasNameLoc);
327}
328
329void Parser::HandlePragmaFPContract() {
330 assert(Tok.is(tok::annot_pragma_fp_contract));
331 tok::OnOffSwitch OOS =
332 static_cast<tok::OnOffSwitch>(
333 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
334 Actions.ActOnPragmaFPContract(OOS);
335 ConsumeToken(); // The annotation token.
336}
337
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000338StmtResult Parser::HandlePragmaCaptured()
339{
340 assert(Tok.is(tok::annot_pragma_captured));
341 ConsumeToken();
342
343 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000344 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000345 return StmtError();
346 }
347
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000348 SourceLocation Loc = Tok.getLocation();
349
350 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000351 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
352 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000353
354 StmtResult R = ParseCompoundStatement();
355 CapturedRegionScope.Exit();
356
357 if (R.isInvalid()) {
358 Actions.ActOnCapturedRegionError();
359 return StmtError();
360 }
361
362 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000363}
364
Eli Friedman68be1642012-10-04 02:36:51 +0000365namespace {
366 typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
367}
368
369void Parser::HandlePragmaOpenCLExtension() {
370 assert(Tok.is(tok::annot_pragma_opencl_extension));
371 OpenCLExtData data =
372 OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
373 unsigned state = data.getInt();
374 IdentifierInfo *ename = data.getPointer();
375 SourceLocation NameLoc = Tok.getLocation();
376 ConsumeToken(); // The annotation token.
377
378 OpenCLOptions &f = Actions.getOpenCLOptions();
379 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
380 // overriding all previously issued extension directives, but only if the
381 // behavior is set to disable."
382 if (state == 0 && ename->isStr("all")) {
383#define OPENCLEXT(nm) f.nm = 0;
384#include "clang/Basic/OpenCLExtensions.def"
385 }
386#define OPENCLEXT(nm) else if (ename->isStr(#nm)) { f.nm = state; }
387#include "clang/Basic/OpenCLExtensions.def"
388 else {
389 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
390 return;
391 }
392}
393
David Majnemer4bb09802014-02-10 19:50:15 +0000394void Parser::HandlePragmaMSPointersToMembers() {
395 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000396 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
397 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000398 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
399 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
400 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
401}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000402
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000403void Parser::HandlePragmaMSVtorDisp() {
404 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
405 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
406 Sema::PragmaVtorDispKind Kind =
407 static_cast<Sema::PragmaVtorDispKind>((Value >> 16) & 0xFFFF);
408 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
409 SourceLocation PragmaLoc = ConsumeToken(); // The annotation token.
410 Actions.ActOnPragmaMSVtorDisp(Kind, PragmaLoc, Mode);
411}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000412
Eli Friedman570024a2010-08-05 06:57:20 +0000413// #pragma GCC visibility comes in two variants:
414// 'push' '(' [visibility] ')'
415// 'pop'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000416void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
417 PragmaIntroducerKind Introducer,
418 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +0000419 SourceLocation VisLoc = VisTok.getLocation();
420
421 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000422 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000423
424 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
425
Eli Friedman570024a2010-08-05 06:57:20 +0000426 const IdentifierInfo *VisType;
427 if (PushPop && PushPop->isStr("pop")) {
Eli Friedman570024a2010-08-05 06:57:20 +0000428 VisType = 0;
429 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000430 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000431 if (Tok.isNot(tok::l_paren)) {
432 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
433 << "visibility";
434 return;
435 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000436 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000437 VisType = Tok.getIdentifierInfo();
438 if (!VisType) {
439 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
440 << "visibility";
441 return;
442 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000443 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +0000444 if (Tok.isNot(tok::r_paren)) {
445 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
446 << "visibility";
447 return;
448 }
449 } else {
450 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
451 << "visibility";
452 return;
453 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +0000454 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000455 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +0000456 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
457 << "visibility";
458 return;
459 }
460
Rafael Espindola273fd772012-01-26 02:02:57 +0000461 Token *Toks = new Token[1];
462 Toks[0].startToken();
463 Toks[0].setKind(tok::annot_pragma_vis);
464 Toks[0].setLocation(VisLoc);
465 Toks[0].setAnnotationValue(
466 const_cast<void*>(static_cast<const void*>(VisType)));
467 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
468 /*OwnsTokens=*/true);
Eli Friedman570024a2010-08-05 06:57:20 +0000469}
470
Daniel Dunbar921b9682008-10-04 19:21:03 +0000471// #pragma pack(...) comes in the following delicious flavors:
472// pack '(' [integer] ')'
473// pack '(' 'show' ')'
474// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Douglas Gregorc7d65762010-09-09 22:45:38 +0000475void PragmaPackHandler::HandlePragma(Preprocessor &PP,
476 PragmaIntroducerKind Introducer,
477 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +0000478 SourceLocation PackLoc = PackTok.getLocation();
479
480 Token Tok;
481 PP.Lex(Tok);
482 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000483 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000484 return;
485 }
486
John McCallfaf5fb42010-08-26 23:41:50 +0000487 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000488 IdentifierInfo *Name = 0;
Eli Friedman68be1642012-10-04 02:36:51 +0000489 Token Alignment;
490 Alignment.startToken();
Daniel Dunbar921b9682008-10-04 19:21:03 +0000491 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000492 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000493 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000494 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000495
496 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +0000497
498 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
499 // the push/pop stack.
500 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
David Blaikiebbafb8a2012-03-11 07:00:24 +0000501 if (PP.getLangOpts().ApplePragmaPack)
Eli Friedman055c9702011-11-02 01:53:16 +0000502 Kind = Sema::PPK_Push;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000503 } else if (Tok.is(tok::identifier)) {
504 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +0000505 if (II->isStr("show")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000506 Kind = Sema::PPK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000507 PP.Lex(Tok);
508 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000509 if (II->isStr("push")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000510 Kind = Sema::PPK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +0000511 } else if (II->isStr("pop")) {
John McCallfaf5fb42010-08-26 23:41:50 +0000512 Kind = Sema::PPK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000513 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000514 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000515 return;
Mike Stump11289f42009-09-09 15:08:12 +0000516 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000517 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000518
Daniel Dunbar921b9682008-10-04 19:21:03 +0000519 if (Tok.is(tok::comma)) {
520 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000521
Daniel Dunbar921b9682008-10-04 19:21:03 +0000522 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000523 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000524
525 PP.Lex(Tok);
526 } else if (Tok.is(tok::identifier)) {
527 Name = Tok.getIdentifierInfo();
528 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000529
Daniel Dunbar921b9682008-10-04 19:21:03 +0000530 if (Tok.is(tok::comma)) {
531 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000532
Daniel Dunbar921b9682008-10-04 19:21:03 +0000533 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000534 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000535 return;
536 }
Mike Stump11289f42009-09-09 15:08:12 +0000537
Eli Friedman68be1642012-10-04 02:36:51 +0000538 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +0000539
540 PP.Lex(Tok);
541 }
542 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +0000543 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000544 return;
545 }
546 }
547 }
David Blaikiebbafb8a2012-03-11 07:00:24 +0000548 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +0000549 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
550 // the push/pop stack.
551 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
552 Kind = Sema::PPK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +0000553 }
Daniel Dunbar921b9682008-10-04 19:21:03 +0000554
555 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000556 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +0000557 return;
558 }
559
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000560 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000561 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000562 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000563 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
564 return;
565 }
566
Daniel Dunbar340cf242012-02-29 01:38:22 +0000567 PragmaPackInfo *Info =
568 (PragmaPackInfo*) PP.getPreprocessorAllocator().Allocate(
569 sizeof(PragmaPackInfo), llvm::alignOf<PragmaPackInfo>());
570 new (Info) PragmaPackInfo();
Eli Friedmanec52f922012-02-23 23:47:16 +0000571 Info->Kind = Kind;
572 Info->Name = Name;
Eli Friedman68be1642012-10-04 02:36:51 +0000573 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000574 Info->LParenLoc = LParenLoc;
575 Info->RParenLoc = RParenLoc;
576
Daniel Dunbar340cf242012-02-29 01:38:22 +0000577 Token *Toks =
578 (Token*) PP.getPreprocessorAllocator().Allocate(
579 sizeof(Token) * 1, llvm::alignOf<Token>());
580 new (Toks) Token();
Eli Friedmanec52f922012-02-23 23:47:16 +0000581 Toks[0].startToken();
582 Toks[0].setKind(tok::annot_pragma_pack);
583 Toks[0].setLocation(PackLoc);
584 Toks[0].setAnnotationValue(static_cast<void*>(Info));
585 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
Daniel Dunbar340cf242012-02-29 01:38:22 +0000586 /*OwnsTokens=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +0000587}
588
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000589// #pragma ms_struct on
590// #pragma ms_struct off
591void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
592 PragmaIntroducerKind Introducer,
593 Token &MSStructTok) {
594 Sema::PragmaMSStructKind Kind = Sema::PMSST_OFF;
595
596 Token Tok;
597 PP.Lex(Tok);
598 if (Tok.isNot(tok::identifier)) {
599 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
600 return;
601 }
602 const IdentifierInfo *II = Tok.getIdentifierInfo();
603 if (II->isStr("on")) {
604 Kind = Sema::PMSST_ON;
605 PP.Lex(Tok);
606 }
607 else if (II->isStr("off") || II->isStr("reset"))
608 PP.Lex(Tok);
609 else {
610 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
611 return;
612 }
613
614 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +0000615 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
616 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000617 return;
618 }
Eli Friedman68be1642012-10-04 02:36:51 +0000619
620 Token *Toks =
621 (Token*) PP.getPreprocessorAllocator().Allocate(
622 sizeof(Token) * 1, llvm::alignOf<Token>());
623 new (Toks) Token();
624 Toks[0].startToken();
625 Toks[0].setKind(tok::annot_pragma_msstruct);
626 Toks[0].setLocation(MSStructTok.getLocation());
627 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
628 static_cast<uintptr_t>(Kind)));
629 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
630 /*OwnsTokens=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +0000631}
632
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000633// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
634// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +0000635static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000636 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000637 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000638
639 if (IsOptions) {
640 PP.Lex(Tok);
641 if (Tok.isNot(tok::identifier) ||
642 !Tok.getIdentifierInfo()->isStr("align")) {
643 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
644 return;
645 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000646 }
Daniel Dunbar663e8092010-05-27 18:42:09 +0000647
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000648 PP.Lex(Tok);
649 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000650 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
651 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000652 return;
653 }
654
655 PP.Lex(Tok);
656 if (Tok.isNot(tok::identifier)) {
657 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000658 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000659 return;
660 }
661
John McCallfaf5fb42010-08-26 23:41:50 +0000662 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000663 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +0000664 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +0000665 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +0000666 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +0000667 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +0000668 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +0000669 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000670 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +0000671 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000672 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +0000673 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000674 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +0000675 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000676 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000677 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
678 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000679 return;
680 }
681
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000682 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000683 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000684 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000685 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000686 return;
687 }
688
Eli Friedman68be1642012-10-04 02:36:51 +0000689 Token *Toks =
690 (Token*) PP.getPreprocessorAllocator().Allocate(
691 sizeof(Token) * 1, llvm::alignOf<Token>());
692 new (Toks) Token();
693 Toks[0].startToken();
694 Toks[0].setKind(tok::annot_pragma_align);
695 Toks[0].setLocation(FirstTok.getLocation());
696 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
697 static_cast<uintptr_t>(Kind)));
698 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
699 /*OwnsTokens=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000700}
701
Douglas Gregorc7d65762010-09-09 22:45:38 +0000702void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
703 PragmaIntroducerKind Introducer,
704 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000705 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +0000706}
707
Douglas Gregorc7d65762010-09-09 22:45:38 +0000708void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
709 PragmaIntroducerKind Introducer,
710 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +0000711 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +0000712}
713
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000714// #pragma unused(identifier)
Douglas Gregorc7d65762010-09-09 22:45:38 +0000715void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
716 PragmaIntroducerKind Introducer,
717 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000718 // FIXME: Should we be expanding macros here? My guess is no.
719 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +0000720
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000721 // Lex the left '('.
722 Token Tok;
723 PP.Lex(Tok);
724 if (Tok.isNot(tok::l_paren)) {
725 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
726 return;
727 }
Mike Stump11289f42009-09-09 15:08:12 +0000728
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000729 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000730 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000731 SourceLocation RParenLoc;
732 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +0000733
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000734 while (true) {
735 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +0000736
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000737 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +0000738 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000739 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000740 LexID = false;
741 continue;
742 }
743
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000744 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000745 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
746 return;
747 }
Mike Stump11289f42009-09-09 15:08:12 +0000748
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000749 // We are execting a ')' or a ','.
750 if (Tok.is(tok::comma)) {
751 LexID = true;
752 continue;
753 }
Mike Stump11289f42009-09-09 15:08:12 +0000754
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000755 if (Tok.is(tok::r_paren)) {
756 RParenLoc = Tok.getLocation();
757 break;
758 }
Mike Stump11289f42009-09-09 15:08:12 +0000759
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000760 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +0000761 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000762 return;
763 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000764
765 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000766 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000767 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
768 "unused";
769 return;
770 }
771
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000772 // Verify that we have a location for the right parenthesis.
773 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +0000774 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000775
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000776 // For each identifier token, insert into the token stream a
777 // annot_pragma_unused token followed by the identifier token.
778 // This allows us to cache a "#pragma unused" that occurs inside an inline
779 // C++ member function.
780
Daniel Dunbar340cf242012-02-29 01:38:22 +0000781 Token *Toks =
782 (Token*) PP.getPreprocessorAllocator().Allocate(
783 sizeof(Token) * 2 * Identifiers.size(), llvm::alignOf<Token>());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000784 for (unsigned i=0; i != Identifiers.size(); i++) {
785 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
786 pragmaUnusedTok.startToken();
787 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
788 pragmaUnusedTok.setLocation(UnusedLoc);
789 idTok = Identifiers[i];
790 }
Daniel Dunbar340cf242012-02-29 01:38:22 +0000791 PP.EnterTokenStream(Toks, 2*Identifiers.size(),
792 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +0000793}
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000794
795// #pragma weak identifier
796// #pragma weak identifier '=' identifier
Douglas Gregorc7d65762010-09-09 22:45:38 +0000797void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
798 PragmaIntroducerKind Introducer,
799 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000800 SourceLocation WeakLoc = WeakTok.getLocation();
801
802 Token Tok;
803 PP.Lex(Tok);
804 if (Tok.isNot(tok::identifier)) {
805 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
806 return;
807 }
808
Eli Friedman68be1642012-10-04 02:36:51 +0000809 Token WeakName = Tok;
810 bool HasAlias = false;
811 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000812
813 PP.Lex(Tok);
814 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +0000815 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000816 PP.Lex(Tok);
817 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +0000818 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000819 << "weak";
820 return;
821 }
Eli Friedman68be1642012-10-04 02:36:51 +0000822 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000823 PP.Lex(Tok);
824 }
825
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +0000826 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000827 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
828 return;
829 }
830
Eli Friedman68be1642012-10-04 02:36:51 +0000831 if (HasAlias) {
832 Token *Toks =
833 (Token*) PP.getPreprocessorAllocator().Allocate(
834 sizeof(Token) * 3, llvm::alignOf<Token>());
835 Token &pragmaUnusedTok = Toks[0];
836 pragmaUnusedTok.startToken();
837 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
838 pragmaUnusedTok.setLocation(WeakLoc);
839 Toks[1] = WeakName;
840 Toks[2] = AliasName;
841 PP.EnterTokenStream(Toks, 3,
842 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000843 } else {
Eli Friedman68be1642012-10-04 02:36:51 +0000844 Token *Toks =
845 (Token*) PP.getPreprocessorAllocator().Allocate(
846 sizeof(Token) * 2, llvm::alignOf<Token>());
847 Token &pragmaUnusedTok = Toks[0];
848 pragmaUnusedTok.startToken();
849 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
850 pragmaUnusedTok.setLocation(WeakLoc);
851 Toks[1] = WeakName;
852 PP.EnterTokenStream(Toks, 2,
853 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +0000854 }
855}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000856
David Chisnall0867d9c2012-02-18 16:12:34 +0000857// #pragma redefine_extname identifier identifier
858void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
859 PragmaIntroducerKind Introducer,
860 Token &RedefToken) {
861 SourceLocation RedefLoc = RedefToken.getLocation();
862
863 Token Tok;
864 PP.Lex(Tok);
865 if (Tok.isNot(tok::identifier)) {
866 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
867 "redefine_extname";
868 return;
869 }
870
Eli Friedman68be1642012-10-04 02:36:51 +0000871 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +0000872 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +0000873
David Chisnall0867d9c2012-02-18 16:12:34 +0000874 if (Tok.isNot(tok::identifier)) {
875 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
876 << "redefine_extname";
877 return;
878 }
Eli Friedman68be1642012-10-04 02:36:51 +0000879
880 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +0000881 PP.Lex(Tok);
882
883 if (Tok.isNot(tok::eod)) {
884 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
885 "redefine_extname";
886 return;
887 }
888
Eli Friedman68be1642012-10-04 02:36:51 +0000889 Token *Toks =
890 (Token*) PP.getPreprocessorAllocator().Allocate(
891 sizeof(Token) * 3, llvm::alignOf<Token>());
892 Token &pragmaRedefTok = Toks[0];
893 pragmaRedefTok.startToken();
894 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
895 pragmaRedefTok.setLocation(RedefLoc);
896 Toks[1] = RedefName;
897 Toks[2] = AliasName;
898 PP.EnterTokenStream(Toks, 3,
899 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +0000900}
901
902
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000903void
904PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
905 PragmaIntroducerKind Introducer,
906 Token &Tok) {
907 tok::OnOffSwitch OOS;
908 if (PP.LexOnOffSwitch(OOS))
909 return;
910
Eli Friedman68be1642012-10-04 02:36:51 +0000911 Token *Toks =
912 (Token*) PP.getPreprocessorAllocator().Allocate(
913 sizeof(Token) * 1, llvm::alignOf<Token>());
914 new (Toks) Token();
915 Toks[0].startToken();
916 Toks[0].setKind(tok::annot_pragma_fp_contract);
917 Toks[0].setLocation(Tok.getLocation());
918 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
919 static_cast<uintptr_t>(OOS)));
920 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
921 /*OwnsTokens=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +0000922}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000923
924void
925PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
926 PragmaIntroducerKind Introducer,
927 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +0000928 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000929 if (Tok.isNot(tok::identifier)) {
930 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
931 "OPENCL";
932 return;
933 }
934 IdentifierInfo *ename = Tok.getIdentifierInfo();
935 SourceLocation NameLoc = Tok.getLocation();
936
937 PP.Lex(Tok);
938 if (Tok.isNot(tok::colon)) {
939 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
940 return;
941 }
942
943 PP.Lex(Tok);
944 if (Tok.isNot(tok::identifier)) {
945 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
946 return;
947 }
948 IdentifierInfo *op = Tok.getIdentifierInfo();
949
950 unsigned state;
951 if (op->isStr("enable")) {
952 state = 1;
953 } else if (op->isStr("disable")) {
954 state = 0;
955 } else {
956 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
957 return;
958 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +0000959 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000960
Eli Friedman68be1642012-10-04 02:36:51 +0000961 PP.Lex(Tok);
962 if (Tok.isNot(tok::eod)) {
963 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
964 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000965 return;
966 }
Eli Friedman68be1642012-10-04 02:36:51 +0000967
968 OpenCLExtData data(ename, state);
969 Token *Toks =
970 (Token*) PP.getPreprocessorAllocator().Allocate(
971 sizeof(Token) * 1, llvm::alignOf<Token>());
972 new (Toks) Token();
973 Toks[0].startToken();
974 Toks[0].setKind(tok::annot_pragma_opencl_extension);
975 Toks[0].setLocation(NameLoc);
976 Toks[0].setAnnotationValue(data.getOpaqueValue());
977 PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
978 /*OwnsTokens=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +0000979
980 if (PP.getPPCallbacks())
981 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename,
982 StateLoc, state);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +0000983}
984
Alexey Bataeva769e072013-03-22 06:34:35 +0000985/// \brief Handle '#pragma omp ...' when OpenMP is disabled.
986///
987void
988PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
989 PragmaIntroducerKind Introducer,
990 Token &FirstTok) {
991 if (PP.getDiagnostics().getDiagnosticLevel(diag::warn_pragma_omp_ignored,
992 FirstTok.getLocation()) !=
993 DiagnosticsEngine::Ignored) {
994 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
995 PP.getDiagnostics().setDiagnosticMapping(diag::warn_pragma_omp_ignored,
996 diag::MAP_IGNORE,
997 SourceLocation());
998 }
999 PP.DiscardUntilEndOfDirective();
1000}
1001
1002/// \brief Handle '#pragma omp ...' when OpenMP is enabled.
1003///
1004void
1005PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
1006 PragmaIntroducerKind Introducer,
1007 Token &FirstTok) {
1008 SmallVector<Token, 16> Pragma;
1009 Token Tok;
1010 Tok.startToken();
1011 Tok.setKind(tok::annot_pragma_openmp);
1012 Tok.setLocation(FirstTok.getLocation());
1013
1014 while (Tok.isNot(tok::eod)) {
1015 Pragma.push_back(Tok);
1016 PP.Lex(Tok);
1017 }
1018 SourceLocation EodLoc = Tok.getLocation();
1019 Tok.startToken();
1020 Tok.setKind(tok::annot_pragma_openmp_end);
1021 Tok.setLocation(EodLoc);
1022 Pragma.push_back(Tok);
1023
1024 Token *Toks = new Token[Pragma.size()];
1025 std::copy(Pragma.begin(), Pragma.end(), Toks);
1026 PP.EnterTokenStream(Toks, Pragma.size(),
1027 /*DisableMacroExpansion=*/true, /*OwnsTokens=*/true);
1028}
Reid Kleckner002562a2013-05-06 21:02:12 +00001029
David Majnemer4bb09802014-02-10 19:50:15 +00001030/// \brief Handle '#pragma pointers_to_members'
1031// The grammar for this pragma is as follows:
1032//
1033// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
1034//
1035// #pragma pointers_to_members '(' 'best_case' ')'
1036// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
1037// #pragma pointers_to_members '(' inheritance-model ')'
1038void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
1039 PragmaIntroducerKind Introducer,
1040 Token &Tok) {
1041 SourceLocation PointersToMembersLoc = Tok.getLocation();
1042 PP.Lex(Tok);
1043 if (Tok.isNot(tok::l_paren)) {
1044 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
1045 << "pointers_to_members";
1046 return;
1047 }
1048 PP.Lex(Tok);
1049 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
1050 if (!Arg) {
1051 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1052 << "pointers_to_members";
1053 return;
1054 }
1055 PP.Lex(Tok);
1056
David Majnemer86c318f2014-02-11 21:05:00 +00001057 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00001058 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001059 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00001060 } else {
1061 if (Arg->isStr("full_generality")) {
1062 if (Tok.is(tok::comma)) {
1063 PP.Lex(Tok);
1064
1065 Arg = Tok.getIdentifierInfo();
1066 if (!Arg) {
1067 PP.Diag(Tok.getLocation(),
1068 diag::err_pragma_pointers_to_members_unknown_kind)
1069 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
1070 return;
1071 }
1072 PP.Lex(Tok);
1073 } else if (Tok.is(tok::r_paren)) {
1074 // #pragma pointers_to_members(full_generality) implicitly specifies
1075 // virtual_inheritance.
1076 Arg = 0;
David Majnemer86c318f2014-02-11 21:05:00 +00001077 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001078 } else {
1079 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
1080 << "full_generality";
1081 return;
1082 }
1083 }
1084
1085 if (Arg) {
1086 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001087 RepresentationMethod =
1088 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001089 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001090 RepresentationMethod =
1091 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001092 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00001093 RepresentationMethod =
1094 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00001095 } else {
1096 PP.Diag(Tok.getLocation(),
1097 diag::err_pragma_pointers_to_members_unknown_kind)
1098 << Arg << /*HasPointerDeclaration*/ 1;
1099 return;
1100 }
1101 }
1102 }
1103
1104 if (Tok.isNot(tok::r_paren)) {
1105 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
1106 << (Arg ? Arg->getName() : "full_generality");
1107 return;
1108 }
1109
1110 PP.Lex(Tok);
1111 if (Tok.isNot(tok::eod)) {
1112 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1113 << "pointers_to_members";
1114 return;
1115 }
1116
1117 Token AnnotTok;
1118 AnnotTok.startToken();
1119 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
1120 AnnotTok.setLocation(PointersToMembersLoc);
1121 AnnotTok.setAnnotationValue(
1122 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
1123 PP.EnterToken(AnnotTok);
1124}
1125
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001126/// \brief Handle '#pragma vtordisp'
1127// The grammar for this pragma is as follows:
1128//
1129// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
1130//
1131// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
1132// #pragma vtordisp '(' 'pop' ')'
1133// #pragma vtordisp '(' ')'
1134void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
1135 PragmaIntroducerKind Introducer,
1136 Token &Tok) {
1137 SourceLocation VtorDispLoc = Tok.getLocation();
1138 PP.Lex(Tok);
1139 if (Tok.isNot(tok::l_paren)) {
1140 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
1141 return;
1142 }
1143 PP.Lex(Tok);
1144
1145 Sema::PragmaVtorDispKind Kind = Sema::PVDK_Set;
1146 const IdentifierInfo *II = Tok.getIdentifierInfo();
1147 if (II) {
1148 if (II->isStr("push")) {
1149 // #pragma vtordisp(push, mode)
1150 PP.Lex(Tok);
1151 if (Tok.isNot(tok::comma)) {
1152 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
1153 return;
1154 }
1155 PP.Lex(Tok);
1156 Kind = Sema::PVDK_Push;
1157 // not push, could be on/off
1158 } else if (II->isStr("pop")) {
1159 // #pragma vtordisp(pop)
1160 PP.Lex(Tok);
1161 Kind = Sema::PVDK_Pop;
1162 }
1163 // not push or pop, could be on/off
1164 } else {
1165 if (Tok.is(tok::r_paren)) {
1166 // #pragma vtordisp()
1167 Kind = Sema::PVDK_Reset;
1168 }
1169 }
1170
1171
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001172 uint64_t Value = 0;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001173 if (Kind == Sema::PVDK_Push || Kind == Sema::PVDK_Set) {
1174 const IdentifierInfo *II = Tok.getIdentifierInfo();
1175 if (II && II->isStr("off")) {
1176 PP.Lex(Tok);
1177 Value = 0;
1178 } else if (II && II->isStr("on")) {
1179 PP.Lex(Tok);
1180 Value = 1;
1181 } else if (Tok.is(tok::numeric_constant) &&
1182 PP.parseSimpleIntegerLiteral(Tok, Value)) {
1183 if (Value > 2) {
1184 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
1185 << 0 << 2 << "vtordisp";
1186 return;
1187 }
1188 } else {
1189 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1190 << "vtordisp";
1191 return;
1192 }
1193 }
1194
1195 // Finish the pragma: ')' $
1196 if (Tok.isNot(tok::r_paren)) {
1197 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
1198 return;
1199 }
1200 PP.Lex(Tok);
1201 if (Tok.isNot(tok::eod)) {
1202 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1203 << "vtordisp";
1204 return;
1205 }
1206
1207 // Enter the annotation.
1208 Token AnnotTok;
1209 AnnotTok.startToken();
1210 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
1211 AnnotTok.setLocation(VtorDispLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00001212 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
1213 static_cast<uintptr_t>((Kind << 16) | (Value & 0xFFFF))));
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001214 PP.EnterToken(AnnotTok);
1215}
1216
Reid Klecknerd3923aa2014-04-03 19:04:24 +00001217void PragmaMSInitSeg::HandlePragma(Preprocessor &PP,
1218 PragmaIntroducerKind Introducer,
1219 Token &Tok) {
1220 unsigned ID = PP.getDiagnostics().getCustomDiagID(
1221 DiagnosticsEngine::Error, "'#pragma init_seg' not implemented");
1222 PP.Diag(Tok.getLocation(), ID);
1223}
1224
Aaron Ballman5d041be2013-06-04 02:07:14 +00001225/// \brief Handle the Microsoft \#pragma detect_mismatch extension.
1226///
1227/// The syntax is:
1228/// \code
1229/// #pragma detect_mismatch("name", "value")
1230/// \endcode
1231/// Where 'name' and 'value' are quoted strings. The values are embedded in
1232/// the object file and passed along to the linker. If the linker detects a
1233/// mismatch in the object file's values for the given name, a LNK2038 error
1234/// is emitted. See MSDN for more details.
1235void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
1236 PragmaIntroducerKind Introducer,
1237 Token &Tok) {
1238 SourceLocation CommentLoc = Tok.getLocation();
1239 PP.Lex(Tok);
1240 if (Tok.isNot(tok::l_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001241 PP.Diag(CommentLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001242 return;
1243 }
1244
1245 // Read the name to embed, which must be a string literal.
1246 std::string NameString;
1247 if (!PP.LexStringLiteral(Tok, NameString,
1248 "pragma detect_mismatch",
1249 /*MacroExpansion=*/true))
1250 return;
1251
1252 // Read the comma followed by a second string literal.
1253 std::string ValueString;
1254 if (Tok.isNot(tok::comma)) {
1255 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1256 return;
1257 }
1258
1259 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
1260 /*MacroExpansion=*/true))
1261 return;
1262
1263 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00001264 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00001265 return;
1266 }
1267 PP.Lex(Tok); // Eat the r_paren.
1268
1269 if (Tok.isNot(tok::eod)) {
1270 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
1271 return;
1272 }
1273
Reid Kleckner71966c92014-02-20 23:37:45 +00001274 // If the pragma is lexically sound, notify any interested PPCallbacks.
1275 if (PP.getPPCallbacks())
1276 PP.getPPCallbacks()->PragmaDetectMismatch(CommentLoc, NameString,
1277 ValueString);
1278
Aaron Ballman5d041be2013-06-04 02:07:14 +00001279 Actions.ActOnPragmaDetectMismatch(NameString, ValueString);
1280}
1281
Reid Kleckner002562a2013-05-06 21:02:12 +00001282/// \brief Handle the microsoft \#pragma comment extension.
1283///
1284/// The syntax is:
1285/// \code
1286/// #pragma comment(linker, "foo")
1287/// \endcode
1288/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
1289/// "foo" is a string, which is fully macro expanded, and permits string
1290/// concatenation, embedded escape characters etc. See MSDN for more details.
1291void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
1292 PragmaIntroducerKind Introducer,
1293 Token &Tok) {
1294 SourceLocation CommentLoc = Tok.getLocation();
1295 PP.Lex(Tok);
1296 if (Tok.isNot(tok::l_paren)) {
1297 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1298 return;
1299 }
1300
1301 // Read the identifier.
1302 PP.Lex(Tok);
1303 if (Tok.isNot(tok::identifier)) {
1304 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
1305 return;
1306 }
1307
1308 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001309 IdentifierInfo *II = Tok.getIdentifierInfo();
1310 Sema::PragmaMSCommentKind Kind =
1311 llvm::StringSwitch<Sema::PragmaMSCommentKind>(II->getName())
1312 .Case("linker", Sema::PCK_Linker)
1313 .Case("lib", Sema::PCK_Lib)
1314 .Case("compiler", Sema::PCK_Compiler)
1315 .Case("exestr", Sema::PCK_ExeStr)
1316 .Case("user", Sema::PCK_User)
1317 .Default(Sema::PCK_Unknown);
1318 if (Kind == Sema::PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00001319 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
1320 return;
1321 }
1322
1323 // Read the optional string if present.
1324 PP.Lex(Tok);
1325 std::string ArgumentString;
1326 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
1327 "pragma comment",
1328 /*MacroExpansion=*/true))
1329 return;
1330
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001331 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00001332 // FIXME: If the kind is "compiler" warn if the string is present (it is
1333 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001334 // The MSDN docs say that "lib" and "linker" require a string and have a short
1335 // whitelist of linker options they support, but in practice MSVC doesn't
1336 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00001337
1338 if (Tok.isNot(tok::r_paren)) {
1339 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1340 return;
1341 }
1342 PP.Lex(Tok); // eat the r_paren.
1343
1344 if (Tok.isNot(tok::eod)) {
1345 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
1346 return;
1347 }
1348
Reid Kleckner71966c92014-02-20 23:37:45 +00001349 // If the pragma is lexically sound, notify any interested PPCallbacks.
1350 if (PP.getPPCallbacks())
1351 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
1352
Reid Klecknere43f0fe2013-05-08 13:44:39 +00001353 Actions.ActOnPragmaMSComment(Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00001354}