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"
|
2010-08-21 02:27:03 +08:00
|
|
|
#include "clang/Sema/DeclSpec.h"
|
|
|
|
#include "clang/Sema/Scope.h"
|
|
|
|
#include "clang/Sema/ParsedTemplate.h"
|
2009-03-05 15:32:12 +08:00
|
|
|
#include "clang/Basic/PrettyStackTrace.h"
|
2009-12-10 08:21:05 +08:00
|
|
|
#include "RAIIObjectsForParser.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-12 16:13:25 +08:00
|
|
|
/// getBinOpPrecedence - Return the precedence of the specified binary operator
|
2010-07-19 13:07:24 +08:00
|
|
|
/// token.
|
2009-09-09 23:08:12 +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-09-09 23:08:12 +08:00
|
|
|
|
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]
|
2011-01-04 03:31:53 +08:00
|
|
|
/// assignment-expression ...[opt]
|
|
|
|
/// expression ',' assignment-expression ...[opt]
|
2006-08-12 16:13:25 +08:00
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseExpression() {
|
|
|
|
ExprResult LHS(ParseAssignmentExpression());
|
2008-12-12 06:33:27 +08:00
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
/// This routine is called when the '@' is seen and consumed.
|
2007-09-20 03:14:32 +08:00
|
|
|
/// 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
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2008-12-12 06:33:27 +08:00
|
|
|
Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) {
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult LHS(ParseObjCAtExpression(AtLoc));
|
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.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2009-01-27 16:43:38 +08:00
|
|
|
Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) {
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult LHS(true);
|
2009-05-17 07:40:44 +08:00
|
|
|
{
|
|
|
|
// Silence extension warnings in the sub-expression
|
|
|
|
ExtensionRAIIObject O(Diags);
|
|
|
|
|
|
|
|
LHS = ParseCastExpression(false);
|
|
|
|
}
|
2009-01-27 16:43:38 +08:00
|
|
|
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
if (!LHS.isInvalid())
|
|
|
|
LHS = Actions.ActOnUnaryOp(getCurScope(), ExtLoc, tok::kw___extension__,
|
|
|
|
LHS.take());
|
2009-01-27 16:43:38 +08:00
|
|
|
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
return ParseRHSOfBinaryExpression(move(LHS), prec::Comma);
|
2009-01-27 16:43:38 +08:00
|
|
|
}
|
|
|
|
|
2006-08-13 02:12:45 +08:00
|
|
|
/// ParseAssignmentExpression - Parse an expr that doesn't include commas.
|
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseAssignmentExpression() {
|
Improve code completion by introducing patterns for the various C and
C++ grammatical constructs that show up in top-level (namespace-level)
declarations, member declarations, template declarations, statements,
expressions, conditions, etc. For example, we now provide a pattern
for
static_cast<type>(expr)
when we can have an expression, or
using namespace identifier;
when we can have a using directive.
Also, improves the results of code completion at the beginning of a
top-level declaration. Previously, we would see value names (function
names, global variables, etc.); now we see types, namespace names,
etc., but no values.
llvm-svn: 93134
2010-01-11 07:08:15 +08:00
|
|
|
if (Tok.is(tok::code_completion)) {
|
2010-08-27 07:41:50 +08:00
|
|
|
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
|
2010-05-25 13:58:43 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
Improve code completion by introducing patterns for the various C and
C++ grammatical constructs that show up in top-level (namespace-level)
declarations, member declarations, template declarations, statements,
expressions, conditions, etc. For example, we now provide a pattern
for
static_cast<type>(expr)
when we can have an expression, or
using namespace identifier;
when we can have a using directive.
Also, improves the results of code completion at the beginning of a
top-level declaration. Previously, we would see value names (function
names, global variables, etc.); now we see types, namespace names,
etc., but no values.
llvm-svn: 93134
2010-01-11 07:08:15 +08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult LHS(ParseCastExpression(false));
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +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.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2008-06-03 05:31:07 +08:00
|
|
|
Parser::ParseAssignmentExprWithObjCMessageExprStart(SourceLocation LBracLoc,
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
SourceLocation SuperLoc,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType ReceiverType,
|
2010-08-24 07:25:46 +08:00
|
|
|
Expr *ReceiverExpr) {
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult R
|
2010-08-24 07:25:46 +08:00
|
|
|
= ParseObjCMessageExpressionBody(LBracLoc, SuperLoc,
|
|
|
|
ReceiverType, ReceiverExpr);
|
2010-09-18 09:28:11 +08:00
|
|
|
R = ParsePostfixExpressionSuffix(R);
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
return ParseRHSOfBinaryExpression(R, prec::Assignment);
|
2008-06-03 05:31:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseConstantExpression() {
|
2009-06-20 07:52:42 +08:00
|
|
|
// C++ [basic.def.odr]p2:
|
2009-09-09 23:08:12 +08:00
|
|
|
// An expression is potentially evaluated unless it appears where an
|
2009-06-20 07:52:42 +08:00
|
|
|
// integral constant expression is required (see 5.19) [...].
|
2009-06-23 04:57:11 +08:00
|
|
|
EnterExpressionEvaluationContext Unevaluated(Actions,
|
2010-08-27 07:41:50 +08:00
|
|
|
Sema::Unevaluated);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult LHS(ParseCastExpression(false));
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
return ParseRHSOfBinaryExpression(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.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
|
|
|
Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) {
|
2010-04-22 06:36:40 +08:00
|
|
|
prec::Level 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.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult TernaryMiddle(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)) {
|
2009-12-10 10:02:58 +08:00
|
|
|
// Don't parse FOO:BAR as if it were a typo for FOO::BAR.
|
|
|
|
ColonProtectionRAIIObject X(*this);
|
|
|
|
|
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();
|
2010-09-18 06:41:34 +08:00
|
|
|
if (TernaryMiddle.isInvalid()) {
|
|
|
|
LHS = ExprError();
|
|
|
|
TernaryMiddle = 0;
|
|
|
|
}
|
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
|
|
|
|
2010-04-21 05:33:39 +08:00
|
|
|
if (Tok.is(tok::colon)) {
|
|
|
|
// Eat the colon.
|
|
|
|
ColonLoc = ConsumeToken();
|
|
|
|
} else {
|
2010-05-25 06:31:37 +08:00
|
|
|
// Otherwise, we're missing a ':'. Assume that this was a typo that the
|
|
|
|
// user forgot. If we're not in a macro instantion, we can suggest a
|
|
|
|
// fixit hint. If there were two spaces before the current token,
|
|
|
|
// suggest inserting the colon in between them, otherwise insert ": ".
|
|
|
|
SourceLocation FILoc = Tok.getLocation();
|
|
|
|
const char *FIText = ": ";
|
|
|
|
if (FILoc.isFileID()) {
|
|
|
|
const SourceManager &SM = PP.getSourceManager();
|
|
|
|
bool IsInvalid = false;
|
|
|
|
const char *SourcePtr =
|
|
|
|
SM.getCharacterData(FILoc.getFileLocWithOffset(-1), &IsInvalid);
|
|
|
|
if (!IsInvalid && *SourcePtr == ' ') {
|
|
|
|
SourcePtr =
|
|
|
|
SM.getCharacterData(FILoc.getFileLocWithOffset(-2), &IsInvalid);
|
|
|
|
if (!IsInvalid && *SourcePtr == ' ') {
|
|
|
|
FILoc = FILoc.getFileLocWithOffset(-1);
|
|
|
|
FIText = ":";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-13 06:10:35 +08:00
|
|
|
Diag(Tok, diag::err_expected_colon)
|
2010-05-25 06:31:37 +08:00
|
|
|
<< FixItHint::CreateInsertion(FILoc, FIText);
|
2008-11-24 07:17:07 +08:00
|
|
|
Diag(OpToken, diag::note_matching) << "?";
|
2010-04-21 05:33:39 +08:00
|
|
|
ColonLoc = Tok.getLocation();
|
2006-08-13 01:13:08 +08:00
|
|
|
}
|
2006-08-12 16:13:25 +08:00
|
|
|
}
|
2009-10-24 05:01:39 +08:00
|
|
|
|
2010-05-30 09:49:25 +08:00
|
|
|
// Code completion for the right-hand side of an assignment expression
|
|
|
|
// goes through a special hook that takes the left-hand side into account.
|
|
|
|
if (Tok.is(tok::code_completion) && NextTokPrec == prec::Assignment) {
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.CodeCompleteAssignmentRHS(getCurScope(), LHS.get());
|
2010-05-30 09:49:25 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
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++.
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult RHS;
|
2009-04-17 01:51:27 +08:00
|
|
|
if (getLang().CPlusPlus && NextTokPrec <= prec::Conditional)
|
|
|
|
RHS = ParseAssignmentExpression();
|
|
|
|
else
|
|
|
|
RHS = ParseCastExpression(false);
|
2006-08-12 16:13:25 +08:00
|
|
|
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
if (RHS.isInvalid())
|
|
|
|
LHS = ExprError();
|
|
|
|
|
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.
|
2010-04-22 06:36:40 +08:00
|
|
|
prec::Level 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.
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
RHS = ParseRHSOfBinaryExpression(RHS,
|
2010-04-22 06:36:40 +08:00
|
|
|
static_cast<prec::Level>(ThisPrec + !isRightAssoc));
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
|
2008-12-09 21:15:23 +08:00
|
|
|
if (RHS.isInvalid())
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
LHS = ExprError();
|
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()));
|
|
|
|
|
2010-07-03 01:43:08 +08:00
|
|
|
LHS = Actions.ActOnBinOp(getCurScope(), OpToken.getLocation(),
|
2010-08-24 07:25:46 +08:00
|
|
|
OpToken.getKind(), LHS.take(), RHS.take());
|
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,
|
2010-08-24 07:25:46 +08:00
|
|
|
LHS.take(), TernaryMiddle.take(),
|
|
|
|
RHS.take());
|
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
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
2009-08-11 07:49:36 +08:00
|
|
|
bool isAddressOfOperand,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType TypeOfCast) {
|
2009-05-22 18:24:42 +08:00
|
|
|
bool NotCastExpr;
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Res = ParseCastExpression(isUnaryExpression,
|
When we run into an error parsing or type-checking the left-hand side
of a binary expression, continue on and parse the right-hand side of
the binary expression anyway, but don't call the semantic actions to
type-check. Previously, we would see the error and then, effectively,
skip tokens until the end of the statement.
The result should be more useful recovery, both in the normal case
(we'll actually see errors beyond the first one in a statement), but
it also helps code completion do a much better job, because we do
"real" code completion on the right-hand side of an invalid binary
expression rather than completing with the recovery completion. For
example, given
x = p->y
if there is no variable named "x", we can still complete after the p->
as a member expression. Along the recovery path, we would have
completed after the "->" as if we were in an expression context, which
is mostly useless.
llvm-svn: 114225
2010-09-18 06:25:06 +08:00
|
|
|
isAddressOfOperand,
|
|
|
|
NotCastExpr,
|
|
|
|
TypeOfCast);
|
2009-05-22 18:24:42 +08:00
|
|
|
if (NotCastExpr)
|
|
|
|
Diag(Tok, diag::err_expected_expression);
|
|
|
|
return move(Res);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
|
|
|
|
/// 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. NotCastExpr is set to true if the token is not the
|
|
|
|
/// start of a cast-expression, and no diagnostic is emitted in this case.
|
|
|
|
///
|
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 ')'
|
2011-01-05 01:33:58 +08:00
|
|
|
/// [C++0x] 'sizeof' '...' '(' identifier ')'
|
2006-08-11 06:57:16 +08:00
|
|
|
/// [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
|
2010-09-11 04:55:37 +08:00
|
|
|
/// [C++0x] 'noexcept' '(' 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'
|
2009-09-09 23:08:12 +08:00
|
|
|
/// [OBJC] '[' objc-message-expr ']'
|
2008-01-26 02:58:06 +08:00
|
|
|
/// [OBJC] '@selector' '(' objc-selector-arg ')'
|
2009-09-09 23:08:12 +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]
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// [C++] typename-specifier '(' expression-list[opt] ')' [C++ 5.2.3]
|
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
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// qualified-id
|
2008-11-07 06:13:31 +08:00
|
|
|
///
|
|
|
|
/// unqualified-id: [C++ 5.1]
|
|
|
|
/// identifier
|
|
|
|
/// operator-function-id
|
Rework the Parser-Sema interaction for Objective-C message
sends. Major changes include:
- Expanded the interface from two actions (ActOnInstanceMessage,
ActOnClassMessage), where ActOnClassMessage also handled sends to
"super" by checking whether the identifier was "super", to three
actions (ActOnInstanceMessage, ActOnClassMessage,
ActOnSuperMessage). Code completion has the same changes.
- The parser now resolves the type to which we are sending a class
message, so ActOnClassMessage now accepts a TypeTy* (rather than
an IdentifierInfo *). This opens the door to more interesting
types (for Objective-C++ support).
- Split ActOnInstanceMessage and ActOnClassMessage into parser
action functions (with their original names) and semantic
functions (BuildInstanceMessage and BuildClassMessage,
respectively). At present, this split is onyl used by
ActOnSuperMessage, which decides which kind of super message it
has and forwards to the appropriate Build*Message. In the future,
Build*Message will be used by template instantiation.
- Use getObjCMessageKind() within the disambiguation of Objective-C
message sends vs. array designators.
Two notes about substandard bits in this patch:
- There is some redundancy in the code in ParseObjCMessageExpr and
ParseInitializerWithPotentialDesignator; this will be addressed
shortly by centralizing the mapping from identifiers to type names
for the message receiver.
- There is some #if 0'd code that won't likely ever be used---it
handles the use of 'super' in methods whose class does not have a
superclass---but could be used to model GCC's behavior more
closely. This code will die in my next check-in, but I want it in
Subversion.
llvm-svn: 102021
2010-04-22 03:57:20 +08:00
|
|
|
/// conversion-function-id
|
|
|
|
/// '~' class-name
|
|
|
|
/// template-id
|
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:
|
2010-08-31 12:59:00 +08:00
|
|
|
/// '__has_nothrow_assign'
|
|
|
|
/// '__has_nothrow_copy'
|
|
|
|
/// '__has_nothrow_constructor'
|
2009-01-06 04:52:13 +08:00
|
|
|
/// '__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'
|
2010-09-03 07:19:42 +08:00
|
|
|
/// '__has_virtual_destructor'
|
2009-01-06 04:52:13 +08:00
|
|
|
/// '__is_abstract' [TODO]
|
|
|
|
/// '__is_class'
|
|
|
|
/// '__is_empty' [TODO]
|
|
|
|
/// '__is_enum'
|
|
|
|
/// '__is_pod'
|
|
|
|
/// '__is_polymorphic'
|
|
|
|
/// '__is_union'
|
|
|
|
///
|
2011-01-28 04:28:01 +08:00
|
|
|
/// binary-type-trait:
|
|
|
|
/// [GNU] '__is_base_of'
|
|
|
|
/// [MS] '__is_convertible_to'
|
2009-01-06 04:52:13 +08:00
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
2010-09-11 04:55:37 +08:00
|
|
|
bool isAddressOfOperand,
|
|
|
|
bool &NotCastExpr,
|
|
|
|
ParsedType TypeOfCast) {
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Res;
|
2006-10-25 11:38:23 +08:00
|
|
|
tok::TokenKind SavedKind = Tok.getKind();
|
2009-05-22 18:24:42 +08:00
|
|
|
NotCastExpr = false;
|
2009-09-09 23:08:12 +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
|
2010-08-24 07:25:46 +08:00
|
|
|
// break out of the switch; at the end we 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 =
|
2010-08-06 22:50:36 +08:00
|
|
|
(isUnaryExpression && !getLang().CPlusPlus)? CompoundLiteral : CastExpr;
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType CastTy;
|
2006-08-24 14:37:51 +08:00
|
|
|
SourceLocation RParenLoc;
|
2009-12-10 10:08:07 +08:00
|
|
|
|
|
|
|
{
|
2010-09-15 22:51:05 +08:00
|
|
|
// The inside of the parens don't need to be a colon protected scope, and
|
|
|
|
// isn't immediately a message send.
|
2009-12-10 10:08:07 +08:00
|
|
|
ColonProtectionRAIIObject X(*this, false);
|
2010-09-15 22:51:05 +08:00
|
|
|
|
2009-12-10 10:08:07 +08:00
|
|
|
Res = ParseParenExpression(ParenExprType, false/*stopIfCastExr*/,
|
|
|
|
TypeOfCast, CastTy, RParenLoc);
|
|
|
|
}
|
2009-09-09 23:08:12 +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:
|
2009-05-22 18:23:40 +08:00
|
|
|
// We have parsed the cast-expression and no postfix-expr pieces are
|
|
|
|
// following.
|
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
|
|
|
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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) {
|
2010-01-08 03:29:58 +08:00
|
|
|
// Avoid the unnecessary parse-time lookup in the common case
|
|
|
|
// where the syntax forbids a type.
|
|
|
|
const Token &Next = NextToken();
|
|
|
|
if (Next.is(tok::coloncolon) ||
|
|
|
|
(!ColonIsSacred && Next.is(tok::colon)) ||
|
|
|
|
Next.is(tok::less) ||
|
|
|
|
Next.is(tok::l_paren)) {
|
|
|
|
// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
|
|
|
|
if (TryAnnotateTypeOrScopeToken())
|
2010-02-26 16:45:28 +08:00
|
|
|
return ExprError();
|
|
|
|
if (!Tok.is(tok::identifier))
|
2010-01-08 03:29:58 +08:00
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
|
|
|
|
}
|
2009-01-05 07:23:14 +08:00
|
|
|
}
|
2008-08-22 23:38:55 +08:00
|
|
|
|
2009-10-26 01:04:48 +08:00
|
|
|
// Consume the identifier so that we can see if it is followed by a '(' or
|
|
|
|
// '.'.
|
|
|
|
IdentifierInfo &II = *Tok.getIdentifierInfo();
|
|
|
|
SourceLocation ILoc = ConsumeToken();
|
|
|
|
|
2010-04-11 16:28:14 +08:00
|
|
|
// Support 'Class.property' and 'super.property' notation.
|
2009-10-26 01:04:48 +08:00
|
|
|
if (getLang().ObjC1 && Tok.is(tok::period) &&
|
2010-07-03 01:43:08 +08:00
|
|
|
(Actions.getTypeName(II, ILoc, getCurScope()) ||
|
2010-04-12 14:20:33 +08:00
|
|
|
// Allow the base to be 'super' if in an objc-method.
|
2010-07-03 01:43:08 +08:00
|
|
|
(&II == Ident_super && getCurScope()->isInObjcMethodScope()))) {
|
2011-01-18 10:00:16 +08:00
|
|
|
ConsumeToken();
|
2009-10-26 01:04:48 +08:00
|
|
|
|
2009-03-10 05:12:44 +08:00
|
|
|
if (Tok.isNot(tok::identifier)) {
|
2009-10-26 01:04:48 +08:00
|
|
|
Diag(Tok, diag::err_expected_property_name);
|
2009-03-10 05:12:44 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
IdentifierInfo &PropertyName = *Tok.getIdentifierInfo();
|
|
|
|
SourceLocation PropertyLoc = ConsumeToken();
|
2009-10-26 01:04:48 +08:00
|
|
|
|
|
|
|
Res = Actions.ActOnClassPropertyRefExpr(II, PropertyName,
|
|
|
|
ILoc, PropertyLoc);
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
2009-03-10 05:12:44 +08:00
|
|
|
}
|
2010-08-27 17:08:28 +08:00
|
|
|
|
2010-09-15 23:09:43 +08:00
|
|
|
// In an Objective-C method, if we have "super" followed by an identifier,
|
2010-09-16 00:23:04 +08:00
|
|
|
// the token sequence is ill-formed. However, if there's a ':' or ']' after
|
2010-09-15 23:09:43 +08:00
|
|
|
// that identifier, this is probably a message send with a missing open
|
2010-09-16 00:23:04 +08:00
|
|
|
// bracket. Treat it as such.
|
|
|
|
if (getLang().ObjC1 && &II == Ident_super && !InMessageExpression &&
|
2010-09-15 23:09:43 +08:00
|
|
|
getCurScope()->isInObjcMethodScope() &&
|
2010-09-16 00:23:04 +08:00
|
|
|
((Tok.is(tok::identifier) &&
|
|
|
|
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) ||
|
|
|
|
Tok.is(tok::code_completion))) {
|
2010-09-15 23:09:43 +08:00
|
|
|
Res = ParseObjCMessageExpressionBody(SourceLocation(), ILoc, ParsedType(),
|
|
|
|
0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2011-02-16 03:17:31 +08:00
|
|
|
// If we have an Objective-C class name followed by an identifier
|
|
|
|
// and either ':' or ']', this is an Objective-C class message
|
|
|
|
// send that's missing the opening '['. Recovery
|
|
|
|
// appropriately. Also take this path if we're performing code
|
|
|
|
// completion after an Objective-C class name.
|
|
|
|
if (getLang().ObjC1 &&
|
|
|
|
((Tok.is(tok::identifier) && !InMessageExpression) ||
|
|
|
|
Tok.is(tok::code_completion))) {
|
2010-09-16 09:51:54 +08:00
|
|
|
const Token& Next = NextToken();
|
2011-02-16 03:17:31 +08:00
|
|
|
if (Tok.is(tok::code_completion) ||
|
|
|
|
Next.is(tok::colon) || Next.is(tok::r_square))
|
2010-09-17 18:21:45 +08:00
|
|
|
if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope()))
|
|
|
|
if (Typ.get()->isObjCObjectOrInterfaceType()) {
|
2010-09-16 09:51:54 +08:00
|
|
|
// Fake up a Declarator to use with ActOnTypeName.
|
|
|
|
DeclSpec DS;
|
|
|
|
DS.SetRangeStart(ILoc);
|
|
|
|
DS.SetRangeEnd(ILoc);
|
|
|
|
const char *PrevSpec = 0;
|
|
|
|
unsigned DiagID;
|
2010-09-17 18:21:45 +08:00
|
|
|
DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ);
|
2010-09-16 09:51:54 +08:00
|
|
|
|
|
|
|
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
|
|
|
TypeResult Ty = Actions.ActOnTypeName(getCurScope(),
|
|
|
|
DeclaratorInfo);
|
|
|
|
if (Ty.isInvalid())
|
|
|
|
break;
|
|
|
|
|
|
|
|
Res = ParseObjCMessageExpressionBody(SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
Ty.get(), 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-27 17:08:28 +08:00
|
|
|
// Make sure to pass down the right value for isAddressOfOperand.
|
|
|
|
if (isAddressOfOperand && isPostfixExpressionSuffixStart())
|
|
|
|
isAddressOfOperand = false;
|
2009-10-26 01:04:48 +08:00
|
|
|
|
2006-11-20 14:49:47 +08:00
|
|
|
// 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.
|
2009-11-04 00:56:39 +08:00
|
|
|
UnqualifiedId Name;
|
|
|
|
CXXScopeSpec ScopeSpec;
|
|
|
|
Name.setIdentifier(&II, ILoc);
|
2010-07-03 01:43:08 +08:00
|
|
|
Res = Actions.ActOnIdExpression(getCurScope(), ScopeSpec, Name,
|
2010-08-27 17:08:28 +08:00
|
|
|
Tok.is(tok::l_paren), isAddressOfOperand);
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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:
|
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;
|
2010-08-06 22:50:36 +08:00
|
|
|
case tok::plusplus: // unary-expression: '++' unary-expression [C99]
|
|
|
|
case tok::minusminus: { // unary-expression: '--' unary-expression [C99]
|
|
|
|
// C++ [expr.unary] has:
|
|
|
|
// unary-expression:
|
|
|
|
// ++ cast-expression
|
|
|
|
// -- cast-expression
|
2006-10-25 11:38:23 +08:00
|
|
|
SourceLocation SavedLoc = ConsumeToken();
|
2010-08-06 22:50:36 +08:00
|
|
|
Res = ParseCastExpression(!getLang().CPlusPlus);
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!Res.isInvalid())
|
2010-08-24 07:25:46 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
|
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())
|
2010-08-24 07:25:46 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
|
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())
|
2010-08-24 07:25:46 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
|
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())
|
2010-08-24 07:25:46 +08:00
|
|
|
Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get());
|
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
|
|
|
|
2011-02-19 05:16:39 +08:00
|
|
|
if (getCurScope()->getFnParent() == 0)
|
|
|
|
return ExprError(Diag(Tok, diag::err_address_of_label_outside_fn));
|
|
|
|
|
2007-05-28 14:56:27 +08:00
|
|
|
Diag(AmpAmpLoc, diag::ext_gnu_address_of_label);
|
2011-02-18 09:27:55 +08:00
|
|
|
LabelDecl *LD = Actions.LookupOrCreateLabel(Tok.getIdentifierInfo(),
|
|
|
|
Tok.getLocation());
|
|
|
|
Res = Actions.ActOnAddrLabel(AmpAmpLoc, Tok.getLocation(), LD);
|
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();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
2008-11-11 19:37:55 +08:00
|
|
|
case tok::kw_typeid:
|
|
|
|
Res = ParseCXXTypeid();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
2010-09-08 20:20:18 +08:00
|
|
|
case tok::kw___uuidof:
|
|
|
|
Res = ParseCXXUuidof();
|
|
|
|
break;
|
2008-06-25 06:12:16 +08:00
|
|
|
case tok::kw_this:
|
2008-08-17 03:34:46 +08:00
|
|
|
Res = ParseCXXThis();
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
2008-08-22 23:38:55 +08:00
|
|
|
|
2010-09-16 09:51:54 +08:00
|
|
|
case tok::annot_typename:
|
|
|
|
if (isStartOfObjCClassMessageMissingOpenBracket()) {
|
|
|
|
ParsedType Type = getTypeAnnotation(Tok);
|
|
|
|
|
|
|
|
// Fake up a Declarator to use with ActOnTypeName.
|
|
|
|
DeclSpec DS;
|
|
|
|
DS.SetRangeStart(Tok.getLocation());
|
|
|
|
DS.SetRangeEnd(Tok.getLastLoc());
|
|
|
|
|
|
|
|
const char *PrevSpec = 0;
|
|
|
|
unsigned DiagID;
|
2010-11-22 18:30:56 +08:00
|
|
|
DS.SetTypeSpecType(TST_typename, Tok.getAnnotationEndLoc(),
|
|
|
|
PrevSpec, DiagID, Type);
|
2010-09-16 09:51:54 +08:00
|
|
|
|
|
|
|
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
|
|
|
TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
|
|
|
|
if (Ty.isInvalid())
|
|
|
|
break;
|
|
|
|
|
|
|
|
ConsumeToken();
|
|
|
|
Res = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
|
|
|
|
Ty.get(), 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Fall through
|
|
|
|
|
2008-08-22 23:38:55 +08:00
|
|
|
case tok::kw_char:
|
|
|
|
case tok::kw_wchar_t:
|
2009-07-14 14:30:34 +08:00
|
|
|
case tok::kw_char16_t:
|
|
|
|
case tok::kw_char32_t:
|
2008-08-22 23:38:55 +08:00
|
|
|
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:
|
2010-09-16 09:51:54 +08:00
|
|
|
case tok::kw___vector: {
|
2009-01-05 06:28:21 +08:00
|
|
|
if (!getLang().CPlusPlus) {
|
|
|
|
Diag(Tok, diag::err_expected_expression);
|
|
|
|
return ExprError();
|
|
|
|
}
|
2009-06-11 08:33:41 +08:00
|
|
|
|
|
|
|
if (SavedKind == tok::kw_typename) {
|
|
|
|
// postfix-expression: typename-specifier '(' expression-list[opt] ')'
|
2010-02-26 16:45:28 +08:00
|
|
|
if (TryAnnotateTypeOrScopeToken())
|
2009-06-11 08:33:41 +08:00
|
|
|
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);
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
2008-08-22 23:38:55 +08:00
|
|
|
}
|
|
|
|
|
2010-02-06 03:11:37 +08:00
|
|
|
case tok::annot_cxxscope: { // [C++] id-expression: qualified-id
|
2010-04-23 10:08:13 +08:00
|
|
|
// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
|
|
|
|
// (We can end up in this situation after tentative parsing.)
|
|
|
|
if (TryAnnotateTypeOrScopeToken())
|
|
|
|
return ExprError();
|
|
|
|
if (!Tok.is(tok::annot_cxxscope))
|
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
|
|
|
|
NotCastExpr, TypeOfCast);
|
|
|
|
|
2010-02-06 03:11:37 +08:00
|
|
|
Token Next = NextToken();
|
|
|
|
if (Next.is(tok::annot_template_id)) {
|
|
|
|
TemplateIdAnnotation *TemplateId
|
|
|
|
= static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue());
|
|
|
|
if (TemplateId->Kind == TNK_Type_template) {
|
|
|
|
// We have a qualified template-id that we know refers to a
|
|
|
|
// type, translate it into a type and continue parsing as a
|
|
|
|
// cast expression.
|
|
|
|
CXXScopeSpec SS;
|
2010-08-24 13:47:05 +08:00
|
|
|
ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false);
|
2011-03-02 08:47:37 +08:00
|
|
|
AnnotateTemplateIdTokenAsType();
|
2010-02-06 03:11:37 +08:00
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
|
|
|
|
NotCastExpr, TypeOfCast);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse as an id-expression.
|
|
|
|
Res = ParseCXXIdExpression(isAddressOfOperand);
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
2010-02-06 03:11:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case tok::annot_template_id: { // [C++] template-id
|
|
|
|
TemplateIdAnnotation *TemplateId
|
|
|
|
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
|
|
|
|
if (TemplateId->Kind == TNK_Type_template) {
|
|
|
|
// We have a template-id that we know refers to a type,
|
|
|
|
// translate it into a type and continue parsing as a cast
|
|
|
|
// expression.
|
|
|
|
AnnotateTemplateIdTokenAsType();
|
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
|
|
|
|
NotCastExpr, TypeOfCast);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through to treat the template-id as an id-expression.
|
|
|
|
}
|
|
|
|
|
2008-11-09 00:45:02 +08:00
|
|
|
case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
|
2009-02-04 04:19:35 +08:00
|
|
|
Res = ParseCXXIdExpression(isAddressOfOperand);
|
2010-08-24 07:25:46 +08:00
|
|
|
break;
|
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())
|
2010-02-26 16:45:28 +08:00
|
|
|
return ExprError();
|
|
|
|
if (!Tok.is(tok::coloncolon))
|
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-09-09 23:08:12 +08:00
|
|
|
|
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
|
|
|
|
2010-09-11 04:55:37 +08:00
|
|
|
case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')'
|
|
|
|
SourceLocation KeyLoc = ConsumeToken();
|
|
|
|
SourceLocation LParen = Tok.getLocation();
|
|
|
|
if (ExpectAndConsume(tok::l_paren,
|
|
|
|
diag::err_expected_lparen_after, "noexcept"))
|
|
|
|
return ExprError();
|
2010-09-11 05:57:27 +08:00
|
|
|
// C++ [expr.unary.noexcept]p1:
|
|
|
|
// The noexcept operator determines whether the evaluation of its operand,
|
|
|
|
// which is an unevaluated operand, can throw an exception.
|
|
|
|
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
|
2010-09-11 04:55:37 +08:00
|
|
|
ExprResult Result = ParseExpression();
|
|
|
|
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
|
|
|
|
if (!Result.isInvalid())
|
|
|
|
Result = Actions.ActOnNoexceptExpr(KeyLoc, LParen, Result.take(), RParen);
|
|
|
|
return move(Result);
|
|
|
|
}
|
|
|
|
|
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:
|
2009-08-16 05:55:26 +08:00
|
|
|
case tok::kw___is_empty:
|
2009-01-06 04:52:13 +08:00
|
|
|
case tok::kw___is_polymorphic:
|
2009-03-22 09:52:17 +08:00
|
|
|
case tok::kw___is_abstract:
|
2009-12-03 08:13:20 +08:00
|
|
|
case tok::kw___is_literal:
|
2009-04-16 08:08:20 +08:00
|
|
|
case tok::kw___has_trivial_constructor:
|
2009-07-24 07:49:00 +08:00
|
|
|
case tok::kw___has_trivial_copy:
|
|
|
|
case tok::kw___has_trivial_assign:
|
2009-04-17 10:34:54 +08:00
|
|
|
case tok::kw___has_trivial_destructor:
|
2010-08-31 12:59:00 +08:00
|
|
|
case tok::kw___has_nothrow_assign:
|
|
|
|
case tok::kw___has_nothrow_copy:
|
|
|
|
case tok::kw___has_nothrow_constructor:
|
2010-09-03 07:19:42 +08:00
|
|
|
case tok::kw___has_virtual_destructor:
|
2009-01-06 04:52:13 +08:00
|
|
|
return ParseUnaryTypeTrait();
|
|
|
|
|
2010-12-09 06:35:30 +08:00
|
|
|
case tok::kw___builtin_types_compatible_p:
|
2010-12-07 08:08:36 +08:00
|
|
|
case tok::kw___is_base_of:
|
2011-01-28 04:28:01 +08:00
|
|
|
case tok::kw___is_convertible_to:
|
2010-12-07 08:08:36 +08:00
|
|
|
return ParseBinaryTypeTrait();
|
|
|
|
|
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());
|
2010-04-06 23:09:27 +08:00
|
|
|
case tok::code_completion:
|
2010-08-27 07:41:50 +08:00
|
|
|
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
|
2010-05-25 13:58:43 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
2010-04-06 23:09:27 +08:00
|
|
|
return ParseCastExpression(isUnaryExpression, isAddressOfOperand,
|
|
|
|
NotCastExpr, TypeOfCast);
|
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());
|
2010-04-06 23:09:27 +08:00
|
|
|
// FALL THROUGH.
|
2006-08-11 04:56:00 +08:00
|
|
|
default:
|
2009-05-22 18:24:42 +08:00
|
|
|
NotCastExpr = true;
|
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
|
|
|
|
2010-08-24 07:25:46 +08:00
|
|
|
// These can be followed by postfix-expr pieces.
|
2010-09-18 09:28:11 +08:00
|
|
|
return ParsePostfixExpressionSuffix(Res);
|
2006-08-13 01:40:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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]
|
2011-01-04 03:31:53 +08:00
|
|
|
/// argument-expression ...[opt]
|
|
|
|
/// argument-expression-list ',' assignment-expression ...[opt]
|
2006-08-13 01:40:43 +08:00
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
|
|
|
Parser::ParsePostfixExpressionSuffix(ExprResult 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()) {
|
2010-09-16 00:23:04 +08:00
|
|
|
case tok::code_completion:
|
|
|
|
if (InMessageExpression)
|
|
|
|
return move(LHS);
|
|
|
|
|
2010-09-18 09:28:11 +08:00
|
|
|
Actions.CodeCompletePostfixExpression(getCurScope(), LHS);
|
2010-09-16 00:23:04 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
|
|
|
LHS = ExprError();
|
|
|
|
break;
|
|
|
|
|
2010-09-15 22:51:05 +08:00
|
|
|
case tok::identifier:
|
|
|
|
// If we see identifier: after an expression, and we're not already in a
|
|
|
|
// message send, then this is probably a message send with a missing
|
|
|
|
// opening bracket '['.
|
|
|
|
if (getLang().ObjC1 && !InMessageExpression &&
|
2010-09-15 22:54:45 +08:00
|
|
|
(NextToken().is(tok::colon) || NextToken().is(tok::r_square))) {
|
2010-09-15 22:51:05 +08:00
|
|
|
LHS = ParseObjCMessageExpressionBody(SourceLocation(), SourceLocation(),
|
|
|
|
ParsedType(), LHS.get());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fall through; this isn't a message send.
|
|
|
|
|
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 ']'
|
2010-06-01 02:18:22 +08:00
|
|
|
// If we have a array postfix expression that starts on a new line and
|
|
|
|
// Objective-C is enabled, it is highly likely that the user forgot a
|
|
|
|
// semicolon after the base expression and that the array postfix-expr is
|
|
|
|
// actually another message send. In this case, do some look-ahead to see
|
|
|
|
// if the contents of the square brackets are obviously not a valid
|
|
|
|
// expression and recover by pretending there is no suffix.
|
|
|
|
if (getLang().ObjC1 && Tok.isAtStartOfLine() &&
|
|
|
|
isSimpleObjCMessageExpression())
|
2010-05-31 22:40:22 +08:00
|
|
|
return move(LHS);
|
|
|
|
|
2006-10-16 14:12:55 +08:00
|
|
|
Loc = ConsumeBracket();
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult 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)) {
|
2010-08-24 07:25:46 +08:00
|
|
|
LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.take(), Loc,
|
|
|
|
Idx.take(), 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
|
|
|
|
2011-02-10 05:12:02 +08:00
|
|
|
case tok::l_paren: // p-e: p-e '(' argument-expression-list[opt] ')'
|
|
|
|
case tok::lesslessless: { // p-e: p-e '<<<' argument-expression-list '>>>'
|
|
|
|
// '(' argument-expression-list[opt] ')'
|
|
|
|
tok::TokenKind OpKind = Tok.getKind();
|
2010-09-15 22:51:05 +08:00
|
|
|
InMessageExpressionRAIIObject InMessage(*this, false);
|
|
|
|
|
2011-02-10 05:12:02 +08:00
|
|
|
Expr *ExecConfig = 0;
|
|
|
|
|
|
|
|
if (OpKind == tok::lesslessless) {
|
|
|
|
ExprVector ExecConfigExprs(Actions);
|
|
|
|
CommaLocsTy ExecConfigCommaLocs;
|
|
|
|
SourceLocation LLLLoc, GGGLoc;
|
|
|
|
|
|
|
|
LLLLoc = ConsumeToken();
|
|
|
|
|
|
|
|
if (ParseExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) {
|
|
|
|
LHS = ExprError();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (LHS.isInvalid()) {
|
|
|
|
SkipUntil(tok::greatergreatergreater);
|
|
|
|
} else if (Tok.isNot(tok::greatergreatergreater)) {
|
|
|
|
MatchRHSPunctuation(tok::greatergreatergreater, LLLLoc);
|
|
|
|
LHS = ExprError();
|
|
|
|
} else {
|
|
|
|
GGGLoc = ConsumeToken();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!LHS.isInvalid()) {
|
|
|
|
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, ""))
|
|
|
|
LHS = ExprError();
|
|
|
|
else
|
|
|
|
Loc = PrevTokLocation;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!LHS.isInvalid()) {
|
|
|
|
ExprResult ECResult = Actions.ActOnCUDAExecConfigExpr(getCurScope(),
|
|
|
|
LLLLoc, move_arg(ExecConfigExprs), GGGLoc);
|
|
|
|
if (ECResult.isInvalid())
|
|
|
|
LHS = ExprError();
|
|
|
|
else
|
|
|
|
ExecConfig = ECResult.get();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Loc = ConsumeParen();
|
|
|
|
}
|
|
|
|
|
2008-11-26 06:21:31 +08:00
|
|
|
ExprVector ArgExprs(Actions);
|
2008-08-17 04:03:01 +08:00
|
|
|
CommaLocsTy CommaLocs;
|
2010-09-18 09:28:11 +08:00
|
|
|
|
2009-09-22 23:41:20 +08:00
|
|
|
if (Tok.is(tok::code_completion)) {
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.CodeCompleteCall(getCurScope(), LHS.get(), 0, 0);
|
2010-05-25 13:58:43 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
2009-09-22 23:41:20 +08:00
|
|
|
}
|
2011-02-10 05:12:02 +08:00
|
|
|
|
|
|
|
if (OpKind == tok::l_paren || !LHS.isInvalid()) {
|
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
|
|
|
if (ParseExpressionList(ArgExprs, CommaLocs, &Sema::CodeCompleteCall,
|
|
|
|
LHS.get())) {
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
LHS = 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 ')'.
|
2010-09-18 09:28:11 +08:00
|
|
|
if (LHS.isInvalid()) {
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
} else if (Tok.isNot(tok::r_paren)) {
|
2009-04-13 08:10:38 +08:00
|
|
|
MatchRHSPunctuation(tok::r_paren, Loc);
|
2010-09-18 09:28:11 +08:00
|
|
|
LHS = ExprError();
|
|
|
|
} else {
|
|
|
|
assert((ArgExprs.size() == 0 ||
|
|
|
|
ArgExprs.size()-1 == CommaLocs.size())&&
|
2006-08-24 12:40:38 +08:00
|
|
|
"Unexpected number of commas!");
|
2010-08-24 07:25:46 +08:00
|
|
|
LHS = Actions.ActOnCallExpr(getCurScope(), LHS.take(), Loc,
|
2011-02-10 05:12:02 +08:00
|
|
|
move_arg(ArgExprs), Tok.getLocation(),
|
|
|
|
ExecConfig);
|
2010-09-18 09:28:11 +08:00
|
|
|
ConsumeParen();
|
2006-08-24 12:40:38 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-08-11 14:41:18 +08:00
|
|
|
break;
|
2006-08-24 11:51:22 +08:00
|
|
|
}
|
2009-09-09 08:23:06 +08:00
|
|
|
case tok::arrow:
|
|
|
|
case tok::period: {
|
|
|
|
// postfix-expression: p-e '->' template[opt] id-expression
|
|
|
|
// postfix-expression: p-e '.' template[opt] id-expression
|
2006-08-24 11:51:22 +08:00
|
|
|
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
|
|
|
|
2009-08-06 11:17:00 +08:00
|
|
|
CXXScopeSpec SS;
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType ObjectType;
|
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
llvm-svn: 97045
2010-02-25 02:44:31 +08:00
|
|
|
bool MayBePseudoDestructor = false;
|
2009-08-06 11:17:00 +08:00
|
|
|
if (getLang().CPlusPlus && !LHS.isInvalid()) {
|
2010-08-24 07:25:46 +08:00
|
|
|
LHS = Actions.ActOnStartCXXMemberReference(getCurScope(), LHS.take(),
|
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
llvm-svn: 97045
2010-02-25 02:44:31 +08:00
|
|
|
OpLoc, OpKind, ObjectType,
|
|
|
|
MayBePseudoDestructor);
|
2009-08-06 11:17:00 +08:00
|
|
|
if (LHS.isInvalid())
|
|
|
|
break;
|
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
llvm-svn: 97045
2010-02-25 02:44:31 +08:00
|
|
|
|
2010-02-25 12:46:04 +08:00
|
|
|
ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
|
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
llvm-svn: 97045
2010-02-25 02:44:31 +08:00
|
|
|
&MayBePseudoDestructor);
|
2010-05-27 23:25:59 +08:00
|
|
|
if (SS.isNotEmpty())
|
2010-08-24 13:47:05 +08:00
|
|
|
ObjectType = ParsedType();
|
2009-08-06 11:17:00 +08:00
|
|
|
}
|
|
|
|
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
llvm-svn: 82166
2009-09-18 05:32:03 +08:00
|
|
|
if (Tok.is(tok::code_completion)) {
|
|
|
|
// Code completion for a member access expression.
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.CodeCompleteMemberReferenceExpr(getCurScope(), LHS.get(),
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
llvm-svn: 82166
2009-09-18 05:32:03 +08:00
|
|
|
OpLoc, OpKind == tok::arrow);
|
|
|
|
|
2010-05-25 13:58:43 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
Initial implementation of a code-completion interface in Clang. In
essence, code completion is triggered by a magic "code completion"
token produced by the lexer [*], which the parser recognizes at
certain points in the grammar. The parser then calls into the Action
object with the appropriate CodeCompletionXXX action.
Sema implements the CodeCompletionXXX callbacks by performing minimal
translation, then forwarding them to a CodeCompletionConsumer
subclass, which uses the results of semantic analysis to provide
code-completion results. At present, only a single, "printing" code
completion consumer is available, for regression testing and
debugging. However, the design is meant to permit other
code-completion consumers.
This initial commit contains two code-completion actions: one for
member access, e.g., "x." or "p->", and one for
nested-name-specifiers, e.g., "std::". More code-completion actions
will follow, along with improved gathering of code-completion results
for the various contexts.
[*] In the current -code-completion-dump testing/debugging mode, the
file is truncated at the completion point and EOF is translated into
"code completion".
llvm-svn: 82166
2009-09-18 05:32:03 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 07:25:46 +08:00
|
|
|
if (MayBePseudoDestructor && !LHS.isInvalid()) {
|
|
|
|
LHS = ParseCXXPseudoDestructor(LHS.take(), OpLoc, OpKind, SS,
|
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
llvm-svn: 97045
2010-02-25 02:44:31 +08:00
|
|
|
ObjectType);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Either the action has told is that this cannot be a
|
|
|
|
// pseudo-destructor expression (based on the type of base
|
|
|
|
// expression), or we didn't see a '~' in the right place. We
|
|
|
|
// can still parse a destructor name here, but in that case it
|
|
|
|
// names a real destructor.
|
2011-01-18 13:04:39 +08:00
|
|
|
// Allow explicit constructor calls in Microsoft mode.
|
|
|
|
// FIXME: Add support for explicit call of template constructor.
|
2009-11-04 03:44:04 +08:00
|
|
|
UnqualifiedId Name;
|
|
|
|
if (ParseUnqualifiedId(SS,
|
|
|
|
/*EnteringContext=*/false,
|
|
|
|
/*AllowDestructorName=*/true,
|
2011-01-18 13:04:39 +08:00
|
|
|
/*AllowConstructorName=*/ getLang().Microsoft,
|
2009-11-04 03:44:04 +08:00
|
|
|
ObjectType,
|
|
|
|
Name))
|
2010-09-18 09:28:11 +08:00
|
|
|
LHS = ExprError();
|
2009-11-04 03:44:04 +08:00
|
|
|
|
|
|
|
if (!LHS.isInvalid())
|
2010-08-24 07:25:46 +08:00
|
|
|
LHS = Actions.ActOnMemberAccessExpr(getCurScope(), LHS.take(), OpLoc,
|
Rework parsing of pseudo-destructor expressions and explicit
destructor calls, e.g.,
p->T::~T
We now detect when the member access that we've parsed, e.g.,
p-> or x.
may be a pseudo-destructor expression, either because the type of p or
x is a scalar or because it is dependent (and, therefore, may become a
scalar at template instantiation time).
We then parse the pseudo-destructor grammar specifically:
::[opt] nested-name-specifier[opt] type-name :: ∼ type-name
and hand those results to a new action, ActOnPseudoDestructorExpr,
which will cope with both dependent member accesses of destructors and
with pseudo-destructor expressions.
This commit affects the parsing of pseudo-destructors, only; the
semantic actions still go through the semantic actions for member
access expressions. That will change soon.
llvm-svn: 97045
2010-02-25 02:44:31 +08:00
|
|
|
OpKind, SS, Name, ObjCImpDecl,
|
2009-11-04 03:44:04 +08:00
|
|
|
Tok.is(tok::l_paren));
|
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::plusplus: // postfix-expression: postfix-expression '++'
|
|
|
|
case tok::minusminus: // postfix-expression: postfix-expression '--'
|
2008-12-09 21:15:23 +08:00
|
|
|
if (!LHS.isInvalid()) {
|
2010-07-03 01:43:08 +08:00
|
|
|
LHS = Actions.ActOnPostfixUnaryOp(getCurScope(), Tok.getLocation(),
|
2010-08-24 07:25:46 +08:00
|
|
|
Tok.getKind(), LHS.take());
|
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
|
|
|
}
|
|
|
|
|
2009-05-22 18:22:50 +08:00
|
|
|
/// ParseExprAfterTypeofSizeofAlignof - We parsed a typeof/sizeof/alignof and
|
|
|
|
/// we are at the start of an expression or a parenthesized type-id.
|
|
|
|
/// OpTok is the operand token (typeof/sizeof/alignof). Returns the expression
|
|
|
|
/// (isCastExpr == false) or the type (isCastExpr == true).
|
|
|
|
///
|
2006-08-11 10:13:20 +08:00
|
|
|
/// 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 ')'
|
2009-05-22 18:22:50 +08:00
|
|
|
///
|
|
|
|
/// [GNU] typeof-specifier:
|
|
|
|
/// typeof ( expressions )
|
|
|
|
/// typeof ( type-name )
|
|
|
|
/// [GNU/C++] typeof unary-expression
|
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2009-05-22 18:22:50 +08:00
|
|
|
Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
|
|
|
|
bool &isCastExpr,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType &CastTy,
|
2009-05-22 18:22:50 +08:00
|
|
|
SourceRange &CastRange) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
|
|
|
assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) ||
|
2009-05-22 18:22:50 +08:00
|
|
|
OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) &&
|
|
|
|
"Not a typeof/sizeof/alignof expression!");
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Operand;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-22 18:22:50 +08:00
|
|
|
// If the operand doesn't start with an '(', it must be an expression.
|
2007-10-10 01:41:39 +08:00
|
|
|
if (Tok.isNot(tok::l_paren)) {
|
2009-05-22 18:22:50 +08:00
|
|
|
isCastExpr = false;
|
|
|
|
if (OpTok.is(tok::kw_typeof) && !getLang().CPlusPlus) {
|
|
|
|
Diag(Tok,diag::err_expected_lparen_after_id) << OpTok.getIdentifierInfo();
|
|
|
|
return ExprError();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 07:52:42 +08:00
|
|
|
// C++0x [expr.sizeof]p1:
|
2009-09-09 23:08:12 +08:00
|
|
|
// [...] The operand is either an expression, which is an unevaluated
|
2009-06-20 07:52:42 +08:00
|
|
|
// operand (Clause 5) [...]
|
|
|
|
//
|
|
|
|
// The GNU typeof and alignof extensions also behave as unevaluated
|
|
|
|
// operands.
|
2009-06-23 04:57:11 +08:00
|
|
|
EnterExpressionEvaluationContext Unevaluated(Actions,
|
2010-08-27 07:41:50 +08:00
|
|
|
Sema::Unevaluated);
|
2009-05-22 18:22:50 +08:00
|
|
|
Operand = ParseCastExpression(true/*isUnaryExpression*/);
|
2006-08-24 14:10:04 +08:00
|
|
|
} 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:49:19 +08:00
|
|
|
SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-20 07:52:42 +08:00
|
|
|
// C++0x [expr.sizeof]p1:
|
2009-09-09 23:08:12 +08:00
|
|
|
// [...] The operand is either an expression, which is an unevaluated
|
2009-06-20 07:52:42 +08:00
|
|
|
// operand (Clause 5) [...]
|
|
|
|
//
|
|
|
|
// The GNU typeof and alignof extensions also behave as unevaluated
|
|
|
|
// operands.
|
2009-06-23 04:57:11 +08:00
|
|
|
EnterExpressionEvaluationContext Unevaluated(Actions,
|
2010-08-27 07:41:50 +08:00
|
|
|
Sema::Unevaluated);
|
2009-11-25 09:26:41 +08:00
|
|
|
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType(), CastTy, RParenLoc);
|
2009-05-22 18:22:50 +08:00
|
|
|
CastRange = SourceRange(LParenLoc, RParenLoc);
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2009-05-22 18:22:50 +08:00
|
|
|
// If ParseParenExpression parsed a '(typename)' sequence only, then this is
|
|
|
|
// a type.
|
|
|
|
if (ExprType == CastExpr) {
|
|
|
|
isCastExpr = true;
|
|
|
|
return ExprEmpty();
|
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2010-07-29 02:22:12 +08:00
|
|
|
if (getLang().CPlusPlus || OpTok.isNot(tok::kw_typeof)) {
|
|
|
|
// GNU typeof in C requires the expression to be parenthesized. Not so for
|
|
|
|
// sizeof/alignof or in C++. Therefore, the parenthesized expression is
|
|
|
|
// the start of a unary-expression, but doesn't include any postfix
|
|
|
|
// pieces. Parse these now if present.
|
2010-08-25 07:41:43 +08:00
|
|
|
if (!Operand.isInvalid())
|
|
|
|
Operand = ParsePostfixExpressionSuffix(Operand.get());
|
2010-07-29 02:22:12 +08:00
|
|
|
}
|
2006-08-24 14:10:04 +08:00
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2009-05-22 18:22:50 +08:00
|
|
|
// If we get here, the operand to the typeof/sizeof/alignof was an expresion.
|
|
|
|
isCastExpr = false;
|
|
|
|
return move(Operand);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression.
|
|
|
|
/// unary-expression: [C99 6.5.3]
|
|
|
|
/// 'sizeof' unary-expression
|
|
|
|
/// 'sizeof' '(' type-name ')'
|
2011-01-05 01:33:58 +08:00
|
|
|
/// [C++0x] 'sizeof' '...' '(' identifier ')'
|
2009-05-22 18:22:50 +08:00
|
|
|
/// [GNU] '__alignof' unary-expression
|
|
|
|
/// [GNU] '__alignof' '(' type-name ')'
|
|
|
|
/// [C++0x] 'alignof' '(' type-id ')'
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseSizeofAlignofExpression() {
|
2009-05-22 18:22:50 +08:00
|
|
|
assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof)
|
|
|
|
|| Tok.is(tok::kw_alignof)) &&
|
|
|
|
"Not a sizeof/alignof expression!");
|
|
|
|
Token OpTok = Tok;
|
|
|
|
ConsumeToken();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-01-05 01:33:58 +08:00
|
|
|
// [C++0x] 'sizeof' '...' '(' identifier ')'
|
|
|
|
if (Tok.is(tok::ellipsis) && OpTok.is(tok::kw_sizeof)) {
|
|
|
|
SourceLocation EllipsisLoc = ConsumeToken();
|
|
|
|
SourceLocation LParenLoc, RParenLoc;
|
|
|
|
IdentifierInfo *Name = 0;
|
|
|
|
SourceLocation NameLoc;
|
|
|
|
if (Tok.is(tok::l_paren)) {
|
|
|
|
LParenLoc = ConsumeParen();
|
|
|
|
if (Tok.is(tok::identifier)) {
|
|
|
|
Name = Tok.getIdentifierInfo();
|
|
|
|
NameLoc = ConsumeToken();
|
|
|
|
RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
|
|
|
if (RParenLoc.isInvalid())
|
|
|
|
RParenLoc = PP.getLocForEndOfToken(NameLoc);
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_expected_parameter_pack);
|
|
|
|
SkipUntil(tok::r_paren);
|
|
|
|
}
|
|
|
|
} else if (Tok.is(tok::identifier)) {
|
|
|
|
Name = Tok.getIdentifierInfo();
|
|
|
|
NameLoc = ConsumeToken();
|
|
|
|
LParenLoc = PP.getLocForEndOfToken(EllipsisLoc);
|
|
|
|
RParenLoc = PP.getLocForEndOfToken(NameLoc);
|
|
|
|
Diag(LParenLoc, diag::err_paren_sizeof_parameter_pack)
|
|
|
|
<< Name
|
|
|
|
<< FixItHint::CreateInsertion(LParenLoc, "(")
|
|
|
|
<< FixItHint::CreateInsertion(RParenLoc, ")");
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_sizeof_parameter_pack);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!Name)
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
return Actions.ActOnSizeofParameterPackExpr(getCurScope(),
|
|
|
|
OpTok.getLocation(),
|
|
|
|
*Name, NameLoc,
|
|
|
|
RParenLoc);
|
|
|
|
}
|
|
|
|
|
2009-05-22 18:22:50 +08:00
|
|
|
bool isCastExpr;
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType CastTy;
|
2009-05-22 18:22:50 +08:00
|
|
|
SourceRange CastRange;
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok,
|
2009-05-22 18:22:50 +08:00
|
|
|
isCastExpr,
|
|
|
|
CastTy,
|
|
|
|
CastRange);
|
|
|
|
|
|
|
|
if (isCastExpr)
|
|
|
|
return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(),
|
|
|
|
OpTok.is(tok::kw_sizeof),
|
2010-08-24 13:47:05 +08:00
|
|
|
/*isType=*/true,
|
|
|
|
CastTy.getAsOpaquePtr(),
|
2009-05-22 18:22:50 +08:00
|
|
|
CastRange);
|
|
|
|
|
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,
|
2009-05-22 18:22:50 +08:00
|
|
|
Operand.release(), CastRange);
|
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 ')'
|
2009-09-09 23:08:12 +08:00
|
|
|
///
|
2006-08-13 03:16:08 +08:00
|
|
|
/// [GNU] offsetof-member-designator:
|
|
|
|
/// [GNU] identifier
|
|
|
|
/// [GNU] offsetof-member-designator '.' identifier
|
|
|
|
/// [GNU] offsetof-member-designator '[' expression ']'
|
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Parser::ParseBuiltinPrimaryExpression() {
|
|
|
|
ExprResult Res;
|
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: {
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Expr(ParseAssignmentExpression());
|
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))
|
2010-09-18 09:28:11 +08:00
|
|
|
Expr = 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);
|
2010-09-18 09:28:11 +08:00
|
|
|
Expr = ExprError();
|
2007-10-16 04:28:48 +08:00
|
|
|
}
|
2010-09-18 09:28:11 +08:00
|
|
|
|
|
|
|
if (Expr.isInvalid() || Ty.isInvalid())
|
2009-02-19 01:45:20 +08:00
|
|
|
Res = ExprError();
|
|
|
|
else
|
2010-08-24 07:25:46 +08:00
|
|
|
Res = Actions.ActOnVAArg(StartLoc, Expr.take(), 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();
|
|
|
|
}
|
2009-09-09 23:08:12 +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: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.
|
2010-08-27 07:41:50 +08:00
|
|
|
llvm::SmallVector<Sema::OffsetOfComponent, 4> Comps;
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2010-08-27 07:41:50 +08:00
|
|
|
Comps.push_back(Sema::OffsetOfComponent());
|
2007-08-30 23:51:11 +08:00
|
|
|
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
|
2010-08-27 07:41:50 +08:00
|
|
|
Comps.push_back(Sema::OffsetOfComponent());
|
2007-08-30 23:51:11 +08:00
|
|
|
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 ']'
|
2010-08-27 07:41:50 +08:00
|
|
|
Comps.push_back(Sema::OffsetOfComponent());
|
2007-08-30 23:51:11 +08:00
|
|
|
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);
|
2009-06-28 04:38:33 +08:00
|
|
|
} else {
|
|
|
|
if (Tok.isNot(tok::r_paren)) {
|
|
|
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
|
|
|
Res = ExprError();
|
|
|
|
} else if (Ty.isInvalid()) {
|
2009-02-19 01:45:20 +08:00
|
|
|
Res = ExprError();
|
2009-06-28 04:38:33 +08:00
|
|
|
} else {
|
2010-07-03 01:43:08 +08:00
|
|
|
Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc,
|
2009-09-09 23:08:12 +08:00
|
|
|
Ty.get(), &Comps[0],
|
2009-02-19 01:45:20 +08:00
|
|
|
Comps.size(), ConsumeParen());
|
2009-06-28 04:38:33 +08:00
|
|
|
}
|
2007-08-30 23:52:49 +08:00
|
|
|
break;
|
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: {
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult 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();
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult 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();
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult 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
|
|
|
}
|
2010-08-24 07:25:46 +08:00
|
|
|
Res = Actions.ActOnChooseExpr(StartLoc, Cond.take(), Expr1.take(),
|
|
|
|
Expr2.take(), ConsumeParen());
|
2007-08-30 23:52:49 +08:00
|
|
|
break;
|
2007-08-04 05:21:27 +08:00
|
|
|
}
|
2008-12-12 05:36:32 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 07:25:46 +08:00
|
|
|
if (Res.isInvalid())
|
|
|
|
return ExprError();
|
|
|
|
|
2006-08-13 03:16:08 +08:00
|
|
|
// These can be followed by postfix-expr pieces because they are
|
|
|
|
// primary-expressions.
|
2010-08-24 07:25:46 +08:00
|
|
|
return ParsePostfixExpressionSuffix(Res.take());
|
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
|
2009-05-22 18:23:40 +08:00
|
|
|
/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
|
|
|
|
/// not the parsed cast-expression.
|
2006-08-11 09:33:00 +08:00
|
|
|
///
|
|
|
|
/// 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
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2009-05-22 18:23:40 +08:00
|
|
|
Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
2010-08-24 13:47:05 +08:00
|
|
|
ParsedType TypeOfCast, ParsedType &CastTy,
|
2009-08-11 07:49:36 +08:00
|
|
|
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();
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Result(true);
|
2009-05-22 18:24:42 +08:00
|
|
|
bool isAmbiguousTypeId;
|
2010-08-24 13:47:05 +08:00
|
|
|
CastTy = ParsedType();
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2010-09-15 07:59:36 +08:00
|
|
|
if (Tok.is(tok::code_completion)) {
|
|
|
|
Actions.CodeCompleteOrdinaryName(getCurScope(),
|
|
|
|
ExprType >= CompoundLiteral? Sema::PCC_ParenthesizedExpression
|
|
|
|
: Sema::PCC_Expression);
|
|
|
|
ConsumeCodeCompletionToken();
|
|
|
|
return ExprError();
|
|
|
|
}
|
|
|
|
|
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);
|
2010-12-24 10:08:15 +08:00
|
|
|
ParsedAttributes attrs;
|
|
|
|
StmtResult Stmt(ParseCompoundStatement(attrs, 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))
|
2010-08-24 07:25:46 +08:00
|
|
|
Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation());
|
2008-12-09 21:15:23 +08:00
|
|
|
|
2009-05-22 18:24:42 +08:00
|
|
|
} else if (ExprType >= CompoundLiteral &&
|
|
|
|
isTypeIdInParens(isAmbiguousTypeId)) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2006-08-13 00:54:25 +08:00
|
|
|
// Otherwise, this is a compound literal expression or cast expression.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-05-22 18:24:42 +08:00
|
|
|
// In C++, if the type-id is ambiguous we disambiguate based on context.
|
|
|
|
// If stopIfCastExpr is true the context is a typeof/sizeof/alignof
|
|
|
|
// in which case we should treat it as type-id.
|
|
|
|
// if stopIfCastExpr is false, we need to determine the context past the
|
|
|
|
// parens, so we defer to ParseCXXAmbiguousParenExpression for that.
|
|
|
|
if (isAmbiguousTypeId && !stopIfCastExpr)
|
|
|
|
return ParseCXXAmbiguousParenExpression(ExprType, CastTy,
|
|
|
|
OpenLoc, RParenLoc);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-09-15 22:51:05 +08:00
|
|
|
TypeResult Ty;
|
|
|
|
|
|
|
|
{
|
|
|
|
InMessageExpressionRAIIObject InMessage(*this, false);
|
|
|
|
Ty = ParseTypeName();
|
|
|
|
}
|
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
// If our type is followed by an identifier and either ':' or ']', then
|
|
|
|
// this is probably an Objective-C message send where the leading '[' is
|
|
|
|
// missing. Recover as if that were the case.
|
|
|
|
if (!Ty.isInvalid() && Tok.is(tok::identifier) && !InMessageExpression &&
|
|
|
|
getLang().ObjC1 && !Ty.get().get().isNull() &&
|
|
|
|
(NextToken().is(tok::colon) || NextToken().is(tok::r_square)) &&
|
|
|
|
Ty.get().get()->isObjCObjectOrInterfaceType()) {
|
|
|
|
Result = ParseObjCMessageExpressionBody(SourceLocation(),
|
|
|
|
SourceLocation(),
|
|
|
|
Ty.get(), 0);
|
|
|
|
} else {
|
|
|
|
// Match the ')'.
|
|
|
|
if (Tok.is(tok::r_paren))
|
|
|
|
RParenLoc = ConsumeParen();
|
|
|
|
else
|
|
|
|
MatchRHSPunctuation(tok::r_paren, OpenLoc);
|
|
|
|
|
|
|
|
if (Tok.is(tok::l_brace)) {
|
|
|
|
ExprType = CompoundLiteral;
|
|
|
|
return ParseCompoundLiteralExpression(Ty.get(), OpenLoc, RParenLoc);
|
|
|
|
}
|
2008-12-12 06:33:27 +08:00
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
if (ExprType == CastExpr) {
|
|
|
|
// We parsed '(' type-name ')' and the thing after it wasn't a '{'.
|
2009-01-20 06:31:54 +08:00
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
if (Ty.isInvalid())
|
|
|
|
return ExprError();
|
2009-02-19 01:45:20 +08:00
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
CastTy = Ty.get();
|
2009-02-19 01:45:20 +08:00
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
// Note that this doesn't parse the subsequent cast-expression, it just
|
|
|
|
// returns the parsed type to the callee.
|
|
|
|
if (stopIfCastExpr)
|
|
|
|
return ExprResult();
|
|
|
|
|
|
|
|
// Reject the cast of super idiom in ObjC.
|
|
|
|
if (Tok.is(tok::identifier) && getLang().ObjC1 &&
|
|
|
|
Tok.getIdentifierInfo() == Ident_super &&
|
|
|
|
getCurScope()->isInObjcMethodScope() &&
|
|
|
|
GetLookAheadToken(1).isNot(tok::period)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_illegal_super_cast)
|
|
|
|
<< SourceRange(OpenLoc, RParenLoc);
|
|
|
|
return ExprError();
|
|
|
|
}
|
2009-05-22 18:23:40 +08:00
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
// Parse the cast-expression that follows it next.
|
|
|
|
// TODO: For cast expression with CastTy.
|
|
|
|
Result = ParseCastExpression(false, false, CastTy);
|
|
|
|
if (!Result.isInvalid())
|
|
|
|
Result = Actions.ActOnCastExpr(getCurScope(), OpenLoc, CastTy,
|
|
|
|
RParenLoc, Result.take());
|
|
|
|
return move(Result);
|
2010-04-11 16:28:14 +08:00
|
|
|
}
|
2009-05-22 18:23:40 +08:00
|
|
|
|
2010-09-16 07:19:31 +08:00
|
|
|
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
|
|
|
|
return ExprError();
|
2006-08-11 07:56:11 +08:00
|
|
|
}
|
2009-11-25 09:26:41 +08:00
|
|
|
} else if (TypeOfCast) {
|
2009-08-11 07:49:36 +08:00
|
|
|
// Parse the expression-list.
|
2010-09-15 22:51:05 +08:00
|
|
|
InMessageExpressionRAIIObject InMessage(*this, false);
|
|
|
|
|
2009-08-11 07:49:36 +08:00
|
|
|
ExprVector ArgExprs(Actions);
|
|
|
|
CommaLocsTy CommaLocs;
|
|
|
|
|
|
|
|
if (!ParseExpressionList(ArgExprs, CommaLocs)) {
|
|
|
|
ExprType = SimpleExpr;
|
2009-11-25 09:26:41 +08:00
|
|
|
Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(),
|
|
|
|
move_arg(ArgExprs), TypeOfCast);
|
2009-08-11 07:49:36 +08:00
|
|
|
}
|
2006-08-11 09:33:00 +08:00
|
|
|
} else {
|
2010-09-15 22:51:05 +08:00
|
|
|
InMessageExpressionRAIIObject InMessage(*this, false);
|
|
|
|
|
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))
|
2010-08-24 07:25:46 +08:00
|
|
|
Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take());
|
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
|
|
|
}
|
2009-09-09 23:08:12 +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
|
|
|
|
2009-05-22 18:24:05 +08:00
|
|
|
/// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name
|
|
|
|
/// and we are at the left brace.
|
|
|
|
///
|
|
|
|
/// postfix-expression: [C99 6.5.2]
|
|
|
|
/// '(' type-name ')' '{' initializer-list '}'
|
|
|
|
/// '(' type-name ')' '{' initializer-list ',' '}'
|
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult
|
2010-08-24 13:47:05 +08:00
|
|
|
Parser::ParseCompoundLiteralExpression(ParsedType Ty,
|
2009-05-22 18:24:05 +08:00
|
|
|
SourceLocation LParenLoc,
|
|
|
|
SourceLocation RParenLoc) {
|
|
|
|
assert(Tok.is(tok::l_brace) && "Not a compound literal!");
|
|
|
|
if (!getLang().C99) // Compound literals don't exist in C90.
|
|
|
|
Diag(LParenLoc, diag::ext_c99_compound_literal);
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Result = ParseInitializer();
|
2009-05-22 18:24:05 +08:00
|
|
|
if (!Result.isInvalid() && Ty)
|
2010-08-24 07:25:46 +08:00
|
|
|
return Actions.ActOnCompoundLiteral(LParenLoc, Ty, RParenLoc, Result.take());
|
2009-05-22 18:24:05 +08:00
|
|
|
return move(Result);
|
|
|
|
}
|
|
|
|
|
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
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult 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.
|
2010-08-31 01:47:05 +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:
|
2011-01-04 03:31:53 +08:00
|
|
|
/// [C++] assignment-expression ...[opt]
|
|
|
|
/// [C++] expression-list , assignment-expression ...[opt]
|
2008-08-17 04:03:01 +08:00
|
|
|
///
|
2010-08-23 14:44:23 +08:00
|
|
|
bool Parser::ParseExpressionList(llvm::SmallVectorImpl<Expr*> &Exprs,
|
|
|
|
llvm::SmallVectorImpl<SourceLocation> &CommaLocs,
|
2010-08-27 07:41:50 +08:00
|
|
|
void (Sema::*Completer)(Scope *S,
|
2010-08-23 14:44:23 +08:00
|
|
|
Expr *Data,
|
|
|
|
Expr **Args,
|
2009-09-22 23:41:20 +08:00
|
|
|
unsigned NumArgs),
|
2010-08-23 14:44:23 +08:00
|
|
|
Expr *Data) {
|
2008-08-17 04:03:01 +08:00
|
|
|
while (1) {
|
2009-09-22 23:41:20 +08:00
|
|
|
if (Tok.is(tok::code_completion)) {
|
|
|
|
if (Completer)
|
2010-07-03 01:43:08 +08:00
|
|
|
(Actions.*Completer)(getCurScope(), Data, Exprs.data(), Exprs.size());
|
2011-02-17 11:09:23 +08:00
|
|
|
else
|
|
|
|
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression);
|
2010-05-25 13:58:43 +08:00
|
|
|
ConsumeCodeCompletionToken();
|
2009-09-22 23:41:20 +08:00
|
|
|
}
|
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Expr(ParseAssignmentExpression());
|
2011-01-04 03:31:53 +08:00
|
|
|
if (Tok.is(tok::ellipsis))
|
|
|
|
Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());
|
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() {
|
2010-10-19 05:34:55 +08:00
|
|
|
if (Tok.is(tok::code_completion)) {
|
|
|
|
Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
|
|
|
|
ConsumeCodeCompletionToken();
|
|
|
|
}
|
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// 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.
|
2010-12-24 10:08:15 +08:00
|
|
|
DeclaratorInfo.addAttributes(DS.takeAttributes());
|
2009-04-30 05:40:37 +08:00
|
|
|
|
2010-12-24 10:08:15 +08:00
|
|
|
MaybeParseGNUAttributes(DeclaratorInfo);
|
2009-04-30 03:03:13 +08:00
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// Inform sema that we are starting a block.
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockArguments(DeclaratorInfo, getCurScope());
|
2009-02-05 06:31:32 +08:00
|
|
|
}
|
|
|
|
|
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 ')'
|
|
|
|
///
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult 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");
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
// Enter a scope to hold everything within the block. This includes the
|
2008-08-29 03:20:44 +08:00
|
|
|
// 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.
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockStart(CaretLoc, getCurScope());
|
2009-09-09 23:08: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.
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockError(CaretLoc, getCurScope());
|
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
|
|
|
|
2010-12-24 10:08:15 +08:00
|
|
|
MaybeParseGNUAttributes(ParamInfo);
|
2009-04-30 03:03:13 +08:00
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// Inform sema that we are starting a block.
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockArguments(ParamInfo, getCurScope());
|
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).
|
2010-12-24 10:08:15 +08:00
|
|
|
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(),
|
|
|
|
true, false,
|
2009-02-18 15:07:28 +08:00
|
|
|
SourceLocation(),
|
2009-04-30 01:30:04 +08:00
|
|
|
0, 0, 0,
|
2011-01-26 11:43:54 +08:00
|
|
|
true, SourceLocation(),
|
2011-03-06 06:42:13 +08:00
|
|
|
EST_None,
|
|
|
|
SourceLocation(),
|
|
|
|
0, 0, 0, 0,
|
2009-08-20 07:14:54 +08:00
|
|
|
CaretLoc, CaretLoc,
|
|
|
|
ParamInfo),
|
2009-02-10 02:23:29 +08:00
|
|
|
CaretLoc);
|
2009-04-30 03:03:13 +08:00
|
|
|
|
2010-12-24 10:08:15 +08:00
|
|
|
MaybeParseGNUAttributes(ParamInfo);
|
2009-04-30 03:03:13 +08:00
|
|
|
|
2009-02-05 06:31:32 +08:00
|
|
|
// Inform sema that we are starting a block.
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockArguments(ParamInfo, getCurScope());
|
2008-08-29 03:20:44 +08:00
|
|
|
}
|
|
|
|
|
2008-12-13 23:32:12 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
ExprResult Result(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);
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockError(CaretLoc, getCurScope());
|
2009-01-15 03:39:53 +08:00
|
|
|
return ExprError();
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-24 14:29:42 +08:00
|
|
|
StmtResult Stmt(ParseCompoundStatementBody());
|
2009-03-27 12:18:06 +08:00
|
|
|
if (!Stmt.isInvalid())
|
2010-08-24 07:25:46 +08:00
|
|
|
Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope());
|
2009-03-27 12:18:06 +08:00
|
|
|
else
|
2010-07-03 01:43:08 +08:00
|
|
|
Actions.ActOnBlockError(CaretLoc, getCurScope());
|
2008-12-13 23:32:12 +08:00
|
|
|
return move(Result);
|
2008-08-29 03:20:44 +08:00
|
|
|
}
|