blob: c4e4a525e56001592bc6b9b2a309ace0f137fa23 [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 Dunbar861800c2010-05-26 23:29:06 +0000113// #pragma 'options' 'align' '=' {'natural', 'mac68k', 'power', 'reset'}
114void 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 }
123
124 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();
139 if (II->isStr("natural"))
140 Kind = Action::POAK_Natural;
141 else if (II->isStr("power"))
142 Kind = Action::POAK_Power;
143 else if (II->isStr("mac68k"))
144 Kind = Action::POAK_Mac68k;
145 else if (II->isStr("reset"))
146 Kind = Action::POAK_Reset;
147 else {
148 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option);
149 return;
150 }
151
152 SourceLocation KindLoc = Tok.getLocation();
153 PP.Lex(Tok);
154 if (Tok.isNot(tok::eom)) {
155 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
156 << "options";
157 return;
158 }
159
160 Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc);
161}
162
Ted Kremenek4726d032009-03-23 22:28:25 +0000163// #pragma unused(identifier)
164void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
165 // FIXME: Should we be expanding macros here? My guess is no.
166 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000167
Ted Kremenek4726d032009-03-23 22:28:25 +0000168 // Lex the left '('.
169 Token Tok;
170 PP.Lex(Tok);
171 if (Tok.isNot(tok::l_paren)) {
172 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
173 return;
174 }
175 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000176
Ted Kremenek4726d032009-03-23 22:28:25 +0000177 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000178 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000179 SourceLocation RParenLoc;
180 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000181
Ted Kremenek4726d032009-03-23 22:28:25 +0000182 while (true) {
183 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000184
Ted Kremenek4726d032009-03-23 22:28:25 +0000185 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000186 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000187 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000188 LexID = false;
189 continue;
190 }
191
Ted Kremenek7a02a372009-08-03 23:24:57 +0000192 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000193 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
194 return;
195 }
Mike Stump1eb44332009-09-09 15:08:12 +0000196
Ted Kremenek4726d032009-03-23 22:28:25 +0000197 // We are execting a ')' or a ','.
198 if (Tok.is(tok::comma)) {
199 LexID = true;
200 continue;
201 }
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Ted Kremenek4726d032009-03-23 22:28:25 +0000203 if (Tok.is(tok::r_paren)) {
204 RParenLoc = Tok.getLocation();
205 break;
206 }
Mike Stump1eb44332009-09-09 15:08:12 +0000207
Ted Kremenek7a02a372009-08-03 23:24:57 +0000208 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000209 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
210 return;
211 }
Eli Friedman99914792009-06-05 00:49:58 +0000212
213 PP.Lex(Tok);
214 if (Tok.isNot(tok::eom)) {
215 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
216 "unused";
217 return;
218 }
219
Ted Kremenek4726d032009-03-23 22:28:25 +0000220 // Verify that we have a location for the right parenthesis.
221 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000222 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000223
Mike Stump1eb44332009-09-09 15:08:12 +0000224 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000225 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
226 parser.CurScope, UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000227}
Eli Friedman99914792009-06-05 00:49:58 +0000228
229// #pragma weak identifier
230// #pragma weak identifier '=' identifier
231void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
232 // FIXME: Should we be expanding macros here? My guess is no.
233 SourceLocation WeakLoc = WeakTok.getLocation();
234
235 Token Tok;
236 PP.Lex(Tok);
237 if (Tok.isNot(tok::identifier)) {
238 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
239 return;
240 }
241
242 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
243 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
244
245 PP.Lex(Tok);
246 if (Tok.is(tok::equal)) {
247 PP.Lex(Tok);
248 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000249 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000250 << "weak";
251 return;
252 }
253 AliasName = Tok.getIdentifierInfo();
254 AliasNameLoc = Tok.getLocation();
255 PP.Lex(Tok);
256 }
257
258 if (Tok.isNot(tok::eom)) {
259 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
260 return;
261 }
262
263 if (AliasName) {
264 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
265 AliasNameLoc);
266 } else {
267 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
268 }
269}