blob: ae74d640bf60c9c6358a2c6ea576edcee5fab1c3 [file] [log] [blame]
Chris Lattnerc951dae2006-08-10 04:23:57 +00001//===--- Expression.cpp - Expression Parsing ------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the Expression parsing implementation.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Parse/Parser.h"
15#include "clang/Basic/Diagnostic.h"
16using namespace llvm;
17using namespace clang;
18
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000019// C99 6.7.8
Chris Lattner89c50c62006-08-11 06:41:18 +000020Parser::ExprResult Parser::ParseInitializer() {
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000021 // FIXME: STUB.
Chris Lattnerf5fbd792006-08-10 23:56:11 +000022 if (Tok.getKind() == tok::l_brace) {
23 ConsumeBrace();
Chris Lattnera092cd1f2006-08-11 01:38:28 +000024
25 if (Tok.getKind() == tok::numeric_constant)
26 ConsumeToken();
27
Chris Lattnerf5fbd792006-08-10 23:56:11 +000028 // FIXME: initializer-list
29 // Match the '}'.
30 MatchRHSPunctuation(tok::r_brace, Tok.getLocation(), "{",
31 diag::err_expected_rbrace);
Chris Lattner89c50c62006-08-11 06:41:18 +000032 return ExprResult(false);
Chris Lattnerf5fbd792006-08-10 23:56:11 +000033 }
34
Chris Lattner89c50c62006-08-11 06:41:18 +000035 return ParseAssignmentExpression();
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000036}
37
38
39
Chris Lattner89c50c62006-08-11 06:41:18 +000040Parser::ExprResult Parser::ParseExpression() {
41 return ParseCastExpression(false);
Chris Lattnerc951dae2006-08-10 04:23:57 +000042}
43
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000044// Expr that doesn't include commas.
Chris Lattner89c50c62006-08-11 06:41:18 +000045Parser::ExprResult Parser::ParseAssignmentExpression() {
46 return ParseExpression();
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000047}
48
Chris Lattnereaf06592006-08-11 02:02:23 +000049/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
50/// true, parse a unary-expression.
51///
Chris Lattner4564bc12006-08-10 23:14:52 +000052/// cast-expression: [C99 6.5.4]
53/// unary-expression
54/// '(' type-name ')' cast-expression
Chris Lattner81b576e2006-08-11 02:13:20 +000055///
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000056/// unary-expression: [C99 6.5.3]
57/// postfix-expression
58/// '++' unary-expression
59/// '--' unary-expression
60/// unary-operator cast-expression
61/// 'sizeof' unary-expression
62/// 'sizeof' '(' type-name ')'
63/// [GNU] '__alignof' unary-expression
64/// [GNU] '__alignof' '(' type-name ')'
65/// [GNU] '&&' identifier
Chris Lattner81b576e2006-08-11 02:13:20 +000066///
Chris Lattnerc2dd85a2006-08-10 22:57:16 +000067/// unary-operator: one of
68/// '&' '*' '+' '-' '~' '!'
69/// [GNU] '__extension__' '__real' '__imag'
70///
Chris Lattner52a99e52006-08-10 20:56:00 +000071/// postfix-expression: [C99 6.5.2]
72/// primary-expression
73/// postfix-expression '[' expression ']'
74/// postfix-expression '(' argument-expression-list[opt] ')'
75/// postfix-expression '.' identifier
76/// postfix-expression '->' identifier
77/// postfix-expression '++'
78/// postfix-expression '--'
79/// '(' type-name ')' '{' initializer-list '}'
80/// '(' type-name ')' '{' initializer-list ',' '}'
81///
82/// argument-expression-list: [C99 6.5.2]
83/// argument-expression
84/// argument-expression-list ',' argument-expression
85///
86/// primary-expression: [C99 6.5.1]
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +000087/// identifier
88/// constant
89/// string-literal
90/// '(' expression ')'
Chris Lattner52a99e52006-08-10 20:56:00 +000091/// '__func__' [C99 6.4.2.2]
92/// [GNU] '__FUNCTION__'
93/// [GNU] '__PRETTY_FUNCTION__'
94/// [GNU] '(' compound-statement ')'
95/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
96/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
97/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
98/// assign-expr ')'
99/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
100/// [OBC] '[' objc-receiver objc-message-args ']' [TODO]
101/// [OBC] '@selector' '(' objc-selector-arg ')' [TODO]
102/// [OBC] '@protocol' '(' identifier ')' [TODO]
103/// [OBC] '@encode' '(' type-name ')' [TODO]
104/// [OBC] objc-string-literal [TODO]
105///
106/// constant: [C99 6.4.4]
107/// integer-constant
108/// floating-constant
109/// enumeration-constant -> identifier
110/// character-constant
111///
112/// [GNU] offsetof-member-designator:
113/// [GNU] identifier
114/// [GNU] offsetof-member-designator '.' identifier
115/// [GNU] offsetof-member-designator '[' expression ']'
116///
Chris Lattner81b576e2006-08-11 02:13:20 +0000117///
Chris Lattner89c50c62006-08-11 06:41:18 +0000118Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
119 ExprResult Res;
120
Chris Lattner81b576e2006-08-11 02:13:20 +0000121 // This handles all of cast-expression, unary-expression, postfix-expression,
122 // and primary-expression. We handle them together like this for efficiency
123 // and to simplify handling of an expression starting with a '(' token: which
124 // may be one of a parenthesized expression, cast-expression, compound literal
125 // expression, or statement expression.
126 //
127 // If the parsed tokens consist of a primary-expression, the cases below
128 // 'break' out of the switch. This allows the postfix expression pieces to
129 // be applied to them. Cases that cannot be followed by postfix exprs should
130 // return instead.
Chris Lattner52a99e52006-08-10 20:56:00 +0000131 switch (Tok.getKind()) {
Chris Lattner81b576e2006-08-11 02:13:20 +0000132 case tok::l_paren:
133 // If this expression is limited to being a unary-expression, the parent can
134 // not start a cast expression.
135 ParenParseOption ParenExprType =
136 isUnaryExpression ? CompoundLiteral : CastExpr;
Chris Lattner89c50c62006-08-11 06:41:18 +0000137 Res = ParseParenExpression(ParenExprType);
138 if (Res.isInvalid) return Res;
139
Chris Lattner81b576e2006-08-11 02:13:20 +0000140 switch (ParenExprType) {
141 case SimpleExpr: break; // Nothing else to do.
142 case CompoundStmt: break; // Nothing else to do.
143 case CompoundLiteral:
144 // We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
145 // postfix-expression exist, parse them now.
146 break;
147 case CastExpr:
148 // We parsed '(' type-name ')' and the thing after it wasn't a '{'. Parse
149 // the cast-expression that follows it next.
Chris Lattner89c50c62006-08-11 06:41:18 +0000150 return ParseCastExpression(false);
Chris Lattner81b576e2006-08-11 02:13:20 +0000151 }
152 break; // These can be followed by postfix-expr pieces.
Chris Lattner89c50c62006-08-11 06:41:18 +0000153
Chris Lattner52a99e52006-08-10 20:56:00 +0000154 // primary-expression
155 case tok::identifier: // primary-expression: identifier
156 // constant: enumeration-constant
157 case tok::numeric_constant: // constant: integer-constant
158 // constant: floating-constant
159 case tok::char_constant: // constant: character-constant
160 case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
161 case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
162 case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
163 ConsumeToken();
164 break;
165 case tok::string_literal: // primary-expression: string-literal
Chris Lattner89c50c62006-08-11 06:41:18 +0000166 Res = ParseStringLiteralExpression();
167 if (Res.isInvalid) return Res;
Chris Lattner52a99e52006-08-10 20:56:00 +0000168 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000169 case tok::kw___builtin_va_arg:
170 case tok::kw___builtin_offsetof:
171 case tok::kw___builtin_choose_expr:
172 case tok::kw___builtin_types_compatible_p:
173 assert(0 && "FIXME: UNIMP!");
Chris Lattner81b576e2006-08-11 02:13:20 +0000174 case tok::plusplus: // unary-expression: '++' unary-expression
175 case tok::minusminus: // unary-expression: '--' unary-expression
176 ConsumeToken();
Chris Lattner89c50c62006-08-11 06:41:18 +0000177 return ParseCastExpression(true);
Chris Lattner81b576e2006-08-11 02:13:20 +0000178 case tok::amp: // unary-expression: '&' cast-expression
179 case tok::star: // unary-expression: '*' cast-expression
180 case tok::plus: // unary-expression: '+' cast-expression
181 case tok::minus: // unary-expression: '-' cast-expression
182 case tok::tilde: // unary-expression: '~' cast-expression
183 case tok::exclaim: // unary-expression: '!' cast-expression
184 case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
185 case tok::kw___imag: // unary-expression: '__real' cast-expression [GNU]
186 //case tok::kw__extension__: [TODO]
187 ConsumeToken();
Chris Lattner89c50c62006-08-11 06:41:18 +0000188 return ParseCastExpression(false);
Chris Lattner81b576e2006-08-11 02:13:20 +0000189
190 case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
191 // unary-expression: 'sizeof' '(' type-name ')'
192 case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
193 // unary-expression: '__alignof' '(' type-name ')'
Chris Lattner89c50c62006-08-11 06:41:18 +0000194 return ParseSizeofAlignofExpression();
Chris Lattner81b576e2006-08-11 02:13:20 +0000195 case tok::ampamp: // unary-expression: '&&' identifier
196 Diag(Tok, diag::ext_gnu_address_of_label);
197 ConsumeToken();
198 if (Tok.getKind() == tok::identifier) {
199 ConsumeToken();
200 } else {
201 Diag(Tok, diag::err_expected_ident);
Chris Lattner89c50c62006-08-11 06:41:18 +0000202 return ExprResult(true);
Chris Lattner81b576e2006-08-11 02:13:20 +0000203 }
Chris Lattner89c50c62006-08-11 06:41:18 +0000204 return ExprResult(false);
Chris Lattner52a99e52006-08-10 20:56:00 +0000205 default:
206 Diag(Tok, diag::err_expected_expression);
Chris Lattner89c50c62006-08-11 06:41:18 +0000207 return ExprResult(true);
Chris Lattnerf8339772006-08-10 22:01:51 +0000208 }
209
210 // Now that the primary-expression piece of the postfix-expression has been
211 // parsed, see if there are any postfix-expression pieces here.
212 SourceLocation Loc;
213 while (1) {
214 switch (Tok.getKind()) {
Chris Lattner89c50c62006-08-11 06:41:18 +0000215 default:
216 return ExprResult(false);
217 case tok::l_square: // postfix-expression: p-e '[' expression ']'
218 Loc = Tok.getLocation();
219 ConsumeBracket();
220 ParseExpression();
221 // Match the ']'.
222 MatchRHSPunctuation(tok::r_square, Loc, "[", diag::err_expected_rsquare);
223 break;
224
225 case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
226 Loc = Tok.getLocation();
227 ConsumeParen();
228
229 while (1) {
230 // FIXME: This should be argument-expression!
231 ParseAssignmentExpression();
Chris Lattner81b576e2006-08-11 02:13:20 +0000232
Chris Lattner89c50c62006-08-11 06:41:18 +0000233 if (Tok.getKind() != tok::comma)
234 break;
235 ConsumeToken(); // Next argument.
236 }
Chris Lattner81b576e2006-08-11 02:13:20 +0000237
Chris Lattner89c50c62006-08-11 06:41:18 +0000238 // Match the ')'.
239 MatchRHSPunctuation(tok::r_paren, Loc, "(", diag::err_expected_rparen);
240 break;
241
242 case tok::arrow: // postfix-expression: p-e '->' identifier
243 case tok::period: // postfix-expression: p-e '.' identifier
244 ConsumeToken();
245 if (Tok.getKind() != tok::identifier) {
246 Diag(Tok, diag::err_expected_ident);
247 return ExprResult(true);
248 }
249 ConsumeToken();
250 break;
251
252 case tok::plusplus: // postfix-expression: postfix-expression '++'
253 case tok::minusminus: // postfix-expression: postfix-expression '--'
254 ConsumeToken();
255 break;
Chris Lattnerf8339772006-08-10 22:01:51 +0000256 }
257 }
Chris Lattner52a99e52006-08-10 20:56:00 +0000258}
259
Chris Lattner81b576e2006-08-11 02:13:20 +0000260/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
261/// unary-expression: [C99 6.5.3]
262/// 'sizeof' unary-expression
263/// 'sizeof' '(' type-name ')'
264/// [GNU] '__alignof' unary-expression
265/// [GNU] '__alignof' '(' type-name ')'
Chris Lattner89c50c62006-08-11 06:41:18 +0000266Parser::ExprResult Parser::ParseSizeofAlignofExpression() {
Chris Lattner81b576e2006-08-11 02:13:20 +0000267 assert((Tok.getKind() == tok::kw_sizeof ||
268 Tok.getKind() == tok::kw___alignof) &&
269 "Not a sizeof/alignof expression!");
270 ConsumeToken();
271
272 // If the operand doesn't start with an '(', it must be an expression.
273 if (Tok.getKind() != tok::l_paren) {
Chris Lattner89c50c62006-08-11 06:41:18 +0000274 return ParseCastExpression(true);
Chris Lattner81b576e2006-08-11 02:13:20 +0000275 }
276
277 // If it starts with a '(', we know that it is either a parenthesized
278 // type-name, or it is a unary-expression that starts with a compound literal,
279 // or starts with a primary-expression that is a parenthesized expression.
280 ParenParseOption ExprType = CastExpr;
Chris Lattner89c50c62006-08-11 06:41:18 +0000281 return ParseParenExpression(ExprType);
Chris Lattner81b576e2006-08-11 02:13:20 +0000282}
283
Chris Lattner52a99e52006-08-10 20:56:00 +0000284/// ParseStringLiteralExpression - This handles the various token types that
285/// form string literals, and also handles string concatenation [C99 5.1.1.2,
286/// translation phase #6].
287///
288/// primary-expression: [C99 6.5.1]
289/// string-literal
Chris Lattner89c50c62006-08-11 06:41:18 +0000290Parser::ExprResult Parser::ParseStringLiteralExpression() {
Chris Lattner4564bc12006-08-10 23:14:52 +0000291 assert(isTokenStringLiteral() && "Not a string literal!");
Chris Lattner52a99e52006-08-10 20:56:00 +0000292 ConsumeStringToken();
293
294 // String concat. Note that keywords like __func__ and __FUNCTION__ aren't
295 // considered to be strings.
Chris Lattner4564bc12006-08-10 23:14:52 +0000296 while (isTokenStringLiteral())
Chris Lattner52a99e52006-08-10 20:56:00 +0000297 ConsumeStringToken();
Chris Lattner89c50c62006-08-11 06:41:18 +0000298 return ExprResult(false);
Chris Lattner52a99e52006-08-10 20:56:00 +0000299}
Chris Lattnerc5e0d4a2006-08-10 19:06:03 +0000300
Chris Lattnerc951dae2006-08-10 04:23:57 +0000301
Chris Lattner4add4e62006-08-11 01:33:00 +0000302/// ParseParenExpression - This parses the unit that starts with a '(' token,
303/// based on what is allowed by ExprType. The actual thing parsed is returned
304/// in ExprType.
305///
306/// primary-expression: [C99 6.5.1]
Chris Lattnerc951dae2006-08-10 04:23:57 +0000307/// '(' expression ')'
Chris Lattnerf8339772006-08-10 22:01:51 +0000308/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
309/// postfix-expression: [C99 6.5.2]
310/// '(' type-name ')' '{' initializer-list '}'
311/// '(' type-name ')' '{' initializer-list ',' '}'
Chris Lattner4add4e62006-08-11 01:33:00 +0000312/// cast-expression: [C99 6.5.4]
313/// '(' type-name ')' cast-expression
Chris Lattnerf8339772006-08-10 22:01:51 +0000314///
Chris Lattner89c50c62006-08-11 06:41:18 +0000315Parser::ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType) {
Chris Lattnerc951dae2006-08-10 04:23:57 +0000316 assert(Tok.getKind() == tok::l_paren && "Not a paren expr!");
317 SourceLocation OpenLoc = Tok.getLocation();
318 ConsumeParen();
Chris Lattner89c50c62006-08-11 06:41:18 +0000319 ExprResult Result(false);
Chris Lattnerc951dae2006-08-10 04:23:57 +0000320
Chris Lattner4add4e62006-08-11 01:33:00 +0000321 if (ExprType >= CompoundStmt && Tok.getKind() == tok::l_brace &&
Chris Lattnerf8339772006-08-10 22:01:51 +0000322 !getLang().NoExtensions) {
323 Diag(Tok, diag::ext_gnu_statement_expr);
324 ParseCompoundStatement();
Chris Lattner4add4e62006-08-11 01:33:00 +0000325 ExprType = CompoundStmt;
326 } else if (ExprType >= CompoundLiteral && isTypeSpecifierQualifier()) {
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000327 // Otherwise, this is a compound expression.
328 ParseTypeName();
329
330 // Match the ')'.
331 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
332
Chris Lattner4add4e62006-08-11 01:33:00 +0000333 if (Tok.getKind() == tok::l_brace) {
Chris Lattner89c50c62006-08-11 06:41:18 +0000334 Result = ParseInitializer();
Chris Lattner4add4e62006-08-11 01:33:00 +0000335 ExprType = CompoundLiteral;
336 } else if (ExprType == CastExpr) {
337 // Note that this doesn't parse the subsequence cast-expression.
338 ExprType = CastExpr;
339 } else {
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000340 Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
Chris Lattner89c50c62006-08-11 06:41:18 +0000341 return ExprResult(true);
Chris Lattnerf5fbd792006-08-10 23:56:11 +0000342 }
Chris Lattner89c50c62006-08-11 06:41:18 +0000343 return Result;
Chris Lattner4add4e62006-08-11 01:33:00 +0000344 } else {
Chris Lattner89c50c62006-08-11 06:41:18 +0000345 Result = ParseExpression();
Chris Lattner4add4e62006-08-11 01:33:00 +0000346 ExprType = SimpleExpr;
Chris Lattnerf8339772006-08-10 22:01:51 +0000347 }
Chris Lattnerc951dae2006-08-10 04:23:57 +0000348
Chris Lattner4564bc12006-08-10 23:14:52 +0000349 // Match the ')'.
Chris Lattner89c50c62006-08-11 06:41:18 +0000350 if (Result.isInvalid)
351 SkipUntil(tok::r_paren);
352 else
353 MatchRHSPunctuation(tok::r_paren, OpenLoc, "(", diag::err_expected_rparen);
354 return Result;
Chris Lattnerc951dae2006-08-10 04:23:57 +0000355}