blob: 94695e4d5694e356efb3ce12a8232c167e847999 [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
103 SourceLocation RParenLoc = Tok.getLocation();
Sebastian Redleffa8d12008-12-10 00:02:53 +0000104 Actions.ActOnPragmaPack(Kind, Name, Alignment.release(), PackLoc,
Daniel Dunbarfcdd8fe2008-10-04 19:21:03 +0000105 LParenLoc, RParenLoc);
106}
107
Ted Kremenek4726d032009-03-23 22:28:25 +0000108// #pragma unused(identifier)
109void PragmaUnusedHandler::HandlePragma(Preprocessor &PP, Token &UnusedTok) {
110 // FIXME: Should we be expanding macros here? My guess is no.
111 SourceLocation UnusedLoc = UnusedTok.getLocation();
112
113 // Lex the left '('.
114 Token Tok;
115 PP.Lex(Tok);
116 if (Tok.isNot(tok::l_paren)) {
117 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
118 return;
119 }
120 SourceLocation LParenLoc = Tok.getLocation();
121
122 // Lex the declaration reference(s).
123 llvm::SmallVector<Action::ExprTy*, 5> Ex;
124 SourceLocation RParenLoc;
125 bool LexID = true;
126
127 while (true) {
128 PP.Lex(Tok);
129
130 if (LexID) {
131 if (Tok.is(tok::identifier)) {
132 Action::OwningExprResult Name =
133 Actions.ActOnIdentifierExpr(parser.CurScope, Tok.getLocation(),
134 *Tok.getIdentifierInfo(), false);
135
136 if (Name.isInvalid()) {
137 if (!Ex.empty())
138 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
139 return;
140 }
141
142 Ex.push_back(Name.release());
143 LexID = false;
144 continue;
145 }
146
147 // Illegal token! Release the parsed expressions (if any) and emit
148 // a warning.
149 if (!Ex.empty())
150 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
151
152 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
153 return;
154 }
155
156 // We are execting a ')' or a ','.
157 if (Tok.is(tok::comma)) {
158 LexID = true;
159 continue;
160 }
161
162 if (Tok.is(tok::r_paren)) {
163 RParenLoc = Tok.getLocation();
164 break;
165 }
166
167 // Illegal token! Release the parsed expressions (if any) and emit
168 // a warning.
169 if (!Ex.empty())
170 Action::MultiExprArg Release(Actions, &Ex[0], Ex.size());
171
172 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_punc);
173 return;
174 }
175
176 // Verify that we have a location for the right parenthesis.
177 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
178 assert(!Ex.empty() && "Valid '#pragma unused' must have arguments");
179
180 // Perform the action to handle the pragma.
181 Actions.ActOnPragmaUnused(&Ex[0], Ex.size(), UnusedLoc, LParenLoc, RParenLoc);
182}