blob: ddba09ae0f95b28640f8ba22b6caf9377881f13a [file] [log] [blame]
Daniel Dunbarfcdd8fe2008-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
14#include "ParsePragma.h"
Chris Lattner500d3292009-01-29 05:15:15 +000015#include "clang/Parse/ParseDiagnostic.h"
Ted Kremenek4726d032009-03-23 22:28:25 +000016#include "clang/Parse/Parser.h"
John McCall19510852010-08-20 18:27:03 +000017#include "clang/Lex/Preprocessor.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000018using namespace clang;
19
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000020
21// #pragma GCC visibility comes in two variants:
22// 'push' '(' [visibility] ')'
23// 'pop'
24void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Token &VisTok) {
25 SourceLocation VisLoc = VisTok.getLocation();
26
27 Token Tok;
28 PP.Lex(Tok);
29
30 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
31
32 bool IsPush;
33 const IdentifierInfo *VisType;
34 if (PushPop && PushPop->isStr("pop")) {
35 IsPush = false;
36 VisType = 0;
37 } else if (PushPop && PushPop->isStr("push")) {
38 IsPush = true;
39 PP.Lex(Tok);
40 if (Tok.isNot(tok::l_paren)) {
41 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
42 << "visibility";
43 return;
44 }
45 PP.Lex(Tok);
46 VisType = Tok.getIdentifierInfo();
47 if (!VisType) {
48 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
49 << "visibility";
50 return;
51 }
52 PP.Lex(Tok);
53 if (Tok.isNot(tok::r_paren)) {
54 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
55 << "visibility";
56 return;
57 }
58 } else {
59 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
60 << "visibility";
61 return;
62 }
63 PP.Lex(Tok);
64 if (Tok.isNot(tok::eom)) {
65 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
66 << "visibility";
67 return;
68 }
69
70 Actions.ActOnPragmaVisibility(IsPush, VisType, VisLoc);
71}
72
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000073// #pragma pack(...) comes in the following delicious flavors:
74// pack '(' [integer] ')'
75// pack '(' 'show' ')'
76// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
77void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000078 SourceLocation PackLoc = PackTok.getLocation();
79
80 Token Tok;
81 PP.Lex(Tok);
82 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000083 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000084 return;
85 }
86
John McCallf312b1e2010-08-26 23:41:50 +000087 Sema::PragmaPackKind Kind = Sema::PPK_Default;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000088 IdentifierInfo *Name = 0;
John McCall60d7b3a2010-08-24 06:29:42 +000089 ExprResult Alignment;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000090 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +000091 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000092 if (Tok.is(tok::numeric_constant)) {
93 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000094 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000095 return;
96
97 PP.Lex(Tok);
98 } else if (Tok.is(tok::identifier)) {
99 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000100 if (II->isStr("show")) {
John McCallf312b1e2010-08-26 23:41:50 +0000101 Kind = Sema::PPK_Show;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000102 PP.Lex(Tok);
103 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000104 if (II->isStr("push")) {
John McCallf312b1e2010-08-26 23:41:50 +0000105 Kind = Sema::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000106 } else if (II->isStr("pop")) {
John McCallf312b1e2010-08-26 23:41:50 +0000107 Kind = Sema::PPK_Pop;
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000108 } else {
109 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
110 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000111 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000112 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000113
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000114 if (Tok.is(tok::comma)) {
115 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000116
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000117 if (Tok.is(tok::numeric_constant)) {
118 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000119 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000120 return;
121
122 PP.Lex(Tok);
123 } else if (Tok.is(tok::identifier)) {
124 Name = Tok.getIdentifierInfo();
125 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000126
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000127 if (Tok.is(tok::comma)) {
128 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000129
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000130 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000131 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000132 return;
133 }
Mike Stump1eb44332009-09-09 15:08:12 +0000134
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000135 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000136 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000137 return;
138
139 PP.Lex(Tok);
140 }
141 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000142 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000143 return;
144 }
145 }
146 }
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000147 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000148
149 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000150 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000151 return;
152 }
153
Daniel Dunbar861800c2010-05-26 23:29:06 +0000154 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000155 PP.Lex(Tok);
156 if (Tok.isNot(tok::eom)) {
157 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
158 return;
159 }
160
Sebastian Redleffa8d12008-12-10 00:02:53 +0000161 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000162 LParenLoc, RParenLoc);
163}
164
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000165// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
166// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
John McCallf312b1e2010-08-26 23:41:50 +0000167static void ParseAlignPragma(Sema &Actions, Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000168 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000169 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000170
171 if (IsOptions) {
172 PP.Lex(Tok);
173 if (Tok.isNot(tok::identifier) ||
174 !Tok.getIdentifierInfo()->isStr("align")) {
175 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
176 return;
177 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000178 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000179
Daniel Dunbar861800c2010-05-26 23:29:06 +0000180 PP.Lex(Tok);
181 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000182 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
183 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000184 return;
185 }
186
187 PP.Lex(Tok);
188 if (Tok.isNot(tok::identifier)) {
189 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000190 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000191 return;
192 }
193
John McCallf312b1e2010-08-26 23:41:50 +0000194 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000195 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000196 if (II->isStr("native"))
John McCallf312b1e2010-08-26 23:41:50 +0000197 Kind = Sema::POAK_Native;
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000198 else if (II->isStr("natural"))
John McCallf312b1e2010-08-26 23:41:50 +0000199 Kind = Sema::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000200 else if (II->isStr("packed"))
John McCallf312b1e2010-08-26 23:41:50 +0000201 Kind = Sema::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000202 else if (II->isStr("power"))
John McCallf312b1e2010-08-26 23:41:50 +0000203 Kind = Sema::POAK_Power;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000204 else if (II->isStr("mac68k"))
John McCallf312b1e2010-08-26 23:41:50 +0000205 Kind = Sema::POAK_Mac68k;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000206 else if (II->isStr("reset"))
John McCallf312b1e2010-08-26 23:41:50 +0000207 Kind = Sema::POAK_Reset;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000208 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000209 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
210 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000211 return;
212 }
213
214 SourceLocation KindLoc = Tok.getLocation();
215 PP.Lex(Tok);
216 if (Tok.isNot(tok::eom)) {
217 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000218 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000219 return;
220 }
221
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000222 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
223}
224
225void PragmaAlignHandler::HandlePragma(Preprocessor &PP, Token &AlignTok) {
226 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
227}
228
229void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
230 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000231}
232
Ted Kremenek4726d032009-03-23 22:28:25 +0000233// #pragma unused(identifier)
234void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
235 // FIXME: Should we be expanding macros here? My guess is no.
236 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000237
Ted Kremenek4726d032009-03-23 22:28:25 +0000238 // Lex the left '('.
239 Token Tok;
240 PP.Lex(Tok);
241 if (Tok.isNot(tok::l_paren)) {
242 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
243 return;
244 }
245 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000246
Ted Kremenek4726d032009-03-23 22:28:25 +0000247 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000248 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000249 SourceLocation RParenLoc;
250 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000251
Ted Kremenek4726d032009-03-23 22:28:25 +0000252 while (true) {
253 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000254
Ted Kremenek4726d032009-03-23 22:28:25 +0000255 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000256 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000257 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000258 LexID = false;
259 continue;
260 }
261
Ted Kremenek7a02a372009-08-03 23:24:57 +0000262 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000263 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
264 return;
265 }
Mike Stump1eb44332009-09-09 15:08:12 +0000266
Ted Kremenek4726d032009-03-23 22:28:25 +0000267 // We are execting a ')' or a ','.
268 if (Tok.is(tok::comma)) {
269 LexID = true;
270 continue;
271 }
Mike Stump1eb44332009-09-09 15:08:12 +0000272
Ted Kremenek4726d032009-03-23 22:28:25 +0000273 if (Tok.is(tok::r_paren)) {
274 RParenLoc = Tok.getLocation();
275 break;
276 }
Mike Stump1eb44332009-09-09 15:08:12 +0000277
Ted Kremenek7a02a372009-08-03 23:24:57 +0000278 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000279 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
280 return;
281 }
Eli Friedman99914792009-06-05 00:49:58 +0000282
283 PP.Lex(Tok);
284 if (Tok.isNot(tok::eom)) {
285 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
286 "unused";
287 return;
288 }
289
Ted Kremenek4726d032009-03-23 22:28:25 +0000290 // Verify that we have a location for the right parenthesis.
291 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000292 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000293
Mike Stump1eb44332009-09-09 15:08:12 +0000294 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000295 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
Douglas Gregor23c94db2010-07-02 17:43:08 +0000296 parser.getCurScope(), UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000297}
Eli Friedman99914792009-06-05 00:49:58 +0000298
299// #pragma weak identifier
300// #pragma weak identifier '=' identifier
301void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
302 // FIXME: Should we be expanding macros here? My guess is no.
303 SourceLocation WeakLoc = WeakTok.getLocation();
304
305 Token Tok;
306 PP.Lex(Tok);
307 if (Tok.isNot(tok::identifier)) {
308 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
309 return;
310 }
311
312 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
313 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
314
315 PP.Lex(Tok);
316 if (Tok.is(tok::equal)) {
317 PP.Lex(Tok);
318 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000319 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000320 << "weak";
321 return;
322 }
323 AliasName = Tok.getIdentifierInfo();
324 AliasNameLoc = Tok.getLocation();
325 PP.Lex(Tok);
326 }
327
328 if (Tok.isNot(tok::eom)) {
329 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
330 return;
331 }
332
333 if (AliasName) {
334 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
335 AliasNameLoc);
336 } else {
337 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
338 }
339}