blob: c53b2e4d27ccbbf31a466d5e67cd85d13e824499 [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"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000016#include "clang/Lex/Preprocessor.h"
17#include "clang/Parse/Action.h"
Ted Kremenek4726d032009-03-23 22:28:25 +000018#include "clang/Parse/Parser.h"
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000019using namespace clang;
20
Eli Friedmanaa8b0d12010-08-05 06:57:20 +000021
22// #pragma GCC visibility comes in two variants:
23// 'push' '(' [visibility] ')'
24// 'pop'
25void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP, Token &VisTok) {
26 SourceLocation VisLoc = VisTok.getLocation();
27
28 Token Tok;
29 PP.Lex(Tok);
30
31 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
32
33 bool IsPush;
34 const IdentifierInfo *VisType;
35 if (PushPop && PushPop->isStr("pop")) {
36 IsPush = false;
37 VisType = 0;
38 } else if (PushPop && PushPop->isStr("push")) {
39 IsPush = true;
40 PP.Lex(Tok);
41 if (Tok.isNot(tok::l_paren)) {
42 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
43 << "visibility";
44 return;
45 }
46 PP.Lex(Tok);
47 VisType = Tok.getIdentifierInfo();
48 if (!VisType) {
49 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
50 << "visibility";
51 return;
52 }
53 PP.Lex(Tok);
54 if (Tok.isNot(tok::r_paren)) {
55 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
56 << "visibility";
57 return;
58 }
59 } else {
60 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
61 << "visibility";
62 return;
63 }
64 PP.Lex(Tok);
65 if (Tok.isNot(tok::eom)) {
66 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
67 << "visibility";
68 return;
69 }
70
71 Actions.ActOnPragmaVisibility(IsPush, VisType, VisLoc);
72}
73
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000074// #pragma pack(...) comes in the following delicious flavors:
75// pack '(' [integer] ')'
76// pack '(' 'show' ')'
77// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
78void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000079 SourceLocation PackLoc = PackTok.getLocation();
80
81 Token Tok;
82 PP.Lex(Tok);
83 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000084 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000085 return;
86 }
87
88 Action::PragmaPackKind Kind = Action::PPK_Default;
89 IdentifierInfo *Name = 0;
Sebastian Redl15faa7f2008-12-09 20:22:58 +000090 Action::OwningExprResult Alignment(Actions);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000091 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +000092 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000093 if (Tok.is(tok::numeric_constant)) {
94 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000095 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000096 return;
97
98 PP.Lex(Tok);
99 } else if (Tok.is(tok::identifier)) {
100 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +0000101 if (II->isStr("show")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000102 Kind = Action::PPK_Show;
103 PP.Lex(Tok);
104 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000105 if (II->isStr("push")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000106 Kind = Action::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +0000107 } else if (II->isStr("pop")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000108 Kind = Action::PPK_Pop;
109 } else {
110 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
111 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000112 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000113 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000114
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000115 if (Tok.is(tok::comma)) {
116 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000117
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000118 if (Tok.is(tok::numeric_constant)) {
119 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000120 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000121 return;
122
123 PP.Lex(Tok);
124 } else if (Tok.is(tok::identifier)) {
125 Name = Tok.getIdentifierInfo();
126 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000127
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000128 if (Tok.is(tok::comma)) {
129 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000130
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000131 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +0000132 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000133 return;
134 }
Mike Stump1eb44332009-09-09 15:08:12 +0000135
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000136 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000137 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000138 return;
139
140 PP.Lex(Tok);
141 }
142 } else {
Chris Lattner08631c52008-11-23 21:45:46 +0000143 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000144 return;
145 }
146 }
147 }
Sebastian Redl0e9eabc2008-12-09 13:15:23 +0000148 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000149
150 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +0000151 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000152 return;
153 }
154
Daniel Dunbar861800c2010-05-26 23:29:06 +0000155 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000156 PP.Lex(Tok);
157 if (Tok.isNot(tok::eom)) {
158 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
159 return;
160 }
161
Sebastian Redleffa8d12008-12-10 00:02:53 +0000162 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000163 LParenLoc, RParenLoc);
164}
165
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000166// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
167// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
168static void ParseAlignPragma(Action &Actions, Preprocessor &PP, Token &FirstTok,
169 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000170 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000171
172 if (IsOptions) {
173 PP.Lex(Tok);
174 if (Tok.isNot(tok::identifier) ||
175 !Tok.getIdentifierInfo()->isStr("align")) {
176 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
177 return;
178 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000179 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000180
Daniel Dunbar861800c2010-05-26 23:29:06 +0000181 PP.Lex(Tok);
182 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000183 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
184 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000185 return;
186 }
187
188 PP.Lex(Tok);
189 if (Tok.isNot(tok::identifier)) {
190 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000191 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000192 return;
193 }
194
195 Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural;
196 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000197 if (II->isStr("native"))
198 Kind = Action::POAK_Native;
199 else if (II->isStr("natural"))
Daniel Dunbar861800c2010-05-26 23:29:06 +0000200 Kind = Action::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000201 else if (II->isStr("packed"))
202 Kind = Action::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000203 else if (II->isStr("power"))
204 Kind = Action::POAK_Power;
205 else if (II->isStr("mac68k"))
206 Kind = Action::POAK_Mac68k;
207 else if (II->isStr("reset"))
208 Kind = Action::POAK_Reset;
209 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000210 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
211 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000212 return;
213 }
214
215 SourceLocation KindLoc = Tok.getLocation();
216 PP.Lex(Tok);
217 if (Tok.isNot(tok::eom)) {
218 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000219 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000220 return;
221 }
222
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000223 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
224}
225
226void PragmaAlignHandler::HandlePragma(Preprocessor &PP, Token &AlignTok) {
227 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
228}
229
230void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
231 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000232}
233
Ted Kremenek4726d032009-03-23 22:28:25 +0000234// #pragma unused(identifier)
235void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
236 // FIXME: Should we be expanding macros here? My guess is no.
237 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000238
Ted Kremenek4726d032009-03-23 22:28:25 +0000239 // Lex the left '('.
240 Token Tok;
241 PP.Lex(Tok);
242 if (Tok.isNot(tok::l_paren)) {
243 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
244 return;
245 }
246 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000247
Ted Kremenek4726d032009-03-23 22:28:25 +0000248 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000249 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000250 SourceLocation RParenLoc;
251 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000252
Ted Kremenek4726d032009-03-23 22:28:25 +0000253 while (true) {
254 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000255
Ted Kremenek4726d032009-03-23 22:28:25 +0000256 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000257 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000258 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000259 LexID = false;
260 continue;
261 }
262
Ted Kremenek7a02a372009-08-03 23:24:57 +0000263 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000264 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
265 return;
266 }
Mike Stump1eb44332009-09-09 15:08:12 +0000267
Ted Kremenek4726d032009-03-23 22:28:25 +0000268 // We are execting a ')' or a ','.
269 if (Tok.is(tok::comma)) {
270 LexID = true;
271 continue;
272 }
Mike Stump1eb44332009-09-09 15:08:12 +0000273
Ted Kremenek4726d032009-03-23 22:28:25 +0000274 if (Tok.is(tok::r_paren)) {
275 RParenLoc = Tok.getLocation();
276 break;
277 }
Mike Stump1eb44332009-09-09 15:08:12 +0000278
Ted Kremenek7a02a372009-08-03 23:24:57 +0000279 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000280 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
281 return;
282 }
Eli Friedman99914792009-06-05 00:49:58 +0000283
284 PP.Lex(Tok);
285 if (Tok.isNot(tok::eom)) {
286 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
287 "unused";
288 return;
289 }
290
Ted Kremenek4726d032009-03-23 22:28:25 +0000291 // Verify that we have a location for the right parenthesis.
292 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000293 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000294
Mike Stump1eb44332009-09-09 15:08:12 +0000295 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000296 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
Douglas Gregor23c94db2010-07-02 17:43:08 +0000297 parser.getCurScope(), UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000298}
Eli Friedman99914792009-06-05 00:49:58 +0000299
300// #pragma weak identifier
301// #pragma weak identifier '=' identifier
302void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
303 // FIXME: Should we be expanding macros here? My guess is no.
304 SourceLocation WeakLoc = WeakTok.getLocation();
305
306 Token Tok;
307 PP.Lex(Tok);
308 if (Tok.isNot(tok::identifier)) {
309 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
310 return;
311 }
312
313 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
314 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
315
316 PP.Lex(Tok);
317 if (Tok.is(tok::equal)) {
318 PP.Lex(Tok);
319 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000320 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000321 << "weak";
322 return;
323 }
324 AliasName = Tok.getIdentifierInfo();
325 AliasNameLoc = Tok.getLocation();
326 PP.Lex(Tok);
327 }
328
329 if (Tok.isNot(tok::eom)) {
330 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
331 return;
332 }
333
334 if (AliasName) {
335 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
336 AliasNameLoc);
337 } else {
338 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
339 }
340}