blob: 397d816c76e46da5c798b9ff69034968854f357d [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;
143 else if (II->isStr("power"))
144 Kind = Action::POAK_Power;
145 else if (II->isStr("mac68k"))
146 Kind = Action::POAK_Mac68k;
147 else if (II->isStr("reset"))
148 Kind = Action::POAK_Reset;
149 else {
150 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_invalid_option);
151 return;
152 }
153
154 SourceLocation KindLoc = Tok.getLocation();
155 PP.Lex(Tok);
156 if (Tok.isNot(tok::eom)) {
157 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
158 << "options";
159 return;
160 }
161
162 Actions.ActOnPragmaOptionsAlign(Kind, OptionsLoc, KindLoc);
163}
164
Ted Kremenek4726d032009-03-23 22:28:25 +0000165// #pragma unused(identifier)
166void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
167 // FIXME: Should we be expanding macros here? My guess is no.
168 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000169
Ted Kremenek4726d032009-03-23 22:28:25 +0000170 // Lex the left '('.
171 Token Tok;
172 PP.Lex(Tok);
173 if (Tok.isNot(tok::l_paren)) {
174 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
175 return;
176 }
177 SourceLocation LParenLoc = Tok.getLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000178
Ted Kremenek4726d032009-03-23 22:28:25 +0000179 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000180 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000181 SourceLocation RParenLoc;
182 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000183
Ted Kremenek4726d032009-03-23 22:28:25 +0000184 while (true) {
185 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000186
Ted Kremenek4726d032009-03-23 22:28:25 +0000187 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000188 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000189 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000190 LexID = false;
191 continue;
192 }
193
Ted Kremenek7a02a372009-08-03 23:24:57 +0000194 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000195 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
196 return;
197 }
Mike Stump1eb44332009-09-09 15:08:12 +0000198
Ted Kremenek4726d032009-03-23 22:28:25 +0000199 // We are execting a ')' or a ','.
200 if (Tok.is(tok::comma)) {
201 LexID = true;
202 continue;
203 }
Mike Stump1eb44332009-09-09 15:08:12 +0000204
Ted Kremenek4726d032009-03-23 22:28:25 +0000205 if (Tok.is(tok::r_paren)) {
206 RParenLoc = Tok.getLocation();
207 break;
208 }
Mike Stump1eb44332009-09-09 15:08:12 +0000209
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_punc);
212 return;
213 }
Eli Friedman99914792009-06-05 00:49:58 +0000214
215 PP.Lex(Tok);
216 if (Tok.isNot(tok::eom)) {
217 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
218 "unused";
219 return;
220 }
221
Ted Kremenek4726d032009-03-23 22:28:25 +0000222 // Verify that we have a location for the right parenthesis.
223 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000224 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000225
Mike Stump1eb44332009-09-09 15:08:12 +0000226 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000227 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
228 parser.CurScope, UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000229}
Eli Friedman99914792009-06-05 00:49:58 +0000230
231// #pragma weak identifier
232// #pragma weak identifier '=' identifier
233void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
234 // FIXME: Should we be expanding macros here? My guess is no.
235 SourceLocation WeakLoc = WeakTok.getLocation();
236
237 Token Tok;
238 PP.Lex(Tok);
239 if (Tok.isNot(tok::identifier)) {
240 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
241 return;
242 }
243
244 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
245 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
246
247 PP.Lex(Tok);
248 if (Tok.is(tok::equal)) {
249 PP.Lex(Tok);
250 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000251 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000252 << "weak";
253 return;
254 }
255 AliasName = Tok.getIdentifierInfo();
256 AliasNameLoc = Tok.getLocation();
257 PP.Lex(Tok);
258 }
259
260 if (Tok.isNot(tok::eom)) {
261 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
262 return;
263 }
264
265 if (AliasName) {
266 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
267 AliasNameLoc);
268 } else {
269 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
270 }
271}