diff options
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 158 |
1 files changed, 95 insertions, 63 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 6d31396..8d4668b 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -6,17 +6,19 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// 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 -// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are -// handled by ParseCastExpression, the higher level pieces are handled by -// ParseBinaryExpression. -// +/// +/// \file +/// \brief Provides 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 +/// operator (e.g. '/') or a ternary operator ("?:"). The unary leaves are +/// handled by ParseCastExpression, the higher level pieces are handled by +/// ParseBinaryExpression. +/// //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" @@ -30,8 +32,7 @@ #include "llvm/ADT/SmallString.h" using namespace clang; -/// getBinOpPrecedence - Return the precedence of the specified binary operator -/// token. +/// \brief Return the precedence of the specified binary operator token. static prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus0x) { @@ -92,8 +93,7 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, } -/// ParseExpression - Simple precedence-based parser for binary/ternary -/// operators. +/// \brief Simple precedence-based parser for binary/ternary operators. /// /// Note: we diverge from the C99 grammar when parsing the assignment-expression /// production. C99 specifies that the LHS of an assignment operator should be @@ -104,6 +104,7 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// consistency, we parse the LHS as a conditional-expression, then check for /// l-value-ness in semantic analysis stages. /// +/// \verbatim /// pm-expression: [C++ 5.5] /// cast-expression /// pm-expression '.*' cast-expression @@ -175,6 +176,7 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// expression: [C99 6.5.17] /// assignment-expression ...[opt] /// expression ',' assignment-expression ...[opt] +/// \endverbatim ExprResult Parser::ParseExpression(TypeCastState isTypeCast) { ExprResult LHS(ParseAssignmentExpression(isTypeCast)); return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); @@ -182,8 +184,8 @@ ExprResult Parser::ParseExpression(TypeCastState isTypeCast) { /// This routine is called when the '@' is seen and consumed. /// Current token is an Identifier and is not a 'try'. This -/// routine is necessary to disambiguate @try-statement from, -/// for example, @encode-expression. +/// routine is necessary to disambiguate \@try-statement from, +/// for example, \@encode-expression. /// ExprResult Parser::ParseExpressionWithLeadingAt(SourceLocation AtLoc) { @@ -211,7 +213,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); } -/// ParseAssignmentExpression - Parse an expr that doesn't include commas. +/// \brief Parse an expr that doesn't include (top-level) commas. ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); @@ -228,11 +230,12 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment); } -/// 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. +/// \brief Parse an assignment expression where part of an Objective-C message +/// send has already been parsed. +/// +/// In this case \p LBracLoc indicates the location of the '[' of the message +/// send, and either \p ReceiverName or \p 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. @@ -262,8 +265,8 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { return Actions.ActOnConstantExpression(Res); } -/// ParseRHSOfBinaryExpression - Parse a binary expression that starts with -/// LHS and has a precedence of at least MinPrec. +/// \brief Parse a binary expression that starts with \p LHS and has a +/// precedence of at least \p MinPrec. ExprResult Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { prec::Level NextTokPrec = getBinOpPrecedence(Tok.getKind(), @@ -439,10 +442,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { } } -/// 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. +/// \brief Parse a cast-expression, or, if \p isUnaryExpression is true, +/// parse a unary-expression. +/// +/// \p isAddressOfOperand exists because an id-expression that is the +/// operand of address-of gets special treatment due to member pointers. /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, @@ -480,12 +484,15 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { }; } -/// 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. +/// \brief Parse a cast-expression, or, if \pisUnaryExpression is true, parse +/// a unary-expression. /// +/// \p 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. +/// +/// \verbatim /// cast-expression: [C99 6.5.4] /// unary-expression /// '(' type-name ')' cast-expression @@ -500,6 +507,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// [C++11] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' +/// [C11] '_Alignof' '(' type-name ')' /// [C++11] 'alignof' '(' type-id ')' /// [GNU] '&&' identifier /// [C++11] 'noexcept' '(' expression ')' [C++11 5.3.7] @@ -531,9 +539,9 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// [GNU] '__builtin_types_compatible_p' '(' type-name ',' type-name ')' /// [GNU] '__null' /// [OBJC] '[' objc-message-expr ']' -/// [OBJC] '@selector' '(' objc-selector-arg ')' -/// [OBJC] '@protocol' '(' identifier ')' -/// [OBJC] '@encode' '(' type-name ')' +/// [OBJC] '\@selector' '(' objc-selector-arg ')' +/// [OBJC] '\@protocol' '(' identifier ')' +/// [OBJC] '\@encode' '(' type-name ')' /// [OBJC] objc-string-literal /// [C++] simple-type-specifier '(' expression-list[opt] ')' [C++ 5.2.3] /// [C++11] simple-type-specifier braced-init-list [C++11 5.2.3] @@ -641,6 +649,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// [Embarcadero] expression-trait: /// '__is_lvalue_expr' /// '__is_rvalue_expr' +/// \endverbatim /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, @@ -846,6 +855,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, break; case tok::kw___func__: // primary-expression: __func__ [C99 6.4.2.2] case tok::kw___FUNCTION__: // primary-expression: __FUNCTION__ [GNU] + case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS] case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); ConsumeToken(); @@ -912,12 +922,15 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Res.get()); return move(Res); } - case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression - // unary-expression: 'sizeof' '(' type-name ')' - case tok::kw_alignof: + case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')' + if (!getLangOpts().C11) + Diag(Tok, diag::ext_c11_alignment) << Tok.getName(); + // fallthrough + case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')' case tok::kw___alignof: // unary-expression: '__alignof' unary-expression // unary-expression: '__alignof' '(' type-name ')' - // unary-expression: 'alignof' '(' type-id ')' + case tok::kw_sizeof: // unary-expression: 'sizeof' unary-expression + // unary-expression: 'sizeof' '(' type-name ')' case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier @@ -1228,9 +1241,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return ParsePostfixExpressionSuffix(Res); } -/// ParsePostfixExpressionSuffix - Once the leading part of a postfix-expression -/// is parsed, this method parses any suffixes that apply. +/// \brief Once the leading part of a postfix-expression is parsed, this +/// method parses any suffixes that apply. /// +/// \verbatim /// postfix-expression: [C99 6.5.2] /// primary-expression /// postfix-expression '[' expression ']' @@ -1246,7 +1260,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// argument-expression-list: [C99 6.5.2] /// argument-expression ...[opt] /// argument-expression-list ',' assignment-expression ...[opt] -/// +/// \endverbatim ExprResult Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // Now that the primary-expression piece of the postfix-expression has been @@ -1498,11 +1512,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /// type-id. OpTok is the operand token (typeof/sizeof/alignof). Returns the /// expression (isCastExpr == false) or the type (isCastExpr == true). /// +/// \verbatim /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' +/// [C11] '_Alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' /// /// [GNU] typeof-specifier: @@ -1513,7 +1529,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /// [OpenCL 1.1 6.11.12] vec_step built-in function: /// vec_step ( expressions ) /// vec_step ( type-name ) -/// +/// \endverbatim ExprResult Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, bool &isCastExpr, @@ -1522,7 +1538,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) || OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) || - OpTok.is(tok::kw_vec_step)) && + OpTok.is(tok::kw__Alignof) || OpTok.is(tok::kw_vec_step)) && "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; @@ -1571,17 +1587,22 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, } -/// ParseUnaryExprOrTypeTraitExpression - Parse a sizeof or alignof expression. +/// \brief Parse a sizeof or alignof expression. +/// +/// \verbatim /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' /// [C++0x] 'sizeof' '...' '(' identifier ')' /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' +/// [C11] '_Alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' +/// \endverbatim ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { - assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) - || Tok.is(tok::kw_alignof) || Tok.is(tok::kw_vec_step)) && + assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) || + Tok.is(tok::kw_alignof) || Tok.is(tok::kw__Alignof) || + Tok.is(tok::kw_vec_step)) && "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); @@ -1629,7 +1650,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { RParenLoc); } - if (OpTok.is(tok::kw_alignof)) + if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof)) Diag(OpTok, diag::warn_cxx98_compat_alignof); EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); @@ -1643,7 +1664,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { CastRange); UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; - if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof)) + if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof) || + OpTok.is(tok::kw__Alignof)) ExprKind = UETT_AlignOf; else if (OpTok.is(tok::kw_vec_step)) ExprKind = UETT_VecStep; @@ -1667,6 +1689,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { /// ParseBuiltinPrimaryExpression /// +/// \verbatim /// primary-expression: [C99 6.5.1] /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')' /// [GNU] '__builtin_offsetof' '(' type-name ',' offsetof-member-designator')' @@ -1679,7 +1702,7 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { /// [GNU] identifier /// [GNU] offsetof-member-designator '.' identifier /// [GNU] offsetof-member-designator '[' expression ']' -/// +/// \endverbatim ExprResult Parser::ParseBuiltinPrimaryExpression() { ExprResult Res; const IdentifierInfo *BuiltinII = Tok.getIdentifierInfo(); @@ -1869,6 +1892,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { /// in ExprType. If stopIfCastExpr is true, it will only return the parsed type, /// not the parsed cast-expression. /// +/// \verbatim /// primary-expression: [C99 6.5.1] /// '(' expression ')' /// [GNU] '(' compound-statement ')' (if !ParenExprOnly) @@ -1883,12 +1907,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { /// (__bridge type-name) cast-expression /// (__bridge_transfer type-name) cast-expression /// (__bridge_retained type-name) cast-expression +/// \endverbatim ExprResult Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, bool isTypeCast, ParsedType &CastTy, SourceLocation &RParenLoc) { assert(Tok.is(tok::l_paren) && "Not a paren expr!"); - GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) return ExprError(); @@ -2102,10 +2126,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, /// ParseCompoundLiteralExpression - We have parsed the parenthesized type-name /// and we are at the left brace. /// +/// \verbatim /// postfix-expression: [C99 6.5.2] /// '(' type-name ')' '{' initializer-list '}' /// '(' type-name ')' '{' initializer-list ',' '}' -/// +/// \endverbatim ExprResult Parser::ParseCompoundLiteralExpression(ParsedType Ty, SourceLocation LParenLoc, @@ -2123,8 +2148,10 @@ Parser::ParseCompoundLiteralExpression(ParsedType Ty, /// form string literals, and also handles string concatenation [C99 5.1.1.2, /// translation phase #6]. /// +/// \verbatim /// primary-expression: [C99 6.5.1] /// string-literal +/// \verbatim ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { assert(isTokenStringLiteral() && "Not a string literal!"); @@ -2145,6 +2172,7 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { /// ParseGenericSelectionExpression - Parse a C11 generic-selection /// [C11 6.5.1.1]. /// +/// \verbatim /// generic-selection: /// _Generic ( assignment-expression , generic-assoc-list ) /// generic-assoc-list: @@ -2153,6 +2181,7 @@ ExprResult Parser::ParseStringLiteralExpression(bool AllowUserDefinedLiteral) { /// generic-association: /// type-name : assignment-expression /// default : assignment-expression +/// \endverbatim ExprResult Parser::ParseGenericSelectionExpression() { assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected"); SourceLocation KeyLoc = ConsumeToken(); @@ -2239,6 +2268,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { /// ParseExpressionList - Used for C/C++ (argument-)expression-list. /// +/// \verbatim /// argument-expression-list: /// assignment-expression /// argument-expression-list , assignment-expression @@ -2257,7 +2287,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { /// [C++0x] initializer-clause: /// [C++0x] assignment-expression /// [C++0x] braced-init-list -/// +/// \endverbatim bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, SmallVectorImpl<SourceLocation> &CommaLocs, void (Sema::*Completer)(Scope *S, @@ -2297,10 +2327,11 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr*> &Exprs, /// ParseBlockId - Parse a block-id, which roughly looks like int (int x). /// +/// \verbatim /// [clang] block-id: /// [clang] specifier-qualifier-list block-declarator -/// -void Parser::ParseBlockId() { +/// \endverbatim +void Parser::ParseBlockId(SourceLocation CaretLoc) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); return cutOffParsing(); @@ -2320,18 +2351,19 @@ void Parser::ParseBlockId() { MaybeParseGNUAttributes(DeclaratorInfo); // Inform sema that we are starting a block. - Actions.ActOnBlockArguments(DeclaratorInfo, getCurScope()); + Actions.ActOnBlockArguments(CaretLoc, DeclaratorInfo, getCurScope()); } /// ParseBlockLiteralExpression - Parse a block literal, which roughly looks /// like ^(int x){ return x+1; } /// +/// \verbatim /// block-literal: /// [clang] '^' block-args[opt] compound-statement /// [clang] '^' block-id compound-statement /// [clang] block-args: /// [clang] '(' parameter-list ')' -/// +/// \endverbatim ExprResult Parser::ParseBlockLiteralExpression() { assert(Tok.is(tok::caret) && "block literal starts with ^"); SourceLocation CaretLoc = ConsumeToken(); @@ -2377,13 +2409,13 @@ ExprResult Parser::ParseBlockLiteralExpression() { MaybeParseGNUAttributes(ParamInfo); // Inform sema that we are starting a block. - Actions.ActOnBlockArguments(ParamInfo, getCurScope()); + Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope()); } else if (!Tok.is(tok::l_brace)) { - ParseBlockId(); + ParseBlockId(CaretLoc); } else { // Otherwise, pretend we saw (void). ParsedAttributes attrs(AttrFactory); - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, + ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), @@ -2400,7 +2432,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { MaybeParseGNUAttributes(ParamInfo); // Inform sema that we are starting a block. - Actions.ActOnBlockArguments(ParamInfo, getCurScope()); + Actions.ActOnBlockArguments(CaretLoc, ParamInfo, getCurScope()); } |