blob: b27e655ff4295507278b6982f9656a49c335ddb8 [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
21// #pragma pack(...) comes in the following delicious flavors:
22// pack '(' [integer] ')'
23// pack '(' 'show' ')'
24// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
25void PragmaPackHandler::HandlePragma(Preprocessor &PP, Token &PackTok) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000026 SourceLocation PackLoc = PackTok.getLocation();
27
28 Token Tok;
29 PP.Lex(Tok);
30 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000031 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000032 return;
33 }
34
35 Action::PragmaPackKind Kind = Action::PPK_Default;
36 IdentifierInfo *Name = 0;
Sebastian Redl15faa7f2008-12-09 20:22:58 +000037 Action::OwningExprResult Alignment(Actions);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000038 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +000039 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000040 if (Tok.is(tok::numeric_constant)) {
41 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000042 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000043 return;
44
45 PP.Lex(Tok);
46 } else if (Tok.is(tok::identifier)) {
47 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +000048 if (II->isStr("show")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000049 Kind = Action::PPK_Show;
50 PP.Lex(Tok);
51 } else {
Chris Lattner08631c52008-11-23 21:45:46 +000052 if (II->isStr("push")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000053 Kind = Action::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +000054 } else if (II->isStr("pop")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000055 Kind = Action::PPK_Pop;
56 } else {
57 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
58 return;
Mike Stump1eb44332009-09-09 15:08:12 +000059 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000060 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000061
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000062 if (Tok.is(tok::comma)) {
63 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000064
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000065 if (Tok.is(tok::numeric_constant)) {
66 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000067 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000068 return;
69
70 PP.Lex(Tok);
71 } else if (Tok.is(tok::identifier)) {
72 Name = Tok.getIdentifierInfo();
73 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000074
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000075 if (Tok.is(tok::comma)) {
76 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000077
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000078 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +000079 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000080 return;
81 }
Mike Stump1eb44332009-09-09 15:08:12 +000082
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000083 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000084 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000085 return;
86
87 PP.Lex(Tok);
88 }
89 } else {
Chris Lattner08631c52008-11-23 21:45:46 +000090 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000091 return;
92 }
93 }
94 }
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000095 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000096
97 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000098 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000099 return;
100 }
101
Daniel Dunbar861800c2010-05-26 23:29:06 +0000102 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedman99914792009-06-05 00:49:58 +0000103 PP.Lex(Tok);
104 if (Tok.isNot(tok::eom)) {
105 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
106 return;
107 }
108
Sebastian Redleffa8d12008-12-10 00:02:53 +0000109 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000110 LParenLoc, RParenLoc);
111}
112
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000113// #pragma 'options' 'align' '=' {'native','natural','mac68k','power','reset'}
Daniel Dunbar861800c2010-05-26 23:29:06 +0000114void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
115 SourceLocation OptionsLoc = OptionsTok.getLocation();
116
117 Token Tok;
118 PP.Lex(Tok);
119 if (Tok.isNot(tok::identifier) || !Tok.getIdentifierInfo()->isStr("align")) {
120 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
121 return;
122 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000123
Daniel Dunbar861800c2010-05-26 23:29:06 +0000124 PP.Lex(Tok);
125 if (Tok.isNot(tok::equal)) {
126 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_equal);
127 return;
128 }
129
130 PP.Lex(Tok);
131 if (Tok.isNot(tok::identifier)) {
132 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
133 << "options";
134 return;
135 }
136
137 Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural;
138 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000139 if (II->isStr("native"))
140 Kind = Action::POAK_Native;
141 else if (II->isStr("natural"))
Daniel Dunbar861800c2010-05-26 23:29:06 +0000142 Kind = Action::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000143 else if (II->isStr("packed"))
144 Kind = Action::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000145 else if (II->isStr("power"))
146 Kind = Action::POAK_Power;
147 else if (II->isStr("mac68k"))
148 Kind = Action::POAK_Mac68k;
149 else if (II->isStr("reset"))
150 Kind = Action::POAK_Reset;
151 else {
152 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option);
153 return;
154 }
155
156 SourceLocation KindLoc = Tok.getLocation();
157 PP.Lex(Tok);
158 if (Tok.isNot(tok::eom)) {
159 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
160 << "options";
161 return;
162 }
163
164 Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc);
165}
166
Ted Kremenek4726d032009-03-23 22:28:25 +0000167// #pragma unused(identifier)
168void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
169 // FIXME: Should we be expanding macros here? My guess is no.
170 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000171
Ted Kremenek4726d032009-03-23 22:28:25 +0000172 // Lex the left '('.
173 Token Tok;
174 PP.Lex(Tok);
175 if (Tok.isNot(tok::l_paren)) {
176 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
177 return;
178 }
179 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000180
Ted Kremenek4726d032009-03-23 22:28:25 +0000181 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000182 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000183 SourceLocation RParenLoc;
184 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000185
Ted Kremenek4726d032009-03-23 22:28:25 +0000186 while (true) {
187 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000188
Ted Kremenek4726d032009-03-23 22:28:25 +0000189 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000190 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000191 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000192 LexID = false;
193 continue;
194 }
195
Ted Kremenek7a02a372009-08-03 23:24:57 +0000196 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000197 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
198 return;
199 }
Mike Stump1eb44332009-09-09 15:08:12 +0000200
Ted Kremenek4726d032009-03-23 22:28:25 +0000201 // We are execting a ')' or a ','.
202 if (Tok.is(tok::comma)) {
203 LexID = true;
204 continue;
205 }
Mike Stump1eb44332009-09-09 15:08:12 +0000206
Ted Kremenek4726d032009-03-23 22:28:25 +0000207 if (Tok.is(tok::r_paren)) {
208 RParenLoc = Tok.getLocation();
209 break;
210 }
Mike Stump1eb44332009-09-09 15:08:12 +0000211
Ted Kremenek7a02a372009-08-03 23:24:57 +0000212 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000213 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
214 return;
215 }
Eli Friedman99914792009-06-05 00:49:58 +0000216
217 PP.Lex(Tok);
218 if (Tok.isNot(tok::eom)) {
219 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
220 "unused";
221 return;
222 }
223
Ted Kremenek4726d032009-03-23 22:28:25 +0000224 // Verify that we have a location for the right parenthesis.
225 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000226 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000227
Mike Stump1eb44332009-09-09 15:08:12 +0000228 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000229 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
230 parser.CurScope, UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000231}
Eli Friedman99914792009-06-05 00:49:58 +0000232
233// #pragma weak identifier
234// #pragma weak identifier '=' identifier
235void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
236 // FIXME: Should we be expanding macros here? My guess is no.
237 SourceLocation WeakLoc = WeakTok.getLocation();
238
239 Token Tok;
240 PP.Lex(Tok);
241 if (Tok.isNot(tok::identifier)) {
242 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
243 return;
244 }
245
246 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
247 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
248
249 PP.Lex(Tok);
250 if (Tok.is(tok::equal)) {
251 PP.Lex(Tok);
252 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000253 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000254 << "weak";
255 return;
256 }
257 AliasName = Tok.getIdentifierInfo();
258 AliasNameLoc = Tok.getLocation();
259 PP.Lex(Tok);
260 }
261
262 if (Tok.isNot(tok::eom)) {
263 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
264 return;
265 }
266
267 if (AliasName) {
268 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
269 AliasNameLoc);
270 } else {
271 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
272 }
273}