blob: 812d8e2af901d631391545f4dbd9ee5178d0c35b [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();
Mike Stump1eb44332009-09-09 15:08:12 +000040 PP.Lex(Tok);
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000041 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;
Mike Stump1eb44332009-09-09 15:08:12 +000060 }
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000061 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000062
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000063 if (Tok.is(tok::comma)) {
64 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000065
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000066 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);
Mike Stump1eb44332009-09-09 15:08:12 +000075
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000076 if (Tok.is(tok::comma)) {
77 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +000078
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000079 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 }
Mike Stump1eb44332009-09-09 15:08:12 +000083
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +000084 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();
Mike Stump1eb44332009-09-09 15:08:12 +0000118
Ted Kremenek4726d032009-03-23 22:28:25 +0000119 // 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();
Mike Stump1eb44332009-09-09 15:08:12 +0000127
Ted Kremenek4726d032009-03-23 22:28:25 +0000128 // Lex the declaration reference(s).
Ted Kremenek7a02a372009-08-03 23:24:57 +0000129 llvm::SmallVector<Token, 5> Identifiers;
Ted Kremenek4726d032009-03-23 22:28:25 +0000130 SourceLocation RParenLoc;
131 bool LexID = true;
Mike Stump1eb44332009-09-09 15:08:12 +0000132
Ted Kremenek4726d032009-03-23 22:28:25 +0000133 while (true) {
134 PP.Lex(Tok);
Mike Stump1eb44332009-09-09 15:08:12 +0000135
Ted Kremenek4726d032009-03-23 22:28:25 +0000136 if (LexID) {
Mike Stump1eb44332009-09-09 15:08:12 +0000137 if (Tok.is(tok::identifier)) {
Ted Kremenek7a02a372009-08-03 23:24:57 +0000138 Identifiers.push_back(Tok);
Ted Kremenek4726d032009-03-23 22:28:25 +0000139 LexID = false;
140 continue;
141 }
142
Ted Kremenek7a02a372009-08-03 23:24:57 +0000143 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000144 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
145 return;
146 }
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Ted Kremenek4726d032009-03-23 22:28:25 +0000148 // We are execting a ')' or a ','.
149 if (Tok.is(tok::comma)) {
150 LexID = true;
151 continue;
152 }
Mike Stump1eb44332009-09-09 15:08:12 +0000153
Ted Kremenek4726d032009-03-23 22:28:25 +0000154 if (Tok.is(tok::r_paren)) {
155 RParenLoc = Tok.getLocation();
156 break;
157 }
Mike Stump1eb44332009-09-09 15:08:12 +0000158
Ted Kremenek7a02a372009-08-03 23:24:57 +0000159 // Illegal token!
Ted Kremenek4726d032009-03-23 22:28:25 +0000160 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
161 return;
162 }
Eli Friedman99914792009-06-05 00:49:58 +0000163
164 PP.Lex(Tok);
165 if (Tok.isNot(tok::eom)) {
166 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
167 "unused";
168 return;
169 }
170
Ted Kremenek4726d032009-03-23 22:28:25 +0000171 // Verify that we have a location for the right parenthesis.
172 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenek7a02a372009-08-03 23:24:57 +0000173 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenek4726d032009-03-23 22:28:25 +0000174
Mike Stump1eb44332009-09-09 15:08:12 +0000175 // Perform the action to handle the pragma.
Ted Kremenek7a02a372009-08-03 23:24:57 +0000176 Actions.ActOnPragmaUnused(Identifiers.data(), Identifiers.size(),
177 parser.CurScope, UnusedLoc, LParenLoc, RParenLoc);
Ted Kremenek4726d032009-03-23 22:28:25 +0000178}
Eli Friedman99914792009-06-05 00:49:58 +0000179
180// #pragma weak identifier
181// #pragma weak identifier '=' identifier
182void PragmaWeakHandler::HandlePragma(Preprocessor &PP, Token &WeakTok) {
183 // FIXME: Should we be expanding macros here? My guess is no.
184 SourceLocation WeakLoc = WeakTok.getLocation();
185
186 Token Tok;
187 PP.Lex(Tok);
188 if (Tok.isNot(tok::identifier)) {
189 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
190 return;
191 }
192
193 IdentifierInfo *WeakName = Tok.getIdentifierInfo(), *AliasName = 0;
194 SourceLocation WeakNameLoc = Tok.getLocation(), AliasNameLoc;
195
196 PP.Lex(Tok);
197 if (Tok.is(tok::equal)) {
198 PP.Lex(Tok);
199 if (Tok.isNot(tok::identifier)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000200 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedman99914792009-06-05 00:49:58 +0000201 << "weak";
202 return;
203 }
204 AliasName = Tok.getIdentifierInfo();
205 AliasNameLoc = Tok.getLocation();
206 PP.Lex(Tok);
207 }
208
209 if (Tok.isNot(tok::eom)) {
210 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
211 return;
212 }
213
214 if (AliasName) {
215 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, WeakLoc, WeakNameLoc,
216 AliasNameLoc);
217 } else {
218 Actions.ActOnPragmaWeakID(WeakName, WeakLoc, WeakNameLoc);
219 }
220}