blob: 58c729aef29e6961d9d1896a9e0179fa29fca761 [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) {
26 // FIXME: Should we be expanding macros here? My guess is no.
27 SourceLocation PackLoc = PackTok.getLocation();
28
29 Token Tok;
30 PP.Lex(Tok);
31 if (Tok.isNot(tok::l_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000032 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000033 return;
34 }
35
36 Action::PragmaPackKind Kind = Action::PPK_Default;
37 IdentifierInfo *Name = 0;
Sebastian Redl15faa7f2008-12-09 20:22:58 +000038 Action::OwningExprResult Alignment(Actions);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000039 SourceLocation LParenLoc = Tok.getLocation();
40 PP.Lex(Tok);
41 if (Tok.is(tok::numeric_constant)) {
42 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000043 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000044 return;
45
46 PP.Lex(Tok);
47 } else if (Tok.is(tok::identifier)) {
48 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattner08631c52008-11-23 21:45:46 +000049 if (II->isStr("show")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000050 Kind = Action::PPK_Show;
51 PP.Lex(Tok);
52 } else {
Chris Lattner08631c52008-11-23 21:45:46 +000053 if (II->isStr("push")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000054 Kind = Action::PPK_Push;
Chris Lattner08631c52008-11-23 21:45:46 +000055 } else if (II->isStr("pop")) {
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000056 Kind = Action::PPK_Pop;
57 } else {
58 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_invalid_action);
59 return;
60 }
61 PP.Lex(Tok);
62
63 if (Tok.is(tok::comma)) {
64 PP.Lex(Tok);
65
66 if (Tok.is(tok::numeric_constant)) {
67 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000068 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000069 return;
70
71 PP.Lex(Tok);
72 } else if (Tok.is(tok::identifier)) {
73 Name = Tok.getIdentifierInfo();
74 PP.Lex(Tok);
75
76 if (Tok.is(tok::comma)) {
77 PP.Lex(Tok);
78
79 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattner08631c52008-11-23 21:45:46 +000080 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000081 return;
82 }
83
84 Alignment = Actions.ActOnNumericConstant(Tok);
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000085 if (Alignment.isInvalid())
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000086 return;
87
88 PP.Lex(Tok);
89 }
90 } else {
Chris Lattner08631c52008-11-23 21:45:46 +000091 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000092 return;
93 }
94 }
95 }
Sebastian Redl0e9eabc2008-12-09 13:15:23 +000096 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000097
98 if (Tok.isNot(tok::r_paren)) {
Ted Kremenek4726d032009-03-23 22:28:25 +000099 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000100 return;
101 }
102
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
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000109 SourceLocation RParenLoc = Tok.getLocation();
Sebastian Redleffa8d12008-12-10 00:02:53 +0000110 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000111 LParenLoc, RParenLoc);
112}
113
Ted Kremenek4726d032009-03-23 22:28:25 +0000114// #pragma unused(identifier)
115void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
116 // FIXME: Should we be expanding macros here? My guess is no.
117 SourceLocation UnusedLoc = UnusedTok.getLocation();
118
119 // Lex the left '('.
120 Token Tok;
121 PP.Lex(Tok);
122 if (Tok.isNot(tok::l_paren)) {
123 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
124 return;
125 }
126 SourceLocation LParenLoc = Tok.getLocation();
127
128 // Lex the declaration reference(s).
129 llvm::SmallVector<Action::ExprTy*, 5> Ex;
130 SourceLocation RParenLoc;
131 bool LexID = true;
132
133 while (true) {
134 PP.Lex(Tok);
135
136 if (LexID) {
137 if (Tok.is(tok::identifier)) {
138 Action::OwningExprResult Name =
139 Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(),
140 *Tok.getIdentifierInfo(), false);
141
142 if (Name.isInvalid()) {
143 if (!Ex.empty())
144 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
145 return;
146 }
147
148 Ex.push_back(Name.release());
149 LexID = false;
150 continue;
151 }
152
153 // Illegal token! Release the parsed expressions (if any) and emit
154 // a warning.
155 if (!Ex.empty())
156 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
157
158 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
159 return;
160 }
161
162 // We are execting a ')' or a ','.
163 if (Tok.is(tok::comma)) {
164 LexID = true;
165 continue;
166 }
167
168 if (Tok.is(tok::r_paren)) {
169 RParenLoc = Tok.getLocation();
170 break;
171 }
172
173 // Illegal token! Release the parsed expressions (if any) and emit
174 // a warning.
175 if (!Ex.empty())
176 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
177
178 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
179 return;
180 }
Eli Friedman99914792009-06-05 00:49:58 +0000181
182 PP.Lex(Tok);
183 if (Tok.isNot(tok::eom)) {
184 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
185 "unused";
186 return;
187 }
188
Ted Kremenek4726d032009-03-23 22:28:25 +0000189 // Verify that we have a location for the right parenthesis.
190 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
191 assert(!Ex.empty() && "Valid '#pragma unused' must have arguments");
192
193 // Perform the action to handle the pragma.
194 Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc);
195}
Eli Friedman99914792009-06-05 00:49:58 +0000196
197// #pragma weak identifier
198// #pragma weak identifier '=' identifier
199void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
200 // FIXME: Should we be expanding macros here? My guess is no.
201 SourceLocation WeakLoc = WeakTok.getLocation();
202
203 Token Tok;
204 PP.Lex(Tok);
205 if (Tok.isNot(tok::identifier)) {
206 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
207 return;
208 }
209
210 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
211 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
212
213 PP.Lex(Tok);
214 if (Tok.is(tok::equal)) {
215 PP.Lex(Tok);
216 if (Tok.isNot(tok::identifier)) {
217 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
218 << "weak";
219 return;
220 }
221 AliasName = Tok.getIdentifierInfo();
222 AliasNameLoc = Tok.getLocation();
223 PP.Lex(Tok);
224 }
225
226 if (Tok.isNot(tok::eom)) {
227 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
228 return;
229 }
230
231 if (AliasName) {
232 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
233 AliasNameLoc);
234 } else {
235 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
236 }
237}