2006-11-05 15:46:30 +08:00
|
|
|
//===--- ParseExpr.cpp - Expression Parsing -------------------------------===//
|
2006-08-10 12:23:57 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 03:59:25 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2006-08-10 12:23:57 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2006-08-12 16:13:25 +08:00
|
|
|
// This file implements the Expression parsing implementation. Expressions in
|
|
|
|
// C99 basically consist of a bunch of binary operators with unary operators and
|
|
|
|
// other random stuff at the leaves.
|
|
|
|
//
|
|
|
|
// In the C99 grammar, these unary operators bind tightest and are represented
|
|
|
|
// as the 'cast-expression' production. Everything else is either a binary
|
2006-08-13 00:45:01 +08:00
|
|
|
// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are
|
2006-08-12 16:13:25 +08:00
|
|
|
// handled by ParseCastExpression, the higher level pieces are handled by
|
|
|
|
// ParseBinaryExpression.
|
2006-08-10 12:23:57 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Parse/Parser.h"
|
2008-08-22 23:38:55 +08:00
|
|
|
#include "clang/Parse/DeclSpec.h"
|
2008-08-29 03:20:44 +08:00
|
|
|
#include "clang/Parse/Scope.h"
|
2009-03-05 15:32:12 +08:00
|
|
|
#include "clang/Basic/PrettyStackTrace.h"
|
2008-10-20 14:45:43 +08:00
|
|
|
#include "ExtensionRAIIObject.h"
|
2008-11-26 06:21:31 +08:00
|
|
|
#include "AstGuard.h"
|
2006-08-24 11:51:22 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2006-11-03 15:48:41 +08:00
|
|
|
#include "llvm/ADT/SmallString.h"
|
2006-08-10 12:23:57 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2006-08-13 00:45:01 +08:00
|
|
|
/// PrecedenceLevels - These are precedences for the binary/ternary operators in
|
2006-08-12 16:13:25 +08:00
|
|
|
/// the C99 grammar. These have been named to relate with the C99 grammar
|
|
|
|
/// productions. Low precedences numbers bind more weakly than high numbers.
|
|
|
|
namespace prec {
|
|
|
|
enum Level {
|
2009-02-07 08:15:38 +08:00
|
|
|
Unknown = 0, // Not binary operator.
|
|
|
|
Comma = 1, // ,
|
|
|
|
Assignment = 2, // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
|
|
|
|
Conditional = 3, // ?
|
|
|
|
LogicalOr = 4, // ||
|
|
|
|
LogicalAnd = 5, // &&
|
|
|
|
InclusiveOr = 6, // |
|
|
|
|
ExclusiveOr = 7, // ^
|
|
|
|
And = 8, // &
|
|
|
|
Equality = 9, // ==, !=
|
|
|
|
Relational = 10, // >=, <=, >, <
|
|
|
|
Shift = 11, // <<, >>
|
|
|
|
Additive = 12, // -, +
|
|
|
|
Multiplicative = 13, // *, /, %
|
|
|
|
PointerToMember = 14 // .*, ->*
|
2006-08-12 16:13:25 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// getBinOpPrecedence - Return the precedence of the specified binary operator
|
|
|
|
/// token. This returns:
|
|
|
|
///
|
2009-02-10 02:46:07 +08:00
|
|
|
static prec::Level getBinOpPrecedence(tok::TokenKind Kind,
|
2009-02-26 07:02:36 +08:00
|
|
|
bool GreaterThanIsOperator,
|
|
|
|
bool CPlusPlus0x) {
|
2006-08-12 16:13:25 +08:00
|
|
|
switch (Kind) {
|
2009-02-10 02:46:07 +08:00
|
|
|
case tok::greater:
|
2009-02-26 07:02:36 +08:00
|
|
|
// C++ [temp.names]p3:
|
|
|
|
// [...] When parsing a template-argument-list, the first
|
|
|
|
// non-nested > is taken as the ending delimiter rather than a
|
|
|
|
// greater-than operator. [...]
|
2009-02-10 02:46:07 +08:00
|
|
|
if (GreaterThanIsOperator)
|
|
|
|
return prec::Relational;
|
|
|
|
return prec::Unknown;
|
|
|
|
|
2009-02-26 07:02:36 +08:00
|
|
|
case tok::greatergreater:
|
|
|
|
// C++0x [temp.names]p3:
|
|
|
|
//
|
|
|
|
// [...] Similarly, the first non-nested >> is treated as two
|
|
|
|
// consecutive but distinct > tokens, the first of which is
|
|
|
|
// taken as the end of the template-argument-list and completes
|
|
|
|
// the template-id. [...]
|
|
|
|
if (GreaterThanIsOperator || !CPlusPlus0x)
|
|
|
|
return prec::Shift;
|
|
|
|
return prec::Unknown;
|
|
|
|
|
2006-08-12 16:13:25 +08:00
|
|
|
default: return prec::Unknown;
|
|
|
|
case tok::comma: return prec::Comma;
|
|
|
|
case tok::equal:
|
|
|
|
case tok::starequal:
|
|
|
|
case tok::slashequal:
|
|
|
|
case tok::percentequal:
|
|
|
|
case tok::plusequal:
|
|
|
|
case tok::minusequal:
|
|
|
|
case tok::lesslessequal:
|
|
|
|
case tok::greatergreaterequal:
|
|
|
|
case tok::ampequal:
|
|
|
|
case tok::caretequal:
|
|
|
|
case tok::pipeequal: return prec::Assignment;
|
|
|
|
case tok::question: return prec::Conditional;
|
|
|
|
case tok::pipepipe: return prec::LogicalOr;
|
|
|
|
case tok::ampamp: return prec::LogicalAnd;
|
|
|
|
case tok::pipe: return prec::InclusiveOr;
|
|
|
|
case tok::caret: return prec::ExclusiveOr;
|
|
|
|
case tok::amp: return prec::And;
|
|
|
|
case tok::exclaimequal:
|
|
|
|
case tok::equalequal: return prec::Equality;
|
|
|
|
case tok::lessequal:
|
|
|
|
case tok::less:
|
2009-02-10 02:46:07 +08:00
|
|
|
case tok::greaterequal: return prec::Relational;
|
2009-02-26 07:02:36 +08:00
|
|
|
case tok::lessless: return prec::Shift;
|
2006-08-12 16:13:25 +08:00
|
|
|
case tok::plus:
|
|
|
|
case tok::minus: return prec::Additive;
|
|
|
|
case tok::percent:
|
|
|
|
case tok::slash:
|
|
|
|
case tok::star: return prec::Multiplicative;
|
2009-02-07 08:15:38 +08:00
|
|
|
case tok::periodstar:
|
|
|
|
case tok::arrowstar: return prec::PointerToMember;
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-08-13 01:22:40 +08:00
|
|
|
/// ParseExpression - Simple precedence-based parser for binary/ternary
|
2006-08-12 16:13:25 +08:00
|
|
|
/// operators.
|
|
|
|
///
|
2006-08-13 00:45:01 +08:00
|
|
|
/// Note: we diverge from the C99 grammar when parsing the assignment-expression
|
|
|
|
/// production. C99 specifies that the LHS of an assignment operator should be
|
|
|
|
/// parsed as a unary-expression, but consistency dictates that it be a
|
|
|
|
/// conditional-expession. In practice, the important thing here is that the
|
|
|
|
/// LHS of an assignment has to be an l-value, which productions between
|
|
|
|
/// unary-expression and conditional-expression don't produce. Because we want
|
|
|
|
/// consistency, we parse the LHS as a conditional-expression, then check for
|
|
|
|
/// l-value-ness in semantic analysis stages.
|
|
|
|
///
|
2009-02-07 08:15:38 +08:00
|
|
|
/// pm-expression: [C++ 5.5]
|
|
|
|
/// cast-expression
|
|
|
|
/// pm-expression '.*' cast-expression
|
|
|
|
/// pm-expression '->*' cast-expression
|
|
|
|
///
|
2006-08-12 16:13:25 +08:00
|
|
|
/// multiplicative-expression: [C99 6.5.5]
|
2009-02-07 08:15:38 +08:00
|
|
|
/// Note: in C++, apply pm-expression instead of cast-expression
|
2006-08-12 16:13:25 +08:00
|
|
|
/// cast-expression
|
|
|
|
/// multiplicative-expression '*' cast-expression
|
|
|
|
/// multiplicative-expression '/' cast-expression
|
|
|
|
/// multiplicative-expression '%' cast-expression
|
|
|
|
///
|
|
|
|
/// additive-expression: [C99 6.5.6]
|
|
|
|
/// multiplicative-expression
|
|
|
|
/// additive-expression '+' multiplicative-expression
|
|
|
|
/// additive-expression '-' multiplicative-expression
|
|
|
|
///
|
|
|
|
/// shift-expression: [C99 6.5.7]
|
|
|
|
/// additive-expression
|
|
|
|
/// shift-expression '<<' additive-expression
|
|
|
|
/// shift-expression '>>' additive-expression
|
|
|
|
///
|
|
|
|
/// relational-expression: [C99 6.5.8]
|
|
|
|
/// shift-expression
|
|
|
|
/// relational-expression '<' shift-expression
|
|
|
|
/// relational-expression '>' shift-expression
|
|
|
|
/// relational-expression '<=' shift-expression
|
|
|
|
/// relational-expression '>=' shift-expression
|
|
|
|
///
|
|
|
|
/// equality-expression: [C99 6.5.9]
|
|
|
|
/// relational-expression
|
|
|
|
/// equality-expression '==' relational-expression
|
|
|
|
/// equality-expression '!=' relational-expression
|
|
|
|
///
|
|
|
|
/// AND-expression: [C99 6.5.10]
|
|
|
|
/// equality-expression
|
|
|
|
/// AND-expression '&' equality-expression
|
|
|
|
///
|
|
|
|
/// exclusive-OR-expression: [C99 6.5.11]
|
|
|
|
/// AND-expression
|
|
|
|
/// exclusive-OR-expression '^' AND-expression
|
|
|
|
///
|
|
|
|
/// inclusive-OR-expression: [C99 6.5.12]
|
|
|
|
/// exclusive-OR-expression
|
|
|
|
/// inclusive-OR-expression '|' exclusive-OR-expression
|
|
|
|
///
|
|
|
|
/// logical-AND-expression: [C99 6.5.13]
|
|
|
|
/// inclusive-OR-expression
|
|
|
|
/// logical-AND-expression '&&' inclusive-OR-expression
|
|
|
|
///
|
|
|
|
/// logical-OR-expression: [C99 6.5.14]
|
|
|
|
/// logical-AND-expression
|
|
|
|
/// logical-OR-expression '||' logical-AND-expression
|
|
|
|
///
|
|
|
|
/// conditional-expression: [C99 6.5.15]
|
|
|
|
/// logical-OR-expression
|
|
|
|
/// logical-OR-expression '?' expression ':' conditional-expression
|
|
|
|
/// [GNU] logical-OR-expression '?' ':' conditional-expression
|
2009-04-17 01:51:27 +08:00
|
|
|
/// [C++] the third operand is an assignment-expression
|
2006-08-12 16:13:25 +08:00
|
|
|
///
|
|
|
|
/// assignment-expression: [C99 6.5.16]
|
|
|
|
/// conditional-expression
|
|
|
|
/// unary-expression assignment-operator assignment-expression
|
2008-02-26 08:51:44 +08:00
|
|
|
/// [C++] throw-expression [C++ 15]
|
2006-08-12 16:13:25 +08:00
|
|
|
///
|
|
|
|
/// assignment-operator: one of
|
|
|
|
/// = *= /= %= += -= <<= >>= &= ^= |=
|
|
|
|
///
|
|
|
|
/// expression: [C99 6.5.17]
|
|
|
|
/// assignment-expression
|
|
|
|
/// expression ',' assignment-expression
|
|
|
|
///
|
2008-12-12 05:36:32 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseExpression() {
|
2009-05-16 05:47:08 +08:00
|
|
|
OwningExprResult LHS(ParseAssignmentExpression());
|
2008-12-12 05:36:32 +08:00
|
|
|
if (LHS.isInvalid()) return move(LHS);
|
|
|
|
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
|
|
|
|
2007-09-20 03:14:32 +08:00
|
|
|
/// This routine is called when the '@' is seen and consumed.
|
|
|
|
/// Current token is an Identifier and is not a 'try'. This
|
2007-10-04 06:03:06 +08:00
|
|
|
/// routine is necessary to disambiguate @try-statement from,
|
|
|
|
/// for example, @encode-expression.
|
2007-09-20 03:14:32 +08:00
|
|
|
///
|
2008-12-12 06:33:27 +08:00
|
|
|
Parser::OwningExprResult
|
|
|
|
Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
|
2008-12-13 23:32:12 +08:00
|
|
|
OwningExprResult LHS(ParseObjCAtExpression(AtLoc));
|
2008-12-12 06:33:27 +08:00
|
|
|
if (LHS.isInvalid()) return move(LHS);
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
|
2007-09-20 03:14:32 +08:00
|
|
|
}
|
|
|
|
|
2009-01-27 16:43:38 +08:00
|
|
|
/// This routine is called when a leading '__extension__' is seen and
|
|
|
|
/// consumed. This is necessary because the token gets consumed in the
|
|
|
|
/// process of disambiguating between an expression and a declaration.
|
|
|
|
Parser::OwningExprResult
|
|
|
|
Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
|
2009-05-17 07:40:44 +08:00
|
|
|
OwningExprResult LHS(Actions, true);
|
|
|
|
{
|
|
|
|
// Silence extension warnings in the sub-expression
|
|
|
|
ExtensionRAIIObject O(Diags);
|
|
|
|
|
|
|
|
LHS = ParseCastExpression(false);
|
|
|
|
if (LHS.isInvalid()) return move(LHS);
|
|
|
|
}
|
2009-01-27 16:43:38 +08:00
|
|
|
|
|
|
|
LHS = Actions.ActOnUnaryOp(CurScope, ExtLoc, tok::kw___extension__,
|
2009-02-05 23:02:23 +08:00
|
|
|
move(LHS));
|
2009-01-27 16:43:38 +08:00
|
|
|
if (LHS.isInvalid()) return move(LHS);
|
|
|
|
|
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
|
|
|
|
}
|
|
|
|
|
2006-08-13 02:12:45 +08:00
|
|
|
/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
|
|
|
|
///
|
2008-12-12 05:36:32 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseAssignmentExpression() {
|
2008-02-26 08:51:44 +08:00
|
|
|
if (Tok.is(tok::kw_throw))
|
2008-12-12 06:51:44 +08:00
|
|
|
return ParseThrowExpression();
|
2008-02-26 08:51:44 +08:00
|
|
|
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult LHS(ParseCastExpression(false));
|
|
|
|
if (LHS.isInvalid()) return move(LHS);
|
|
|
|
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment);
|
2006-08-13 01:22:40 +08:00
|
|
|
}
|
|
|
|
|
2008-06-03 05:31:07 +08:00
|
|
|
/// ParseAssignmentExprWithObjCMessageExprStart - Parse an assignment expression
|
|
|
|
/// where part of an objc message send has already been parsed. In this case
|
|
|
|
/// LBracLoc indicates the location of the '[' of the message send, and either
|
|
|
|
/// ReceiverName or ReceiverExpr is non-null indicating the receiver of the
|
|
|
|
/// message.
|
|
|
|
///
|
|
|
|
/// Since this handles full assignment-expression's, it handles postfix
|
|
|
|
/// expressions and other binary operators for these expressions as well.
|
2008-12-13 23:32:12 +08:00
|
|
|
Parser::OwningExprResult
|
2008-06-03 05:31:07 +08:00
|
|
|
Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
|
2008-11-19 23:54:23 +08:00
|
|
|
SourceLocation NameLoc,
|
2008-06-03 05:31:07 +08:00
|
|
|
IdentifierInfo *ReceiverName,
|
2008-12-13 23:32:12 +08:00
|
|
|
ExprArg ReceiverExpr) {
|
|
|
|
OwningExprResult R(ParseObjCMessageExpressionBody(LBracLoc, NameLoc,
|
|
|
|
ReceiverName,
|
|
|
|
move(ReceiverExpr)));
|
|
|
|
if (R.isInvalid()) return move(R);
|
2008-12-12 05:36:32 +08:00
|
|
|
R = ParsePostfixExpressionSuffix(move(R));
|
2008-12-13 23:32:12 +08:00
|
|
|
if (R.isInvalid()) return move(R);
|
|
|
|
return ParseRHSOfBinaryExpression(move(R), prec::Assignment);
|
2008-06-03 05:31:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-12 05:36:32 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseConstantExpression() {
|
|
|
|
OwningExprResult LHS(ParseCastExpression(false));
|
|
|
|
if (LHS.isInvalid()) return move(LHS);
|
|
|
|
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Conditional);
|
2006-08-13 08:12:11 +08:00
|
|
|
}
|
|
|
|
|
2006-08-12 16:13:25 +08:00
|
|
|
/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with
|
|
|
|
/// LHS and has a precedence of at least MinPrec.
|
2008-12-12 06:33:27 +08:00
|
|
|
Parser::OwningExprResult
|
|
|
|
Parser::ParseRHSOfBinaryExpression(OwningExprResult LHS, unsigned MinPrec) {
|
2009-02-26 07:02:36 +08:00
|
|
|
unsigned NextTokPrec = getBinOpPrecedence(Tok.getKind(),
|
|
|
|
GreaterThanIsOperator,
|
|
|
|
getLang().CPlusPlus0x);
|
2006-08-23 13:17:46 +08:00
|
|
|
SourceLocation ColonLoc;
|
|
|
|
|
2006-08-12 16:13:25 +08:00
|
|
|
while (1) {
|
|
|
|
// If this token has a lower precedence than we are allowed to parse (e.g.
|
|
|
|
// because we are called recursively, or because the token is not a binop),
|
|
|
|
// then we are done!
|
2008-12-09 21:15:23 +08:00
|
|
|
if (NextTokPrec < MinPrec)
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(LHS);
|
2006-08-12 16:13:25 +08:00
|
|
|
|
|
|
|
// Consume the operator, saving the operator token for error reporting.
|
2007-07-21 00:59:19 +08:00
|
|
|
Token OpToken = Tok;
|
2006-08-12 16:13:25 +08:00
|
|
|
ConsumeToken();
|
2009-02-07 08:15:38 +08:00
|
|
|
|
2006-08-13 01:13:08 +08:00
|
|
|
// Special case handling for the ternary operator.
|
2008-12-10 04:22:58 +08:00
|
|
|
OwningExprResult TernaryMiddle(Actions, true);
|
2006-08-13 01:13:08 +08:00
|
|
|
if (NextTokPrec == prec::Conditional) {
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::colon)) {
|
2006-08-13 01:13:08 +08:00
|
|
|
// Handle this production specially:
|
|
|
|
// logical-OR-expression '?' expression ':' conditional-expression
|
|
|
|
// In particular, the RHS of the '?' is 'expression', not
|
|
|
|
// 'logical-OR-expression' as we might expect.
|
|
|
|
TernaryMiddle = ParseExpression();
|
2008-12-09 21:15:23 +08:00
|
|
|
if (TernaryMiddle.isInvalid())
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(TernaryMiddle);
|
2006-08-13 01:13:08 +08:00
|
|
|
} else {
|
|
|
|
// Special case handling of "X ? Y : Z" where Y is empty:
|
|
|
|
// logical-OR-expression '?' ':' conditional-expression [GNU]
|
2008-12-10 04:22:58 +08:00
|
|
|
TernaryMiddle = 0;
|
2006-08-13 01:13:08 +08:00
|
|
|
Diag(Tok, diag::ext_gnu_conditional_expr);
|
|
|
|
}
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::colon)) {
|
2006-08-13 01:13:08 +08:00
|
|
|
Diag(Tok, diag::err_expected_colon);
|
2008-11-24 07:17:07 +08:00
|
|
|
Diag(OpToken, diag::note_matching) << "?";
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2006-08-13 01:13:08 +08:00
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2006-08-13 01:13:08 +08:00
|
|
|
// Eat the colon.
|
2006-10-16 14:06:51 +08:00
|
|
|
ColonLoc = ConsumeToken();
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2006-08-13 01:13:08 +08:00
|
|
|
// Parse another leaf here for the RHS of the operator.
|
2009-04-17 01:51:27 +08:00
|
|
|
// ParseCastExpression works here because all RHS expressions in C have it
|
|
|
|
// as a prefix, at least. However, in C++, an assignment-expression could
|
|
|
|
// be a throw-expression, which is not a valid cast-expression.
|
|
|
|
// Therefore we need some special-casing here.
|
|
|
|
// Also note that the third operand of the conditional operator is
|
|
|
|
// an assignment-expression in C++.
|
|
|
|
OwningExprResult RHS(Actions);
|
|
|
|
if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
|
|
|
|
RHS = ParseAssignmentExpression();
|
|
|
|
else
|
|
|
|
RHS = ParseCastExpression(false);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (RHS.isInvalid())
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(RHS);
|
2006-08-12 16:13:25 +08:00
|
|
|
|
|
|
|
// Remember the precedence of this operator and get the precedence of the
|
|
|
|
// operator immediately to the right of the RHS.
|
|
|
|
unsigned ThisPrec = NextTokPrec;
|
2009-02-26 07:02:36 +08:00
|
|
|
NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
|
|
|
|
getLang().CPlusPlus0x);
|
2006-08-13 01:18:19 +08:00
|
|
|
|
|
|
|
// Assignment and conditional expressions are right-associative.
|
2007-12-18 14:06:23 +08:00
|
|
|
bool isRightAssoc = ThisPrec == prec::Conditional ||
|
|
|
|
ThisPrec == prec::Assignment;
|
2006-08-12 16:13:25 +08:00
|
|
|
|
|
|
|
// Get the precedence of the operator to the right of the RHS. If it binds
|
|
|
|
// more tightly with RHS than we do, evaluate it completely first.
|
|
|
|
if (ThisPrec < NextTokPrec ||
|
|
|
|
(ThisPrec == NextTokPrec && isRightAssoc)) {
|
2006-08-13 01:18:19 +08:00
|
|
|
// If this is left-associative, only parse things on the RHS that bind
|
|
|
|
// more tightly than the current operator. If it is left-associative, it
|
|
|
|
// is okay, to bind exactly as tightly. For example, compile A=B=C=D as
|
|
|
|
// A=(B=(C=D)), where each paren is a level of recursion here.
|
2008-11-26 06:21:31 +08:00
|
|
|
// The function takes ownership of the RHS.
|
2008-12-12 06:33:27 +08:00
|
|
|
RHS = ParseRHSOfBinaryExpression(move(RHS), ThisPrec + !isRightAssoc);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (RHS.isInvalid())
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(RHS);
|
2006-08-12 16:13:25 +08:00
|
|
|
|
2009-02-26 07:02:36 +08:00
|
|
|
NextTokPrec = getBinOpPrecedence(Tok.getKind(), GreaterThanIsOperator,
|
|
|
|
getLang().CPlusPlus0x);
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
|
|
|
assert(NextTokPrec <= ThisPrec && "Recursion didn't work!");
|
2008-11-26 06:21:31 +08:00
|
|
|
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!LHS.isInvalid()) {
|
2007-08-31 13:01:50 +08:00
|
|
|
// Combine the LHS and RHS into the LHS (e.g. build AST).
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
if (TernaryMiddle.isInvalid()) {
|
|
|
|
// If we're using '>>' as an operator within a template
|
|
|
|
// argument list (in C++98), suggest the addition of
|
|
|
|
// parentheses so that the code remains well-formed in C++0x.
|
|
|
|
if (!GreaterThanIsOperator && OpToken.is(tok::greatergreater))
|
|
|
|
SuggestParentheses(OpToken.getLocation(),
|
|
|
|
diag::warn_cxx0x_right_shift_in_template_arg,
|
|
|
|
SourceRange(Actions.getExprRange(LHS.get()).getBegin(),
|
|
|
|
Actions.getExprRange(RHS.get()).getEnd()));
|
|
|
|
|
2008-12-10 08:02:53 +08:00
|
|
|
LHS = Actions.ActOnBinOp(CurScope, OpToken.getLocation(),
|
2009-02-05 23:02:23 +08:00
|
|
|
OpToken.getKind(), move(LHS), move(RHS));
|
Introduce code modification hints into the diagnostics system. When we
know how to recover from an error, we can attach a hint to the
diagnostic that states how to modify the code, which can be one of:
- Insert some new code (a text string) at a particular source
location
- Remove the code within a given range
- Replace the code within a given range with some new code (a text
string)
Right now, we use these hints to annotate diagnostic information. For
example, if one uses the '>>' in a template argument in C++98, as in
this code:
template<int I> class B { };
B<1000 >> 2> *b1;
we'll warn that the behavior will change in C++0x. The fix is to
insert parenthese, so we use code insertion annotations to illustrate
where the parentheses go:
test.cpp:10:10: warning: use of right-shift operator ('>>') in template
argument will require parentheses in C++0x
B<1000 >> 2> *b1;
^
( )
Use of these annotations is partially implemented for HTML
diagnostics, but it's not (yet) producing valid HTML, which may be
related to PR2386, so it has been #if 0'd out.
In this future, we could consider hooking this mechanism up to the
rewriter to actually try to fix these problems during compilation (or,
after a compilation whose only errors have fixes). For now, however, I
suggest that we use these code modification hints whenever we can, so
that we get better diagnostics now and will have better coverage when
we find better ways to use this information.
This also fixes PR3410 by placing the complaint about missing tokens
just after the previous token (rather than at the location of the next
token).
llvm-svn: 65570
2009-02-27 05:00:50 +08:00
|
|
|
} else
|
2007-09-16 11:34:24 +08:00
|
|
|
LHS = Actions.ActOnConditionalOp(OpToken.getLocation(), ColonLoc,
|
2009-02-05 23:02:23 +08:00
|
|
|
move(LHS), move(TernaryMiddle),
|
|
|
|
move(RHS));
|
2007-08-31 13:01:50 +08:00
|
|
|
}
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-11 10:02:23 +08:00
|
|
|
/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
|
2009-02-04 04:19:35 +08:00
|
|
|
/// true, parse a unary-expression. isAddressOfOperand exists because an
|
|
|
|
/// id-expression that is the operand of address-of gets special treatment
|
|
|
|
/// due to member pointers.
|
2006-08-11 10:02:23 +08:00
|
|
|
///
|
2006-08-11 07:14:52 +08:00
|
|
|
/// cast-expression: [C99 6.5.4]
|
|
|
|
/// unary-expression
|
|
|
|
/// '(' type-name ')' cast-expression
|
2006-08-11 10:13:20 +08:00
|
|
|
///
|
2006-08-11 06:57:16 +08:00
|
|
|
/// unary-expression: [C99 6.5.3]
|
|
|
|
/// postfix-expression
|
|
|
|
/// '++' unary-expression
|
|
|
|
/// '--' unary-expression
|
|
|
|
/// unary-operator cast-expression
|
|
|
|
/// 'sizeof' unary-expression
|
|
|
|
/// 'sizeof' '(' type-name ')'
|
|
|
|
/// [GNU] '__alignof' unary-expression
|
|
|
|
/// [GNU] '__alignof' '(' type-name ')'
|
2008-11-06 23:17:27 +08:00
|
|
|
/// [C++0x] 'alignof' '(' type-id ')'
|
2006-08-11 06:57:16 +08:00
|
|
|
/// [GNU] '&&' identifier
|
2008-11-22 03:14:01 +08:00
|
|
|
/// [C++] new-expression
|
|
|
|
/// [C++] delete-expression
|
2006-08-11 10:13:20 +08:00
|
|
|
///
|
2006-08-11 06:57:16 +08:00
|
|
|
/// unary-operator: one of
|
|
|
|
/// '&' '*' '+' '-' '~' '!'
|
|
|
|
/// [GNU] '__extension__' '__real' '__imag'
|
|
|
|
///
|
2006-08-11 04:56:00 +08:00
|
|
|
/// primary-expression: [C99 6.5.1]
|
2008-11-07 06:13:31 +08:00
|
|
|
/// [C99] identifier
|
2008-11-11 19:37:55 +08:00
|
|
|
/// [C++] id-expression
|
2006-08-11 03:06:03 +08:00
|
|
|
/// constant
|
|
|
|
/// string-literal
|
2007-02-13 09:51:42 +08:00
|
|
|
/// [C++] boolean-literal [C++ 2.13.5]
|
2009-05-11 02:38:11 +08:00
|
|
|
/// [C++0x] 'nullptr' [C++0x 2.14.7]
|
2006-08-11 03:06:03 +08:00
|
|
|
/// '(' expression ')'
|
2006-08-11 04:56:00 +08:00
|
|
|
/// '__func__' [C99 6.4.2.2]
|
|
|
|
/// [GNU] '__FUNCTION__'
|
|
|
|
/// [GNU] '__PRETTY_FUNCTION__'
|
|
|
|
/// [GNU] '(' compound-statement ')'
|
|
|
|
/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
|
|
|
|
/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
|
|
|
|
/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
|
|
|
|
/// assign-expr ')'
|
|
|
|
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
|
2008-11-29 12:51:27 +08:00
|
|
|
/// [GNU] '__null'
|
2007-09-27 01:03:44 +08:00
|
|
|
/// [OBJC] '[' objc-message-expr ']'
|
2008-01-26 02:58:06 +08:00
|
|
|
/// [OBJC] '@selector' '(' objc-selector-arg ')'
|
2007-09-27 01:03:44 +08:00
|
|
|
/// [OBJC] '@protocol' '(' identifier ')'
|
|
|
|
/// [OBJC] '@encode' '(' type-name ')'
|
2007-09-06 03:52:07 +08:00
|
|
|
/// [OBJC] objc-string-literal
|
2008-08-22 23:38:55 +08:00
|
|
|
/// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
|
|
|
|
/// [C++] typename-specifier '(' expression-list[opt] ')' [TODO]
|
2007-06-30 02:21:34 +08:00
|
|
|
/// [C++] 'const_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
|
|
|
|
/// [C++] 'dynamic_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
|
|
|
|
/// [C++] 'reinterpret_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
|
|
|
|
/// [C++] 'static_cast' '<' type-name '>' '(' expression ')' [C++ 5.2p1]
|
2008-11-11 19:37:55 +08:00
|
|
|
/// [C++] 'typeid' '(' expression ')' [C++ 5.2p1]
|
|
|
|
/// [C++] 'typeid' '(' type-id ')' [C++ 5.2p1]
|
2008-07-16 15:23:27 +08:00
|
|
|
/// [C++] 'this' [C++ 9.3.2]
|
2009-01-06 04:52:13 +08:00
|
|
|
/// [G++] unary-type-trait '(' type-id ')'
|
|
|
|
/// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO]
|
2008-08-29 03:20:44 +08:00
|
|
|
/// [clang] '^' block-literal
|
2006-08-11 04:56:00 +08:00
|
|
|
///
|
|
|
|
/// constant: [C99 6.4.4]
|
|
|
|
/// integer-constant
|
|
|
|
/// floating-constant
|
|
|
|
/// enumeration-constant -> identifier
|
|
|
|
/// character-constant
|
|
|
|
///
|
2008-11-07 06:13:31 +08:00
|
|
|
/// id-expression: [C++ 5.1]
|
|
|
|
/// unqualified-id
|
|
|
|
/// qualified-id [TODO]
|
|
|
|
///
|
|
|
|
/// unqualified-id: [C++ 5.1]
|
|
|
|
/// identifier
|
|
|
|
/// operator-function-id
|
|
|
|
/// conversion-function-id [TODO]
|
|
|
|
/// '~' class-name [TODO]
|
|
|
|
/// template-id [TODO]
|
2008-11-09 00:45:02 +08:00
|
|
|
///
|
2008-11-22 03:14:01 +08:00
|
|
|
/// new-expression: [C++ 5.3.4]
|
|
|
|
/// '::'[opt] 'new' new-placement[opt] new-type-id
|
|
|
|
/// new-initializer[opt]
|
|
|
|
/// '::'[opt] 'new' new-placement[opt] '(' type-id ')'
|
|
|
|
/// new-initializer[opt]
|
|
|
|
///
|
|
|
|
/// delete-expression: [C++ 5.3.5]
|
|
|
|
/// '::'[opt] 'delete' cast-expression
|
|
|
|
/// '::'[opt] 'delete' '[' ']' cast-expression
|
|
|
|
///
|
2009-01-06 04:52:13 +08:00
|
|
|
/// [GNU] unary-type-trait:
|
|
|
|
/// '__has_nothrow_assign' [TODO]
|
|
|
|
/// '__has_nothrow_copy' [TODO]
|
|
|
|
/// '__has_nothrow_constructor' [TODO]
|
|
|
|
/// '__has_trivial_assign' [TODO]
|
|
|
|
/// '__has_trivial_copy' [TODO]
|
2009-04-16 08:08:20 +08:00
|
|
|
/// '__has_trivial_constructor'
|
2009-04-17 10:34:54 +08:00
|
|
|
/// '__has_trivial_destructor'
|
2009-01-06 04:52:13 +08:00
|
|
|
/// '__has_virtual_destructor' [TODO]
|
|
|
|
/// '__is_abstract' [TODO]
|
|
|
|
/// '__is_class'
|
|
|
|
/// '__is_empty' [TODO]
|
|
|
|
/// '__is_enum'
|
|
|
|
/// '__is_pod'
|
|
|
|
/// '__is_polymorphic'
|
|
|
|
/// '__is_union'
|
|
|
|
///
|
|
|
|
/// [GNU] binary-type-trait:
|
|
|
|
/// '__is_base_of' [TODO]
|
|
|
|
///
|
2009-02-04 04:19:35 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|
|
|
bool isAddressOfOperand) {
|
2008-12-10 04:22:58 +08:00
|
|
|
OwningExprResult Res(Actions);
|
2006-10-25 11:38:23 +08:00
|
|
|
tok::TokenKind SavedKind = Tok.getKind();
|
2006-08-11 14:41:18 +08:00
|
|
|
|
2006-08-11 10:13:20 +08:00
|
|
|
// This handles all of cast-expression, unary-expression, postfix-expression,
|
|
|
|
// and primary-expression. We handle them together like this for efficiency
|
|
|
|
// and to simplify handling of an expression starting with a '(' token: which
|
|
|
|
// may be one of a parenthesized expression, cast-expression, compound literal
|
|
|
|
// expression, or statement expression.
|
|
|
|
//
|
|
|
|
// If the parsed tokens consist of a primary-expression, the cases below
|
2006-08-13 01:40:43 +08:00
|
|
|
// call ParsePostfixExpressionSuffix to handle the postfix expression
|
|
|
|
// suffixes. Cases that cannot be followed by postfix exprs should
|
|
|
|
// return without invoking ParsePostfixExpressionSuffix.
|
2006-10-25 11:49:28 +08:00
|
|
|
switch (SavedKind) {
|
2006-08-24 14:37:51 +08:00
|
|
|
case tok::l_paren: {
|
2006-08-11 10:13:20 +08:00
|
|
|
// If this expression is limited to being a unary-expression, the parent can
|
|
|
|
// not start a cast expression.
|
|
|
|
ParenParseOption ParenExprType =
|
|
|
|
isUnaryExpression ? CompoundLiteral : CastExpr;
|
2006-08-24 14:37:51 +08:00
|
|
|
TypeTy *CastTy;
|
|
|
|
SourceLocation LParenLoc = Tok.getLocation();
|
|
|
|
SourceLocation RParenLoc;
|
|
|
|
Res = ParseParenExpression(ParenExprType, CastTy, RParenLoc);
|
2008-12-12 05:36:32 +08:00
|
|
|
if (Res.isInvalid()) return move(Res);
|
2006-08-11 14:41:18 +08:00
|
|
|
|
2006-08-11 10:13:20 +08:00
|
|
|
switch (ParenExprType) {
|
|
|
|
case SimpleExpr: break; // Nothing else to do.
|
|
|
|
case CompoundStmt: break; // Nothing else to do.
|
|
|
|
case CompoundLiteral:
|
|
|
|
// We parsed '(' type-name ')' '{' ... '}'. If any suffixes of
|
|
|
|
// postfix-expression exist, parse them now.
|
|
|
|
break;
|
|
|
|
case CastExpr:
|
|
|
|
// We parsed '(' type-name ')' and the thing after it wasn't a '{'. Parse
|
|
|
|
// the cast-expression that follows it next.
|
2006-08-24 14:37:51 +08:00
|
|
|
// TODO: For cast expression with CastTy.
|
|
|
|
Res = ParseCastExpression(false);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Res.isInvalid())
|
2009-02-05 23:02:23 +08:00
|
|
|
Res = Actions.ActOnCastExpr(LParenLoc, CastTy, RParenLoc, move(Res));
|
2008-12-12 05:36:32 +08:00
|
|
|
return move(Res);
|
2006-08-11 10:13:20 +08:00
|
|
|
}
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2006-08-13 01:40:43 +08:00
|
|
|
// These can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-08-24 14:37:51 +08:00
|
|
|
}
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2006-08-11 04:56:00 +08:00
|
|
|
// primary-expression
|
2006-08-23 13:17:46 +08:00
|
|
|
case tok::numeric_constant:
|
|
|
|
// constant: integer-constant
|
|
|
|
// constant: floating-constant
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2007-09-16 11:34:24 +08:00
|
|
|
Res = Actions.ActOnNumericConstant(Tok);
|
2006-08-23 13:17:46 +08:00
|
|
|
ConsumeToken();
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2006-08-23 13:17:46 +08:00
|
|
|
// These can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-08-23 13:17:46 +08:00
|
|
|
|
2007-02-13 09:51:42 +08:00
|
|
|
case tok::kw_true:
|
|
|
|
case tok::kw_false:
|
2008-12-12 06:51:44 +08:00
|
|
|
return ParseCXXBoolLiteral();
|
2007-02-13 09:51:42 +08:00
|
|
|
|
2009-05-11 02:38:11 +08:00
|
|
|
case tok::kw_nullptr:
|
|
|
|
return Actions.ActOnCXXNullPtrLiteral(ConsumeToken());
|
|
|
|
|
2008-11-09 00:45:02 +08:00
|
|
|
case tok::identifier: { // primary-expression: identifier
|
|
|
|
// unqualified-id: identifier
|
|
|
|
// constant: enumeration-constant
|
2009-01-06 13:06:21 +08:00
|
|
|
// Turn a potentially qualified name into a annot_typename or
|
2009-01-05 06:52:14 +08:00
|
|
|
// annot_cxxscope if it would be valid. This handles things like x::y, etc.
|
2009-01-05 07:23:14 +08:00
|
|
|
if (getLang().CPlusPlus) {
|
2009-01-05 07:46:59 +08:00
|
|
|
// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
|
|
|
|
if (TryAnnotateTypeOrScopeToken())
|
2009-02-04 04:19:35 +08:00
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
|
2009-01-05 07:23:14 +08:00
|
|
|
}
|
2008-08-22 23:38:55 +08:00
|
|
|
|
2009-03-10 05:12:44 +08:00
|
|
|
// Support 'Class.property' notation.
|
|
|
|
// We don't use isTokObjCMessageIdentifierReceiver(), since it allows
|
|
|
|
// 'super' (which is inappropriate here).
|
|
|
|
if (getLang().ObjC1 &&
|
|
|
|
Actions.getTypeName(*Tok.getIdentifierInfo(),
|
|
|
|
Tok.getLocation(), CurScope) &&
|
|
|
|
NextToken().is(tok::period)) {
|
|
|
|
IdentifierInfo &ReceiverName = *Tok.getIdentifierInfo();
|
|
|
|
SourceLocation IdentLoc = ConsumeToken();
|
|
|
|
SourceLocation DotLoc = ConsumeToken();
|
|
|
|
|
|
|
|
if (Tok.isNot(tok::identifier)) {
|
|
|
|
Diag(Tok, diag::err_expected_ident);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
|
|
|
|
SourceLocation PropertyLoc = ConsumeToken();
|
|
|
|
|
|
|
|
Res = Actions.ActOnClassPropertyRefExpr(ReceiverName, PropertyName,
|
|
|
|
IdentLoc, PropertyLoc);
|
2009-04-03 02:37:59 +08:00
|
|
|
// These can be followed by postfix-expr pieces.
|
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2009-03-10 05:12:44 +08:00
|
|
|
}
|
2006-11-20 14:49:47 +08:00
|
|
|
// Consume the identifier so that we can see if it is followed by a '('.
|
|
|
|
// Function designators are allowed to be undeclared (C99 6.5.1p2), so we
|
|
|
|
// need to know whether or not this identifier is a function designator or
|
|
|
|
// not.
|
|
|
|
IdentifierInfo &II = *Tok.getIdentifierInfo();
|
|
|
|
SourceLocation L = ConsumeToken();
|
2007-10-10 01:41:39 +08:00
|
|
|
Res = Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren));
|
2006-11-20 12:58:19 +08:00
|
|
|
// These can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-11-20 14:49:47 +08:00
|
|
|
}
|
2006-08-11 04:56:00 +08:00
|
|
|
case tok::char_constant: // constant: character-constant
|
2007-09-16 11:34:24 +08:00
|
|
|
Res = Actions.ActOnCharacterConstant(Tok);
|
2007-04-27 04:39:23 +08:00
|
|
|
ConsumeToken();
|
|
|
|
// These can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-08-11 04:56:00 +08:00
|
|
|
case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2]
|
|
|
|
case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU]
|
|
|
|
case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU]
|
2008-08-10 09:53:14 +08:00
|
|
|
Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind);
|
2006-08-11 04:56:00 +08:00
|
|
|
ConsumeToken();
|
2006-08-13 01:40:43 +08:00
|
|
|
// These can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-08-11 04:56:00 +08:00
|
|
|
case tok::string_literal: // primary-expression: string-literal
|
2006-10-06 13:22:26 +08:00
|
|
|
case tok::wide_string_literal:
|
2006-08-11 14:41:18 +08:00
|
|
|
Res = ParseStringLiteralExpression();
|
2008-12-12 05:36:32 +08:00
|
|
|
if (Res.isInvalid()) return move(Res);
|
2006-08-13 01:40:43 +08:00
|
|
|
// This can be followed by postfix-expr pieces (e.g. "foo"[1]).
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-08-11 06:01:51 +08:00
|
|
|
case tok::kw___builtin_va_arg:
|
|
|
|
case tok::kw___builtin_offsetof:
|
|
|
|
case tok::kw___builtin_choose_expr:
|
|
|
|
case tok::kw___builtin_types_compatible_p:
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseBuiltinPrimaryExpression();
|
2008-11-29 12:51:27 +08:00
|
|
|
case tok::kw___null:
|
2009-03-16 01:47:39 +08:00
|
|
|
return Actions.ActOnGNUNullExpr(ConsumeToken());
|
2008-11-29 12:51:27 +08:00
|
|
|
break;
|
2006-08-11 10:13:20 +08:00
|
|
|
case tok::plusplus: // unary-expression: '++' unary-expression
|
2006-10-25 11:38:23 +08:00
|
|
|
case tok::minusminus: { // unary-expression: '--' unary-expression
|
|
|
|
SourceLocation SavedLoc = ConsumeToken();
|
2006-08-23 14:42:10 +08:00
|
|
|
Res = ParseCastExpression(true);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Res.isInvalid())
|
2009-02-05 23:02:23 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
|
2008-12-12 05:36:32 +08:00
|
|
|
return move(Res);
|
2006-10-25 11:38:23 +08:00
|
|
|
}
|
2009-02-04 04:19:35 +08:00
|
|
|
case tok::amp: { // unary-expression: '&' cast-expression
|
|
|
|
// Special treatment because of member pointers
|
|
|
|
SourceLocation SavedLoc = ConsumeToken();
|
|
|
|
Res = ParseCastExpression(false, true);
|
|
|
|
if (!Res.isInvalid())
|
2009-02-05 23:02:23 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
|
2009-02-04 04:19:35 +08:00
|
|
|
return move(Res);
|
|
|
|
}
|
|
|
|
|
2006-08-11 10:13:20 +08:00
|
|
|
case tok::star: // unary-expression: '*' cast-expression
|
|
|
|
case tok::plus: // unary-expression: '+' cast-expression
|
|
|
|
case tok::minus: // unary-expression: '-' cast-expression
|
|
|
|
case tok::tilde: // unary-expression: '~' cast-expression
|
|
|
|
case tok::exclaim: // unary-expression: '!' cast-expression
|
|
|
|
case tok::kw___real: // unary-expression: '__real' cast-expression [GNU]
|
2008-02-03 04:20:10 +08:00
|
|
|
case tok::kw___imag: { // unary-expression: '__imag' cast-expression [GNU]
|
|
|
|
SourceLocation SavedLoc = ConsumeToken();
|
|
|
|
Res = ParseCastExpression(false);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Res.isInvalid())
|
2009-02-05 23:02:23 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
|
2008-12-12 05:36:32 +08:00
|
|
|
return move(Res);
|
2008-12-09 21:15:23 +08:00
|
|
|
}
|
|
|
|
|
2006-10-25 11:38:23 +08:00
|
|
|
case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU]
|
2008-02-03 04:20:10 +08:00
|
|
|
// __extension__ silences extension warnings in the subexpression.
|
2008-10-20 14:45:43 +08:00
|
|
|
ExtensionRAIIObject O(Diags); // Use RAII to do this.
|
2006-10-25 11:38:23 +08:00
|
|
|
SourceLocation SavedLoc = ConsumeToken();
|
2006-08-23 14:42:10 +08:00
|
|
|
Res = ParseCastExpression(false);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Res.isInvalid())
|
2009-02-05 23:02:23 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move(Res));
|
2008-12-12 05:36:32 +08:00
|
|
|
return move(Res);
|
2006-10-25 11:38:23 +08:00
|
|
|
}
|
2006-08-11 10:13:20 +08:00
|
|
|
case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression
|
|
|
|
// unary-expression: 'sizeof' '(' type-name ')'
|
2008-11-06 23:17:27 +08:00
|
|
|
case tok::kw_alignof:
|
2006-08-11 10:13:20 +08:00
|
|
|
case tok::kw___alignof: // unary-expression: '__alignof' unary-expression
|
|
|
|
// unary-expression: '__alignof' '(' type-name ')'
|
2008-11-06 23:17:27 +08:00
|
|
|
// unary-expression: 'alignof' '(' type-id ')'
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseSizeofAlignofExpression();
|
2006-10-25 11:38:23 +08:00
|
|
|
case tok::ampamp: { // unary-expression: '&&' identifier
|
2007-05-28 14:56:27 +08:00
|
|
|
SourceLocation AmpAmpLoc = ConsumeToken();
|
2008-12-12 05:36:32 +08:00
|
|
|
if (Tok.isNot(tok::identifier))
|
|
|
|
return ExprError(Diag(Tok, diag::err_expected_ident));
|
2008-12-10 08:02:53 +08:00
|
|
|
|
2007-05-28 14:56:27 +08:00
|
|
|
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
|
2007-09-16 22:56:35 +08:00
|
|
|
Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(),
|
2007-05-28 14:56:27 +08:00
|
|
|
Tok.getIdentifierInfo());
|
2006-10-16 06:33:58 +08:00
|
|
|
ConsumeToken();
|
2008-12-12 05:36:32 +08:00
|
|
|
return move(Res);
|
2006-10-25 11:38:23 +08:00
|
|
|
}
|
2006-12-05 02:06:35 +08:00
|
|
|
case tok::kw_const_cast:
|
|
|
|
case tok::kw_dynamic_cast:
|
|
|
|
case tok::kw_reinterpret_cast:
|
|
|
|
case tok::kw_static_cast:
|
2008-08-17 03:45:32 +08:00
|
|
|
Res = ParseCXXCasts();
|
|
|
|
// These can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2008-11-11 19:37:55 +08:00
|
|
|
case tok::kw_typeid:
|
|
|
|
Res = ParseCXXTypeid();
|
|
|
|
// This can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2008-06-25 06:12:16 +08:00
|
|
|
case tok::kw_this:
|
2008-08-17 03:34:46 +08:00
|
|
|
Res = ParseCXXThis();
|
|
|
|
// This can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2008-08-22 23:38:55 +08:00
|
|
|
|
|
|
|
case tok::kw_char:
|
|
|
|
case tok::kw_wchar_t:
|
|
|
|
case tok::kw_bool:
|
|
|
|
case tok::kw_short:
|
|
|
|
case tok::kw_int:
|
|
|
|
case tok::kw_long:
|
|
|
|
case tok::kw_signed:
|
|
|
|
case tok::kw_unsigned:
|
|
|
|
case tok::kw_float:
|
|
|
|
case tok::kw_double:
|
|
|
|
case tok::kw_void:
|
2009-03-28 07:10:48 +08:00
|
|
|
case tok::kw_typename:
|
2009-01-05 06:28:21 +08:00
|
|
|
case tok::kw_typeof:
|
2009-01-06 13:06:21 +08:00
|
|
|
case tok::annot_typename: {
|
2009-01-05 06:28:21 +08:00
|
|
|
if (!getLang().CPlusPlus) {
|
|
|
|
Diag(Tok, diag::err_expected_expression);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
2008-08-22 23:38:55 +08:00
|
|
|
// postfix-expression: simple-type-specifier '(' expression-list[opt] ')'
|
|
|
|
//
|
|
|
|
DeclSpec DS;
|
|
|
|
ParseCXXSimpleTypeSpecifier(DS);
|
|
|
|
if (Tok.isNot(tok::l_paren))
|
2008-12-12 05:36:32 +08:00
|
|
|
return ExprError(Diag(Tok, diag::err_expected_lparen_after_type)
|
|
|
|
<< DS.getSourceRange());
|
2008-08-22 23:38:55 +08:00
|
|
|
|
|
|
|
Res = ParseCXXTypeConstructExpression(DS);
|
|
|
|
// This can be followed by postfix-expr pieces.
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2008-08-22 23:38:55 +08:00
|
|
|
}
|
|
|
|
|
2008-11-09 00:45:02 +08:00
|
|
|
case tok::annot_cxxscope: // [C++] id-expression: qualified-id
|
|
|
|
case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
|
|
|
|
// template-id
|
2009-02-04 04:19:35 +08:00
|
|
|
Res = ParseCXXIdExpression(isAddressOfOperand);
|
2008-12-12 05:36:32 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2008-11-07 06:13:31 +08:00
|
|
|
|
2009-01-05 06:52:14 +08:00
|
|
|
case tok::coloncolon: {
|
2009-01-05 11:55:46 +08:00
|
|
|
// ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken
|
|
|
|
// annotates the token, tail recurse.
|
|
|
|
if (TryAnnotateTypeOrScopeToken())
|
2009-02-04 04:19:35 +08:00
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
|
|
|
|
|
2009-01-05 06:52:14 +08:00
|
|
|
// ::new -> [C++] new-expression
|
|
|
|
// ::delete -> [C++] delete-expression
|
2009-01-05 11:55:46 +08:00
|
|
|
SourceLocation CCLoc = ConsumeToken();
|
2009-01-05 05:25:24 +08:00
|
|
|
if (Tok.is(tok::kw_new))
|
2009-01-05 11:55:46 +08:00
|
|
|
return ParseCXXNewExpression(true, CCLoc);
|
2009-01-05 06:52:14 +08:00
|
|
|
if (Tok.is(tok::kw_delete))
|
2009-01-05 11:55:46 +08:00
|
|
|
return ParseCXXDeleteExpression(true, CCLoc);
|
|
|
|
|
2009-01-05 07:23:14 +08:00
|
|
|
// This is not a type name or scope specifier, it is an invalid expression.
|
2009-01-05 11:55:46 +08:00
|
|
|
Diag(CCLoc, diag::err_expected_expression);
|
2009-01-05 07:23:14 +08:00
|
|
|
return ExprError();
|
2009-01-05 05:25:24 +08:00
|
|
|
}
|
2008-12-03 00:35:44 +08:00
|
|
|
|
2008-11-22 03:14:01 +08:00
|
|
|
case tok::kw_new: // [C++] new-expression
|
2009-01-05 05:25:24 +08:00
|
|
|
return ParseCXXNewExpression(false, Tok.getLocation());
|
2008-11-22 03:14:01 +08:00
|
|
|
|
|
|
|
case tok::kw_delete: // [C++] delete-expression
|
2009-01-05 05:25:24 +08:00
|
|
|
return ParseCXXDeleteExpression(false, Tok.getLocation());
|
2008-11-22 03:14:01 +08:00
|
|
|
|
2009-01-06 04:52:13 +08:00
|
|
|
case tok::kw___is_pod: // [GNU] unary-type-trait
|
|
|
|
case tok::kw___is_class:
|
|
|
|
case tok::kw___is_enum:
|
|
|
|
case tok::kw___is_union:
|
|
|
|
case tok::kw___is_polymorphic:
|
2009-03-22 09:52:17 +08:00
|
|
|
case tok::kw___is_abstract:
|
2009-04-16 08:08:20 +08:00
|
|
|
case tok::kw___has_trivial_constructor:
|
2009-04-17 10:34:54 +08:00
|
|
|
case tok::kw___has_trivial_destructor:
|
2009-01-06 04:52:13 +08:00
|
|
|
return ParseUnaryTypeTrait();
|
|
|
|
|
2007-10-04 06:03:06 +08:00
|
|
|
case tok::at: {
|
|
|
|
SourceLocation AtLoc = ConsumeToken();
|
2008-12-13 23:32:12 +08:00
|
|
|
return ParseObjCAtExpression(AtLoc);
|
2007-10-04 06:03:06 +08:00
|
|
|
}
|
2008-08-29 03:20:44 +08:00
|
|
|
case tok::caret:
|
2009-03-27 12:18:06 +08:00
|
|
|
return ParsePostfixExpressionSuffix(ParseBlockLiteralExpression());
|
2008-12-13 03:20:14 +08:00
|
|
|
case tok::l_square:
|
|
|
|
// These can be followed by postfix-expr pieces.
|
|
|
|
if (getLang().ObjC1)
|
2008-12-13 23:32:12 +08:00
|
|
|
return ParsePostfixExpressionSuffix(ParseObjCMessageExpression());
|
2009-01-05 06:28:21 +08:00
|
|
|
// FALL THROUGH.
|
2006-08-11 04:56:00 +08:00
|
|
|
default:
|
|
|
|
Diag(Tok, diag::err_expected_expression);
|
2008-12-12 05:36:32 +08:00
|
|
|
return ExprError();
|
2006-08-11 06:01:51 +08:00
|
|
|
}
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2006-08-13 01:40:43 +08:00
|
|
|
// unreachable.
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression
|
|
|
|
/// is parsed, this method parses any suffixes that apply.
|
|
|
|
///
|
|
|
|
/// postfix-expression: [C99 6.5.2]
|
|
|
|
/// primary-expression
|
|
|
|
/// postfix-expression '[' expression ']'
|
|
|
|
/// postfix-expression '(' argument-expression-list[opt] ')'
|
|
|
|
/// postfix-expression '.' identifier
|
|
|
|
/// postfix-expression '->' identifier
|
|
|
|
/// postfix-expression '++'
|
|
|
|
/// postfix-expression '--'
|
|
|
|
/// '(' type-name ')' '{' initializer-list '}'
|
|
|
|
/// '(' type-name ')' '{' initializer-list ',' '}'
|
|
|
|
///
|
|
|
|
/// argument-expression-list: [C99 6.5.2]
|
|
|
|
/// argument-expression
|
|
|
|
/// argument-expression-list ',' assignment-expression
|
|
|
|
///
|
2008-12-12 05:36:32 +08:00
|
|
|
Parser::OwningExprResult
|
|
|
|
Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
|
2006-08-11 06:01:51 +08:00
|
|
|
// Now that the primary-expression piece of the postfix-expression has been
|
|
|
|
// parsed, see if there are any postfix-expression pieces here.
|
|
|
|
SourceLocation Loc;
|
|
|
|
while (1) {
|
|
|
|
switch (Tok.getKind()) {
|
2006-08-13 01:40:43 +08:00
|
|
|
default: // Not a postfix-expression suffix.
|
2008-12-12 05:36:32 +08:00
|
|
|
return move(LHS);
|
2006-08-24 11:51:22 +08:00
|
|
|
case tok::l_square: { // postfix-expression: p-e '[' expression ']'
|
2006-10-16 14:12:55 +08:00
|
|
|
Loc = ConsumeBracket();
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult Idx(ParseExpression());
|
2008-11-26 06:21:31 +08:00
|
|
|
|
2006-08-24 11:51:22 +08:00
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
2008-12-09 21:15:23 +08:00
|
|
|
|
|
|
|
if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) {
|
2009-02-05 23:02:23 +08:00
|
|
|
LHS = Actions.ActOnArraySubscriptExpr(CurScope, move(LHS), Loc,
|
|
|
|
move(Idx), RLoc);
|
2008-12-09 21:15:23 +08:00
|
|
|
} else
|
2008-12-12 05:36:32 +08:00
|
|
|
LHS = ExprError();
|
2006-08-24 11:51:22 +08:00
|
|
|
|
2006-08-11 14:41:18 +08:00
|
|
|
// Match the ']'.
|
2006-08-15 12:55:54 +08:00
|
|
|
MatchRHSPunctuation(tok::r_square, Loc);
|
2006-08-11 14:41:18 +08:00
|
|
|
break;
|
2006-08-24 11:51:22 +08:00
|
|
|
}
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2006-08-24 11:51:22 +08:00
|
|
|
case tok::l_paren: { // p-e: p-e '(' argument-expression-list[opt] ')'
|
2008-11-26 06:21:31 +08:00
|
|
|
ExprVector ArgExprs(Actions);
|
2008-08-17 04:03:01 +08:00
|
|
|
CommaLocsTy CommaLocs;
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2006-10-16 14:12:55 +08:00
|
|
|
Loc = ConsumeParen();
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
2008-08-17 04:03:01 +08:00
|
|
|
if (ParseExpressionList(ArgExprs, CommaLocs)) {
|
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 05:36:32 +08:00
|
|
|
return ExprError();
|
2006-08-13 02:12:45 +08:00
|
|
|
}
|
2006-08-11 14:41:18 +08:00
|
|
|
}
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2006-08-11 14:41:18 +08:00
|
|
|
// Match the ')'.
|
2009-04-13 08:10:38 +08:00
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
|
|
|
MatchRHSPunctuation(tok::r_paren, Loc);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!LHS.isInvalid()) {
|
2006-08-24 12:40:38 +08:00
|
|
|
assert((ArgExprs.size() == 0 || ArgExprs.size()-1 == CommaLocs.size())&&
|
|
|
|
"Unexpected number of commas!");
|
2009-02-05 23:02:23 +08:00
|
|
|
LHS = Actions.ActOnCallExpr(CurScope, move(LHS), Loc,
|
2009-01-19 08:08:26 +08:00
|
|
|
move_arg(ArgExprs), &CommaLocs[0],
|
2008-11-26 06:21:31 +08:00
|
|
|
Tok.getLocation());
|
2006-08-24 12:40:38 +08:00
|
|
|
}
|
2009-04-13 08:10:38 +08:00
|
|
|
|
|
|
|
ConsumeParen();
|
2006-08-11 14:41:18 +08:00
|
|
|
break;
|
2006-08-24 11:51:22 +08:00
|
|
|
}
|
2006-08-11 14:41:18 +08:00
|
|
|
case tok::arrow: // postfix-expression: p-e '->' identifier
|
2006-08-24 11:51:22 +08:00
|
|
|
case tok::period: { // postfix-expression: p-e '.' identifier
|
|
|
|
tok::TokenKind OpKind = Tok.getKind();
|
2006-10-16 14:06:51 +08:00
|
|
|
SourceLocation OpLoc = ConsumeToken(); // Eat the "." or "->" token.
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::identifier)) {
|
2006-08-11 14:41:18 +08:00
|
|
|
Diag(Tok, diag::err_expected_ident);
|
2008-12-12 05:36:32 +08:00
|
|
|
return ExprError();
|
2006-08-11 14:41:18 +08:00
|
|
|
}
|
2008-12-12 05:36:32 +08:00
|
|
|
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!LHS.isInvalid()) {
|
2009-02-05 23:02:23 +08:00
|
|
|
LHS = Actions.ActOnMemberReferenceExpr(CurScope, move(LHS), OpLoc,
|
2008-12-23 08:26:44 +08:00
|
|
|
OpKind, Tok.getLocation(),
|
2009-03-05 06:30:12 +08:00
|
|
|
*Tok.getIdentifierInfo(),
|
|
|
|
ObjCImpDecl);
|
2008-11-26 06:21:31 +08:00
|
|
|
}
|
2006-08-11 14:41:18 +08:00
|
|
|
ConsumeToken();
|
|
|
|
break;
|
2006-08-24 11:51:22 +08:00
|
|
|
}
|
2006-08-11 14:41:18 +08:00
|
|
|
case tok::plusplus: // postfix-expression: postfix-expression '++'
|
|
|
|
case tok::minusminus: // postfix-expression: postfix-expression '--'
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!LHS.isInvalid()) {
|
2008-11-19 23:42:04 +08:00
|
|
|
LHS = Actions.ActOnPostfixUnaryOp(CurScope, Tok.getLocation(),
|
2009-02-05 23:02:23 +08:00
|
|
|
Tok.getKind(), move(LHS));
|
2008-11-26 06:21:31 +08:00
|
|
|
}
|
2006-08-11 14:41:18 +08:00
|
|
|
ConsumeToken();
|
|
|
|
break;
|
2006-08-11 06:01:51 +08:00
|
|
|
}
|
|
|
|
}
|
2006-08-11 04:56:00 +08:00
|
|
|
}
|
|
|
|
|
2006-08-13 01:40:43 +08:00
|
|
|
|
2006-08-11 10:13:20 +08:00
|
|
|
/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
|
|
|
|
/// unary-expression: [C99 6.5.3]
|
|
|
|
/// 'sizeof' unary-expression
|
|
|
|
/// 'sizeof' '(' type-name ')'
|
|
|
|
/// [GNU] '__alignof' unary-expression
|
|
|
|
/// [GNU] '__alignof' '(' type-name ')'
|
2008-11-06 23:17:27 +08:00
|
|
|
/// [C++0x] 'alignof' '(' type-id ')'
|
2008-12-12 06:33:27 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseSizeofAlignofExpression() {
|
2008-11-06 23:17:27 +08:00
|
|
|
assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
|
|
|
|
|| Tok.is(tok::kw_alignof)) &&
|
2006-08-11 10:13:20 +08:00
|
|
|
"Not a sizeof/alignof expression!");
|
2007-07-21 00:59:19 +08:00
|
|
|
Token OpTok = Tok;
|
2006-08-11 10:13:20 +08:00
|
|
|
ConsumeToken();
|
|
|
|
|
|
|
|
// If the operand doesn't start with an '(', it must be an expression.
|
2008-12-10 04:22:58 +08:00
|
|
|
OwningExprResult Operand(Actions);
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::l_paren)) {
|
2006-08-24 14:10:04 +08:00
|
|
|
Operand = ParseCastExpression(true);
|
|
|
|
} else {
|
|
|
|
// If it starts with a '(', we know that it is either a parenthesized
|
|
|
|
// type-name, or it is a unary-expression that starts with a compound
|
|
|
|
// literal, or starts with a primary-expression that is a parenthesized
|
|
|
|
// expression.
|
|
|
|
ParenParseOption ExprType = CastExpr;
|
2006-08-24 14:37:51 +08:00
|
|
|
TypeTy *CastTy;
|
2006-08-24 14:49:19 +08:00
|
|
|
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
|
2006-08-24 14:37:51 +08:00
|
|
|
Operand = ParseParenExpression(ExprType, CastTy, RParenLoc);
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2006-08-24 14:10:04 +08:00
|
|
|
// If ParseParenExpression parsed a '(typename)' sequence only, the this is
|
|
|
|
// sizeof/alignof a type. Otherwise, it is sizeof/alignof an expression.
|
2007-11-14 04:50:37 +08:00
|
|
|
if (ExprType == CastExpr)
|
2009-01-19 08:08:26 +08:00
|
|
|
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
|
2008-11-12 01:56:53 +08:00
|
|
|
OpTok.is(tok::kw_sizeof),
|
|
|
|
/*isType=*/true, CastTy,
|
2009-01-19 08:08:26 +08:00
|
|
|
SourceRange(LParenLoc, RParenLoc));
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-11-14 04:50:37 +08:00
|
|
|
// If this is a parenthesized expression, it is the start of a
|
|
|
|
// unary-expression, but doesn't include any postfix pieces. Parse these
|
|
|
|
// now if present.
|
2008-12-12 05:36:32 +08:00
|
|
|
Operand = ParsePostfixExpressionSuffix(move(Operand));
|
2006-08-24 14:10:04 +08:00
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2006-08-24 14:10:04 +08:00
|
|
|
// If we get here, the operand to the sizeof/alignof was an expresion.
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Operand.isInvalid())
|
2008-11-12 01:56:53 +08:00
|
|
|
Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
|
|
|
|
OpTok.is(tok::kw_sizeof),
|
2008-12-10 08:02:53 +08:00
|
|
|
/*isType=*/false,
|
|
|
|
Operand.release(), SourceRange());
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(Operand);
|
2006-08-11 10:13:20 +08:00
|
|
|
}
|
|
|
|
|
2006-08-13 03:16:08 +08:00
|
|
|
/// ParseBuiltinPrimaryExpression
|
|
|
|
///
|
|
|
|
/// primary-expression: [C99 6.5.1]
|
|
|
|
/// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')'
|
|
|
|
/// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')'
|
|
|
|
/// [GNU] '__builtin_choose_expr' '(' assign-expr ',' assign-expr ','
|
|
|
|
/// assign-expr ')'
|
|
|
|
/// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')'
|
|
|
|
///
|
|
|
|
/// [GNU] offsetof-member-designator:
|
|
|
|
/// [GNU] identifier
|
|
|
|
/// [GNU] offsetof-member-designator '.' identifier
|
|
|
|
/// [GNU] offsetof-member-designator '[' expression ']'
|
|
|
|
///
|
2008-12-12 06:33:27 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
|
2008-12-10 04:22:58 +08:00
|
|
|
OwningExprResult Res(Actions);
|
2006-08-13 03:16:08 +08:00
|
|
|
const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo();
|
|
|
|
|
|
|
|
tok::TokenKind T = Tok.getKind();
|
2006-10-16 14:06:51 +08:00
|
|
|
SourceLocation StartLoc = ConsumeToken(); // Eat the builtin identifier.
|
2006-08-13 03:16:08 +08:00
|
|
|
|
|
|
|
// All of these start with an open paren.
|
2008-12-12 06:33:27 +08:00
|
|
|
if (Tok.isNot(tok::l_paren))
|
|
|
|
return ExprError(Diag(Tok, diag::err_expected_lparen_after_id)
|
|
|
|
<< BuiltinII);
|
|
|
|
|
2006-10-16 14:12:55 +08:00
|
|
|
SourceLocation LParenLoc = ConsumeParen();
|
2006-08-24 11:51:22 +08:00
|
|
|
// TODO: Build AST.
|
|
|
|
|
2006-08-13 03:16:08 +08:00
|
|
|
switch (T) {
|
|
|
|
default: assert(0 && "Not a builtin primary expression!");
|
2007-10-16 04:28:48 +08:00
|
|
|
case tok::kw___builtin_va_arg: {
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult Expr(ParseAssignmentExpression());
|
2008-12-09 21:15:23 +08:00
|
|
|
if (Expr.isInvalid()) {
|
2006-08-13 03:16:08 +08:00
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2006-08-13 03:16:08 +08:00
|
|
|
}
|
2006-08-13 03:30:51 +08:00
|
|
|
|
2006-08-15 11:41:14 +08:00
|
|
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2006-08-13 03:30:51 +08:00
|
|
|
|
2009-02-19 01:45:20 +08:00
|
|
|
TypeResult Ty = ParseTypeName();
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2007-10-16 04:28:48 +08:00
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
|
|
|
Diag(Tok, diag::err_expected_rparen);
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2007-10-16 04:28:48 +08:00
|
|
|
}
|
2009-02-19 01:45:20 +08:00
|
|
|
if (Ty.isInvalid())
|
|
|
|
Res = ExprError();
|
|
|
|
else
|
2009-03-16 01:47:39 +08:00
|
|
|
Res = Actions.ActOnVAArg(StartLoc, move(Expr), Ty.get(), ConsumeParen());
|
2006-08-13 03:16:08 +08:00
|
|
|
break;
|
2007-10-16 04:28:48 +08:00
|
|
|
}
|
2007-08-30 23:51:11 +08:00
|
|
|
case tok::kw___builtin_offsetof: {
|
2007-08-31 01:08:45 +08:00
|
|
|
SourceLocation TypeLoc = Tok.getLocation();
|
2009-02-19 01:45:20 +08:00
|
|
|
TypeResult Ty = ParseTypeName();
|
2009-03-25 01:21:43 +08:00
|
|
|
if (Ty.isInvalid()) {
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
2006-08-15 11:41:14 +08:00
|
|
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
|
|
|
|
2006-08-13 03:16:08 +08:00
|
|
|
// We must have at least one identifier here.
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::identifier)) {
|
2007-08-30 23:51:11 +08:00
|
|
|
Diag(Tok, diag::err_expected_ident);
|
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2007-08-30 23:51:11 +08:00
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-08-30 23:51:11 +08:00
|
|
|
// Keep track of the various subcomponents we see.
|
|
|
|
llvm::SmallVector<Action::OffsetOfComponent, 4> Comps;
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-08-30 23:51:11 +08:00
|
|
|
Comps.push_back(Action::OffsetOfComponent());
|
|
|
|
Comps.back().isBrackets = false;
|
|
|
|
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
|
|
|
|
Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken();
|
2006-08-13 03:26:13 +08:00
|
|
|
|
2008-11-26 06:21:31 +08:00
|
|
|
// FIXME: This loop leaks the index expressions on error.
|
2006-08-13 03:16:08 +08:00
|
|
|
while (1) {
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.is(tok::period)) {
|
2006-08-13 03:16:08 +08:00
|
|
|
// offsetof-member-designator: offsetof-member-designator '.' identifier
|
2007-08-30 23:51:11 +08:00
|
|
|
Comps.push_back(Action::OffsetOfComponent());
|
|
|
|
Comps.back().isBrackets = false;
|
|
|
|
Comps.back().LocStart = ConsumeToken();
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::identifier)) {
|
2007-08-30 23:51:11 +08:00
|
|
|
Diag(Tok, diag::err_expected_ident);
|
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2007-08-30 23:51:11 +08:00
|
|
|
}
|
|
|
|
Comps.back().U.IdentInfo = Tok.getIdentifierInfo();
|
|
|
|
Comps.back().LocEnd = ConsumeToken();
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
} else if (Tok.is(tok::l_square)) {
|
2006-08-13 03:16:08 +08:00
|
|
|
// offsetof-member-designator: offsetof-member-design '[' expression ']'
|
2007-08-30 23:51:11 +08:00
|
|
|
Comps.push_back(Action::OffsetOfComponent());
|
|
|
|
Comps.back().isBrackets = true;
|
|
|
|
Comps.back().LocStart = ConsumeBracket();
|
2006-08-13 03:16:08 +08:00
|
|
|
Res = ParseExpression();
|
2008-12-09 21:15:23 +08:00
|
|
|
if (Res.isInvalid()) {
|
2006-08-13 03:16:08 +08:00
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(Res);
|
2006-08-13 03:16:08 +08:00
|
|
|
}
|
2008-12-10 08:02:53 +08:00
|
|
|
Comps.back().U.E = Res.release();
|
2006-08-13 03:16:08 +08:00
|
|
|
|
2007-08-30 23:51:11 +08:00
|
|
|
Comps.back().LocEnd =
|
|
|
|
MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
|
2007-10-10 01:41:39 +08:00
|
|
|
} else if (Tok.is(tok::r_paren)) {
|
2009-02-19 01:45:20 +08:00
|
|
|
if (Ty.isInvalid())
|
|
|
|
Res = ExprError();
|
|
|
|
else
|
|
|
|
Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
|
|
|
|
Ty.get(), &Comps[0],
|
|
|
|
Comps.size(), ConsumeParen());
|
2007-08-30 23:52:49 +08:00
|
|
|
break;
|
2006-08-13 03:16:08 +08:00
|
|
|
} else {
|
2007-08-30 23:51:11 +08:00
|
|
|
// Error occurred.
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2006-08-13 03:16:08 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2007-08-30 23:51:11 +08:00
|
|
|
}
|
2007-08-04 05:21:27 +08:00
|
|
|
case tok::kw___builtin_choose_expr: {
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult Cond(ParseAssignmentExpression());
|
2008-12-09 21:15:23 +08:00
|
|
|
if (Cond.isInvalid()) {
|
2007-08-04 05:21:27 +08:00
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(Cond);
|
2007-08-04 05:21:27 +08:00
|
|
|
}
|
2006-08-15 11:41:14 +08:00
|
|
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
|
|
|
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult Expr1(ParseAssignmentExpression());
|
2008-12-09 21:15:23 +08:00
|
|
|
if (Expr1.isInvalid()) {
|
2007-08-04 05:21:27 +08:00
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(Expr1);
|
2008-12-09 21:15:23 +08:00
|
|
|
}
|
2006-08-15 11:41:14 +08:00
|
|
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
|
|
|
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult Expr2(ParseAssignmentExpression());
|
2008-12-09 21:15:23 +08:00
|
|
|
if (Expr2.isInvalid()) {
|
2007-08-04 05:21:27 +08:00
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 06:33:27 +08:00
|
|
|
return move(Expr2);
|
2008-12-09 21:15:23 +08:00
|
|
|
}
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
2007-08-04 05:21:27 +08:00
|
|
|
Diag(Tok, diag::err_expected_rparen);
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2007-08-04 05:21:27 +08:00
|
|
|
}
|
2009-03-16 01:47:39 +08:00
|
|
|
Res = Actions.ActOnChooseExpr(StartLoc, move(Cond), move(Expr1),
|
|
|
|
move(Expr2), ConsumeParen());
|
2007-08-30 23:52:49 +08:00
|
|
|
break;
|
2007-08-04 05:21:27 +08:00
|
|
|
}
|
2006-08-13 03:16:08 +08:00
|
|
|
case tok::kw___builtin_types_compatible_p:
|
2009-02-19 01:45:20 +08:00
|
|
|
TypeResult Ty1 = ParseTypeName();
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2006-08-15 11:41:14 +08:00
|
|
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
|
|
|
|
2009-02-19 01:45:20 +08:00
|
|
|
TypeResult Ty2 = ParseTypeName();
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
2007-08-02 07:45:51 +08:00
|
|
|
Diag(Tok, diag::err_expected_rparen);
|
2008-12-12 06:33:27 +08:00
|
|
|
return ExprError();
|
2007-08-02 07:45:51 +08:00
|
|
|
}
|
2009-02-19 01:45:20 +08:00
|
|
|
|
|
|
|
if (Ty1.isInvalid() || Ty2.isInvalid())
|
|
|
|
Res = ExprError();
|
|
|
|
else
|
|
|
|
Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1.get(), Ty2.get(),
|
|
|
|
ConsumeParen());
|
2007-08-30 23:52:49 +08:00
|
|
|
break;
|
2008-12-12 05:36:32 +08:00
|
|
|
}
|
|
|
|
|
2006-08-13 03:16:08 +08:00
|
|
|
// These can be followed by postfix-expr pieces because they are
|
|
|
|
// primary-expressions.
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParsePostfixExpressionSuffix(move(Res));
|
2006-08-13 03:16:08 +08:00
|
|
|
}
|
|
|
|
|
2006-08-11 09:33:00 +08:00
|
|
|
/// ParseParenExpression - This parses the unit that starts with a '(' token,
|
|
|
|
/// based on what is allowed by ExprType. The actual thing parsed is returned
|
|
|
|
/// in ExprType.
|
|
|
|
///
|
|
|
|
/// primary-expression: [C99 6.5.1]
|
2006-08-10 12:23:57 +08:00
|
|
|
/// '(' expression ')'
|
2006-08-11 06:01:51 +08:00
|
|
|
/// [GNU] '(' compound-statement ')' (if !ParenExprOnly)
|
|
|
|
/// postfix-expression: [C99 6.5.2]
|
|
|
|
/// '(' type-name ')' '{' initializer-list '}'
|
|
|
|
/// '(' type-name ')' '{' initializer-list ',' '}'
|
2006-08-11 09:33:00 +08:00
|
|
|
/// cast-expression: [C99 6.5.4]
|
|
|
|
/// '(' type-name ')' cast-expression
|
2006-08-11 06:01:51 +08:00
|
|
|
///
|
2008-12-12 06:33:27 +08:00
|
|
|
Parser::OwningExprResult
|
|
|
|
Parser::ParseParenExpression(ParenParseOption &ExprType,
|
|
|
|
TypeTy *&CastTy, SourceLocation &RParenLoc) {
|
2007-10-10 01:41:39 +08:00
|
|
|
assert(Tok.is(tok::l_paren) && "Not a paren expr!");
|
2009-02-10 05:04:56 +08:00
|
|
|
GreaterThanIsOperatorScope G(GreaterThanIsOperator, true);
|
2006-10-16 14:12:55 +08:00
|
|
|
SourceLocation OpenLoc = ConsumeParen();
|
2008-12-10 04:22:58 +08:00
|
|
|
OwningExprResult Result(Actions, true);
|
2006-08-24 14:37:51 +08:00
|
|
|
CastTy = 0;
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) {
|
2006-08-11 06:01:51 +08:00
|
|
|
Diag(Tok, diag::ext_gnu_statement_expr);
|
2008-12-12 03:30:53 +08:00
|
|
|
OwningStmtResult Stmt(ParseCompoundStatement(true));
|
2006-08-11 09:33:00 +08:00
|
|
|
ExprType = CompoundStmt;
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2007-07-25 00:58:17 +08:00
|
|
|
// If the substmt parsed correctly, build the AST node.
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Stmt.isInvalid() && Tok.is(tok::r_paren))
|
2009-03-16 01:47:39 +08:00
|
|
|
Result = Actions.ActOnStmtExpr(OpenLoc, move(Stmt), Tok.getLocation());
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2008-10-06 03:56:22 +08:00
|
|
|
} else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
|
2006-08-13 00:54:25 +08:00
|
|
|
// Otherwise, this is a compound literal expression or cast expression.
|
2009-02-19 01:45:20 +08:00
|
|
|
TypeResult Ty = ParseTypeName();
|
2006-08-11 07:56:11 +08:00
|
|
|
|
|
|
|
// Match the ')'.
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.is(tok::r_paren))
|
2006-10-16 14:12:55 +08:00
|
|
|
RParenLoc = ConsumeParen();
|
|
|
|
else
|
2006-08-24 14:37:51 +08:00
|
|
|
MatchRHSPunctuation(tok::r_paren, OpenLoc);
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.is(tok::l_brace)) {
|
2006-08-13 00:54:25 +08:00
|
|
|
if (!getLang().C99) // Compound literals don't exist in C90.
|
|
|
|
Diag(OpenLoc, diag::ext_c99_compound_literal);
|
2006-08-11 14:41:18 +08:00
|
|
|
Result = ParseInitializer();
|
2006-08-11 09:33:00 +08:00
|
|
|
ExprType = CompoundLiteral;
|
2009-02-19 01:45:20 +08:00
|
|
|
if (!Result.isInvalid() && !Ty.isInvalid())
|
|
|
|
return Actions.ActOnCompoundLiteral(OpenLoc, Ty.get(), RParenLoc,
|
2009-02-05 23:02:23 +08:00
|
|
|
move(Result));
|
2008-12-12 14:00:12 +08:00
|
|
|
return move(Result);
|
|
|
|
}
|
2009-01-20 06:31:54 +08:00
|
|
|
|
2008-12-12 14:00:12 +08:00
|
|
|
if (ExprType == CastExpr) {
|
2009-02-19 01:45:20 +08:00
|
|
|
// Note that this doesn't parse the subsequent cast-expression, it just
|
2006-08-24 14:37:51 +08:00
|
|
|
// returns the parsed type to the callee.
|
2006-08-11 09:33:00 +08:00
|
|
|
ExprType = CastExpr;
|
2009-02-19 01:45:20 +08:00
|
|
|
|
|
|
|
if (Ty.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
CastTy = Ty.get();
|
2008-12-12 06:33:27 +08:00
|
|
|
return OwningExprResult(Actions);
|
2006-08-11 07:56:11 +08:00
|
|
|
}
|
2009-01-20 06:31:54 +08:00
|
|
|
|
2008-12-12 14:00:12 +08:00
|
|
|
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
|
|
|
|
return ExprError();
|
2006-08-11 09:33:00 +08:00
|
|
|
} else {
|
2006-08-11 14:41:18 +08:00
|
|
|
Result = ParseExpression();
|
2006-08-11 09:33:00 +08:00
|
|
|
ExprType = SimpleExpr;
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Result.isInvalid() && Tok.is(tok::r_paren))
|
2009-02-05 23:02:23 +08:00
|
|
|
Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), move(Result));
|
2006-08-11 06:01:51 +08:00
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2006-08-11 07:14:52 +08:00
|
|
|
// Match the ')'.
|
2008-12-12 14:00:12 +08:00
|
|
|
if (Result.isInvalid()) {
|
2006-08-11 14:41:18 +08:00
|
|
|
SkipUntil(tok::r_paren);
|
2008-12-12 14:00:12 +08:00
|
|
|
return ExprError();
|
2006-08-24 14:37:51 +08:00
|
|
|
}
|
2008-12-12 14:00:12 +08:00
|
|
|
|
|
|
|
if (Tok.is(tok::r_paren))
|
|
|
|
RParenLoc = ConsumeParen();
|
|
|
|
else
|
|
|
|
MatchRHSPunctuation(tok::r_paren, OpenLoc);
|
2008-12-12 06:33:27 +08:00
|
|
|
|
|
|
|
return move(Result);
|
2006-08-10 12:23:57 +08:00
|
|
|
}
|
2006-10-06 13:22:26 +08:00
|
|
|
|
|
|
|
/// ParseStringLiteralExpression - This handles the various token types that
|
|
|
|
/// form string literals, and also handles string concatenation [C99 5.1.1.2,
|
|
|
|
/// translation phase #6].
|
|
|
|
///
|
|
|
|
/// primary-expression: [C99 6.5.1]
|
|
|
|
/// string-literal
|
2008-12-12 06:51:44 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseStringLiteralExpression() {
|
2006-10-06 13:22:26 +08:00
|
|
|
assert(isTokenStringLiteral() && "Not a string literal!");
|
2008-12-12 06:51:44 +08:00
|
|
|
|
2006-10-06 13:22:26 +08:00
|
|
|
// String concat. Note that keywords like __func__ and __FUNCTION__ are not
|
|
|
|
// considered to be strings for concatenation purposes.
|
2007-07-21 00:59:19 +08:00
|
|
|
llvm::SmallVector<Token, 4> StringToks;
|
2008-12-12 06:51:44 +08:00
|
|
|
|
2006-10-06 13:22:26 +08:00
|
|
|
do {
|
|
|
|
StringToks.push_back(Tok);
|
|
|
|
ConsumeStringToken();
|
|
|
|
} while (isTokenStringLiteral());
|
2006-11-09 14:34:47 +08:00
|
|
|
|
|
|
|
// Pass the set of string tokens, ready for concatenation, to the actions.
|
2009-01-19 02:53:16 +08:00
|
|
|
return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size());
|
2006-10-06 13:22:26 +08:00
|
|
|
}
|
2008-08-17 04:03:01 +08:00
|
|
|
|
|
|
|
/// ParseExpressionList - Used for C/C++ (argument-)expression-list.
|
|
|
|
///
|
|
|
|
/// argument-expression-list:
|
|
|
|
/// assignment-expression
|
|
|
|
/// argument-expression-list , assignment-expression
|
|
|
|
///
|
|
|
|
/// [C++] expression-list:
|
|
|
|
/// [C++] assignment-expression
|
|
|
|
/// [C++] expression-list , assignment-expression
|
|
|
|
///
|
|
|
|
bool Parser::ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs) {
|
|
|
|
while (1) {
|
2008-12-12 05:36:32 +08:00
|
|
|
OwningExprResult Expr(ParseAssignmentExpression());
|
2008-12-09 21:15:23 +08:00
|
|
|
if (Expr.isInvalid())
|
2008-08-17 04:03:01 +08:00
|
|
|
return true;
|
2008-08-19 06:49:40 +08:00
|
|
|
|
2008-12-10 08:02:53 +08:00
|
|
|
Exprs.push_back(Expr.release());
|
2008-08-17 04:03:01 +08:00
|
|
|
|
|
|
|
if (Tok.isNot(tok::comma))
|
|
|
|
return false;
|
|
|
|
// Move to the next argument, remember where the comma was.
|
|
|
|
CommaLocs.push_back(ConsumeToken());
|
|
|
|
}
|
|
|
|
}
|
2008-08-29 03:20:44 +08:00
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
/// ParseBlockId - Parse a block-id, which roughly looks like int (int x).
|
|
|
|
///
|
|
|
|
/// [clang] block-id:
|
|
|
|
/// [clang] specifier-qualifier-list block-declarator
|
|
|
|
///
|
|
|
|
void Parser::ParseBlockId() {
|
|
|
|
// Parse the specifier-qualifier-list piece.
|
|
|
|
DeclSpec DS;
|
|
|
|
ParseSpecifierQualifierList(DS);
|
|
|
|
|
|
|
|
// Parse the block-declarator.
|
|
|
|
Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext);
|
|
|
|
ParseDeclarator(DeclaratorInfo);
|
2009-04-30 03:03:13 +08:00
|
|
|
|
2009-04-30 05:40:37 +08:00
|
|
|
// We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes.
|
|
|
|
DeclaratorInfo.AddAttributes(DS.TakeAttributes(),
|
|
|
|
SourceLocation());
|
|
|
|
|
2009-04-30 03:03:13 +08:00
|
|
|
if (Tok.is(tok::kw___attribute)) {
|
|
|
|
SourceLocation Loc;
|
|
|
|
AttributeList *AttrList = ParseAttributes(&Loc);
|
|
|
|
DeclaratorInfo.AddAttributes(AttrList, Loc);
|
|
|
|
}
|
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// Inform sema that we are starting a block.
|
|
|
|
Actions.ActOnBlockArguments(DeclaratorInfo, CurScope);
|
|
|
|
}
|
|
|
|
|
2008-08-29 03:20:44 +08:00
|
|
|
/// ParseBlockLiteralExpression - Parse a block literal, which roughly looks
|
2008-09-17 07:11:46 +08:00
|
|
|
/// like ^(int x){ return x+1; }
|
2008-08-29 03:20:44 +08:00
|
|
|
///
|
|
|
|
/// block-literal:
|
|
|
|
/// [clang] '^' block-args[opt] compound-statement
|
2009-02-05 06:31:32 +08:00
|
|
|
/// [clang] '^' block-id compound-statement
|
2008-08-29 03:20:44 +08:00
|
|
|
/// [clang] block-args:
|
|
|
|
/// [clang] '(' parameter-list ')'
|
|
|
|
///
|
2008-12-13 23:32:12 +08:00
|
|
|
Parser::OwningExprResult Parser::ParseBlockLiteralExpression() {
|
2008-08-29 03:20:44 +08:00
|
|
|
assert(Tok.is(tok::caret) && "block literal starts with ^");
|
|
|
|
SourceLocation CaretLoc = ConsumeToken();
|
2008-12-13 23:32:12 +08:00
|
|
|
|
2009-03-05 15:32:12 +08:00
|
|
|
PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), CaretLoc,
|
|
|
|
"block literal parsing");
|
|
|
|
|
2008-08-29 03:20:44 +08:00
|
|
|
// Enter a scope to hold everything within the block. This includes the
|
|
|
|
// argument decls, decls within the compound expression, etc. This also
|
|
|
|
// allows determining whether a variable reference inside the block is
|
|
|
|
// within or outside of the block.
|
2009-02-10 02:23:29 +08:00
|
|
|
ParseScope BlockScope(this, Scope::BlockScope | Scope::FnScope |
|
|
|
|
Scope::BreakScope | Scope::ContinueScope |
|
|
|
|
Scope::DeclScope);
|
2008-10-10 09:28:17 +08:00
|
|
|
|
|
|
|
// Inform sema that we are starting a block.
|
|
|
|
Actions.ActOnBlockStart(CaretLoc, CurScope);
|
2009-03-05 15:32:12 +08:00
|
|
|
|
2008-08-29 03:20:44 +08:00
|
|
|
// Parse the return type if present.
|
|
|
|
DeclSpec DS;
|
2009-02-05 06:31:32 +08:00
|
|
|
Declarator ParamInfo(DS, Declarator::BlockLiteralContext);
|
2009-02-10 02:23:29 +08:00
|
|
|
// FIXME: Since the return type isn't actually parsed, it can't be used to
|
|
|
|
// fill ParamInfo with an initial valid range, so do it manually.
|
|
|
|
ParamInfo.SetSourceRange(SourceRange(Tok.getLocation(), Tok.getLocation()));
|
2008-12-13 23:32:12 +08:00
|
|
|
|
2008-08-29 03:20:44 +08:00
|
|
|
// If this block has arguments, parse them. There is no ambiguity here with
|
|
|
|
// the expression case, because the expression case requires a parameter list.
|
|
|
|
if (Tok.is(tok::l_paren)) {
|
|
|
|
ParseParenDeclarator(ParamInfo);
|
|
|
|
// Parse the pieces after the identifier as if we had "int(...)".
|
2009-02-10 02:23:29 +08:00
|
|
|
// SetIdentifier sets the source range end, but in this case we're past
|
|
|
|
// that location.
|
|
|
|
SourceLocation Tmp = ParamInfo.getSourceRange().getEnd();
|
2008-08-29 03:20:44 +08:00
|
|
|
ParamInfo.SetIdentifier(0, CaretLoc);
|
2009-02-10 02:23:29 +08:00
|
|
|
ParamInfo.SetRangeEnd(Tmp);
|
2009-04-25 16:06:05 +08:00
|
|
|
if (ParamInfo.isInvalidType()) {
|
2009-02-05 06:31:32 +08:00
|
|
|
// If there was an error parsing the arguments, they may have
|
|
|
|
// tried to use ^(x+y) which requires an argument list. Just
|
|
|
|
// skip the whole block literal.
|
2009-04-19 04:05:34 +08:00
|
|
|
Actions.ActOnBlockError(CaretLoc, CurScope);
|
2008-12-13 23:32:12 +08:00
|
|
|
return ExprError();
|
2008-08-29 03:20:44 +08:00
|
|
|
}
|
2009-04-30 03:03:13 +08:00
|
|
|
|
|
|
|
if (Tok.is(tok::kw___attribute)) {
|
|
|
|
SourceLocation Loc;
|
|
|
|
AttributeList *AttrList = ParseAttributes(&Loc);
|
|
|
|
ParamInfo.AddAttributes(AttrList, Loc);
|
|
|
|
}
|
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// Inform sema that we are starting a block.
|
|
|
|
Actions.ActOnBlockArguments(ParamInfo, CurScope);
|
2009-04-15 02:24:37 +08:00
|
|
|
} else if (!Tok.is(tok::l_brace)) {
|
2009-02-05 06:31:32 +08:00
|
|
|
ParseBlockId();
|
2008-08-29 03:20:44 +08:00
|
|
|
} else {
|
|
|
|
// Otherwise, pretend we saw (void).
|
2009-02-18 15:07:28 +08:00
|
|
|
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
|
|
|
|
SourceLocation(),
|
2009-04-30 01:30:04 +08:00
|
|
|
0, 0, 0,
|
|
|
|
false, false, 0, 0,
|
|
|
|
CaretLoc, ParamInfo),
|
2009-02-10 02:23:29 +08:00
|
|
|
CaretLoc);
|
2009-04-30 03:03:13 +08:00
|
|
|
|
|
|
|
if (Tok.is(tok::kw___attribute)) {
|
|
|
|
SourceLocation Loc;
|
|
|
|
AttributeList *AttrList = ParseAttributes(&Loc);
|
|
|
|
ParamInfo.AddAttributes(AttrList, Loc);
|
|
|
|
}
|
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// Inform sema that we are starting a block.
|
|
|
|
Actions.ActOnBlockArguments(ParamInfo, CurScope);
|
2008-08-29 03:20:44 +08:00
|
|
|
}
|
|
|
|
|
2008-12-13 23:32:12 +08:00
|
|
|
|
2008-12-10 04:22:58 +08:00
|
|
|
OwningExprResult Result(Actions, true);
|
2009-03-27 12:18:06 +08:00
|
|
|
if (!Tok.is(tok::l_brace)) {
|
2009-01-15 03:39:53 +08:00
|
|
|
// Saw something like: ^expr
|
|
|
|
Diag(Tok, diag::err_expected_expression);
|
2009-04-19 04:05:34 +08:00
|
|
|
Actions.ActOnBlockError(CaretLoc, CurScope);
|
2009-01-15 03:39:53 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2009-03-27 12:18:06 +08:00
|
|
|
|
|
|
|
OwningStmtResult Stmt(ParseCompoundStatementBody());
|
|
|
|
if (!Stmt.isInvalid())
|
|
|
|
Result = Actions.ActOnBlockStmtExpr(CaretLoc, move(Stmt), CurScope);
|
|
|
|
else
|
|
|
|
Actions.ActOnBlockError(CaretLoc, CurScope);
|
2008-12-13 23:32:12 +08:00
|
|
|
return move(Result);
|
2008-08-29 03:20:44 +08:00
|
|
|
}
|