blob: e414e4fc5ae17030691098598afbb8c8bd5434cc [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 Dunbarcbb98ed2010-07-31 19:17:07 +0000113// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
114// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
115static void ParseAlignPragma(Action &Actions, Preprocessor &PP, Token &FirstTok,
116 bool IsOptions) {
Daniel Dunbar861800c2010-05-26 23:29:06 +0000117 Token Tok;
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000118
119 if (IsOptions) {
120 PP.Lex(Tok);
121 if (Tok.isNot(tok::identifier) ||
122 !Tok.getIdentifierInfo()->isStr("align")) {
123 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
124 return;
125 }
Daniel Dunbar861800c2010-05-26 23:29:06 +0000126 }
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000127
Daniel Dunbar861800c2010-05-26 23:29:06 +0000128 PP.Lex(Tok);
129 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000130 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
131 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000132 return;
133 }
134
135 PP.Lex(Tok);
136 if (Tok.isNot(tok::identifier)) {
137 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000138 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000139 return;
140 }
141
142 Action::PragmaOptionsAlignKind Kind = Action::POAK_Natural;
143 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar638e7cf2010-05-27 18:42:09 +0000144 if (II->isStr("native"))
145 Kind = Action::POAK_Native;
146 else if (II->isStr("natural"))
Daniel Dunbar861800c2010-05-26 23:29:06 +0000147 Kind = Action::POAK_Natural;
Daniel Dunbar6f739142010-05-27 18:42:17 +0000148 else if (II->isStr("packed"))
149 Kind = Action::POAK_Packed;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000150 else if (II->isStr("power"))
151 Kind = Action::POAK_Power;
152 else if (II->isStr("mac68k"))
153 Kind = Action::POAK_Mac68k;
154 else if (II->isStr("reset"))
155 Kind = Action::POAK_Reset;
156 else {
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000157 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
158 << IsOptions;
Daniel Dunbar861800c2010-05-26 23:29:06 +0000159 return;
160 }
161
162 SourceLocation KindLoc = Tok.getLocation();
163 PP.Lex(Tok);
164 if (Tok.isNot(tok::eom)) {
165 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000166 << (IsOptions ? "options" : "align");
Daniel Dunbar861800c2010-05-26 23:29:06 +0000167 return;
168 }
169
Daniel Dunbarcbb98ed2010-07-31 19:17:07 +0000170 Actions.ActOnPragmaOptionsAlign(Kind, FirstTok.getLocation(), KindLoc);
171}
172
173void PragmaAlignHandler::HandlePragma(Preprocessor &PP, Token &AlignTok) {
174 ParseAlignPragma(Actions, PP, AlignTok, /*IsOptions=*/false);
175}
176
177void PragmaOptionsHandler::HandlePragma(Preprocessor &PP, Token &OptionsTok) {
178 ParseAlignPragma(Actions, PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar861800c2010-05-26 23:29:06 +0000179}
180
Ted Kremenek4726d032009-03-23 22:28:25 +0000181// #pragma unused(identifier)
182void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
183 // FIXME: Should we be expanding macros here? My guess is no.
184 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000185
Ted Kremenek4726d032009-03-23 22:28:25 +0000186 // Lex the left '('.
187 Token Tok;
188 PP.Lex(Tok);
189 if (Tok.isNot(tok::l_paren)) {
190 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
191 return;
192 }
193 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000194
Ted Kremenek4726d032009-03-23 22:28:25 +0000195 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000196 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000197 SourceLocation RParenLoc;
198 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000199
Ted Kremenek4726d032009-03-23 22:28:25 +0000200 while (true) {
201 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Ted Kremenek4726d032009-03-23 22:28:25 +0000203 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000204 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000205 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000206 LexID = false;
207 continue;
208 }
209
Ted Kremenek7a02a372009-08-03 23:24:57 +0000210 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000211 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
212 return;
213 }
Mike Stump1eb44332009-09-09 15:08:12 +0000214
Ted Kremenek4726d032009-03-23 22:28:25 +0000215 // We are execting a ')' or a ','.
216 if (Tok.is(tok::comma)) {
217 LexID = true;
218 continue;
219 }
Mike Stump1eb44332009-09-09 15:08:12 +0000220
Ted Kremenek4726d032009-03-23 22:28:25 +0000221 if (Tok.is(tok::r_paren)) {
222 RParenLoc = Tok.getLocation();
223 break;
224 }
Mike Stump1eb44332009-09-09 15:08:12 +0000225
Ted Kremenek7a02a372009-08-03 23:24:57 +0000226 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000227 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
228 return;
229 }
Eli Friedman99914792009-06-05 00:49:58 +0000230
231 PP.Lex(Tok);
232 if (Tok.isNot(tok::eom)) {
233 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
234 "unused";
235 return;
236 }
237
Ted Kremenek4726d032009-03-23 22:28:25 +0000238 // Verify that we have a location for the right parenthesis.
239 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000240 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000241
Mike Stump1eb44332009-09-09 15:08:12 +0000242 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000243 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
Douglas Gregor23c94db2010-07-02 17:43:08 +0000244 parser.getCurScope(), UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000245}
Eli Friedman99914792009-06-05 00:49:58 +0000246
247// #pragma weak identifier
248// #pragma weak identifier '=' identifier
249void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
250 // FIXME: Should we be expanding macros here? My guess is no.
251 SourceLocation WeakLoc = WeakTok.getLocation();
252
253 Token Tok;
254 PP.Lex(Tok);
255 if (Tok.isNot(tok::identifier)) {
256 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
257 return;
258 }
259
260 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
261 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
262
263 PP.Lex(Tok);
264 if (Tok.is(tok::equal)) {
265 PP.Lex(Tok);
266 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000267 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000268 << "weak";
269 return;
270 }
271 AliasName = Tok.getIdentifierInfo();
272 AliasNameLoc = Tok.getLocation();
273 PP.Lex(Tok);
274 }
275
276 if (Tok.isNot(tok::eom)) {
277 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
278 return;
279 }
280
281 if (AliasName) {
282 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
283 AliasNameLoc);
284 } else {
285 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
286 }
287}