diff options
Diffstat (limited to 'lib/Parse/ParseExpr.cpp')
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 302 |
1 files changed, 250 insertions, 52 deletions
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 616c251..91fe1e1 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -174,7 +174,6 @@ static prec::Level getBinOpPrecedence(tok::TokenKind Kind, /// expression: [C99 6.5.17] /// assignment-expression ...[opt] /// expression ',' assignment-expression ...[opt] -/// ExprResult Parser::ParseExpression() { ExprResult LHS(ParseAssignmentExpression()); return ParseRHSOfBinaryExpression(move(LHS), prec::Comma); @@ -212,7 +211,6 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { } /// ParseAssignmentExpression - Parse an expr that doesn't include commas. -/// ExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); @@ -222,7 +220,7 @@ ExprResult Parser::ParseAssignmentExpression() { if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); - ExprResult LHS(ParseCastExpression(false)); + ExprResult LHS = ParseCastExpression(false, false, ParsedType()); return ParseRHSOfBinaryExpression(move(LHS), prec::Assignment); } @@ -415,8 +413,8 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { /// due to member pointers. /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand, - ParsedType TypeOfCast) { + bool isAddressOfOperand, + ParsedType TypeOfCast) { bool NotCastExpr; ExprResult Res = ParseCastExpression(isUnaryExpression, isAddressOfOperand, @@ -465,6 +463,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [C++] boolean-literal [C++ 2.13.5] /// [C++0x] 'nullptr' [C++0x 2.14.7] /// '(' expression ')' +/// [C1X] generic-selection /// '__func__' [C99 6.4.2.2] /// [GNU] '__FUNCTION__' /// [GNU] '__PRETTY_FUNCTION__' @@ -491,6 +490,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// [C++] 'this' [C++ 9.3.2] /// [G++] unary-type-trait '(' type-id ')' /// [G++] binary-type-trait '(' type-id ',' type-id ')' [TODO] +/// [EMBT] array-type-trait '(' type-id ',' integer ')' /// [clang] '^' block-literal /// /// constant: [C99 6.4.4] @@ -520,6 +520,34 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '::'[opt] 'delete' cast-expression /// '::'[opt] 'delete' '[' ']' cast-expression /// +/// [GNU/Embarcadero] unary-type-trait: +/// '__is_arithmetic' +/// '__is_floating_point' +/// '__is_integral' +/// '__is_lvalue_expr' +/// '__is_rvalue_expr' +/// '__is_complete_type' +/// '__is_void' +/// '__is_array' +/// '__is_function' +/// '__is_reference' +/// '__is_lvalue_reference' +/// '__is_rvalue_reference' +/// '__is_fundamental' +/// '__is_object' +/// '__is_scalar' +/// '__is_compound' +/// '__is_pointer' +/// '__is_member_object_pointer' +/// '__is_member_function_pointer' +/// '__is_member_pointer' +/// '__is_const' +/// '__is_volatile' +/// '__is_trivial' +/// '__is_standard_layout' +/// '__is_signed' +/// '__is_unsigned' +/// /// [GNU] unary-type-trait: /// '__has_nothrow_assign' /// '__has_nothrow_copy' @@ -535,11 +563,22 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, /// '__is_enum' /// '__is_pod' /// '__is_polymorphic' +/// '__is_trivial' /// '__is_union' /// /// binary-type-trait: /// [GNU] '__is_base_of' /// [MS] '__is_convertible_to' +/// '__is_convertible' +/// '__is_same' +/// +/// [Embarcadero] array-type-trait: +/// '__array_rank' +/// '__array_extent' +/// +/// [Embarcadero] expression-trait: +/// '__is_lvalue_expr' +/// '__is_rvalue_expr' /// ExprResult Parser::ParseCastExpression(bool isUnaryExpression, bool isAddressOfOperand, @@ -610,6 +649,12 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_nullptr: return Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); + case tok::annot_primary_expr: + assert(Res.get() == 0 && "Stray primary-expression annotation?"); + Res = getExprAnnotation(Tok); + ConsumeToken(); + break; + case tok::identifier: { // primary-expression: identifier // unqualified-id: identifier // constant: enumeration-constant @@ -683,7 +728,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, if (ParsedType Typ = Actions.getTypeName(II, ILoc, getCurScope())) if (Typ.get()->isObjCObjectOrInterfaceType()) { // Fake up a Declarator to use with ActOnTypeName. - DeclSpec DS; + DeclSpec DS(AttrFactory); DS.SetRangeStart(ILoc); DS.SetRangeEnd(ILoc); const char *PrevSpec = 0; @@ -731,6 +776,9 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::wide_string_literal: Res = ParseStringLiteralExpression(); break; + case tok::kw__Generic: // primary-expression: generic-selection [C1X 6.5.1] + Res = ParseGenericSelectionExpression(); + break; case tok::kw___builtin_va_arg: case tok::kw___builtin_offsetof: case tok::kw___builtin_choose_expr: @@ -788,7 +836,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___alignof: // unary-expression: '__alignof' unary-expression // unary-expression: '__alignof' '(' type-name ')' // unary-expression: 'alignof' '(' type-id ')' - return ParseSizeofAlignofExpression(); + case tok::kw_vec_step: // unary-expression: OpenCL 'vec_step' expression + return ParseUnaryExprOrTypeTraitExpression(); case tok::ampamp: { // unary-expression: '&&' identifier SourceLocation AmpAmpLoc = ConsumeToken(); if (Tok.isNot(tok::identifier)) @@ -825,7 +874,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, ParsedType Type = getTypeAnnotation(Tok); // Fake up a Declarator to use with ActOnTypeName. - DeclSpec DS; + DeclSpec DS(AttrFactory); DS.SetRangeStart(Tok.getLocation()); DS.SetRangeEnd(Tok.getLastLoc()); @@ -854,6 +903,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw_short: case tok::kw_int: case tok::kw_long: + case tok::kw___int64: case tok::kw_signed: case tok::kw_unsigned: case tok::kw_float: @@ -875,7 +925,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // postfix-expression: simple-type-specifier '(' expression-list[opt] ')' // - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseCXXSimpleTypeSpecifier(DS); if (Tok.isNot(tok::l_paren)) return ExprError(Diag(Tok, diag::err_expected_lparen_after_type) @@ -904,7 +954,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, // cast expression. CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, ParsedType(), false); - AnnotateTemplateIdTokenAsType(&SS); + AnnotateTemplateIdTokenAsType(); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, TypeOfCast); } @@ -978,14 +1028,39 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return move(Result); } - case tok::kw___is_pod: // [GNU] unary-type-trait + case tok::kw___is_abstract: // [GNU] unary-type-trait case tok::kw___is_class: - case tok::kw___is_enum: - case tok::kw___is_union: case tok::kw___is_empty: - case tok::kw___is_polymorphic: - case tok::kw___is_abstract: + case tok::kw___is_enum: case tok::kw___is_literal: + case tok::kw___is_arithmetic: + case tok::kw___is_integral: + case tok::kw___is_floating_point: + case tok::kw___is_complete_type: + case tok::kw___is_void: + case tok::kw___is_array: + case tok::kw___is_function: + case tok::kw___is_reference: + case tok::kw___is_lvalue_reference: + case tok::kw___is_rvalue_reference: + case tok::kw___is_fundamental: + case tok::kw___is_object: + case tok::kw___is_scalar: + case tok::kw___is_compound: + case tok::kw___is_pointer: + case tok::kw___is_member_object_pointer: + case tok::kw___is_member_function_pointer: + case tok::kw___is_member_pointer: + case tok::kw___is_const: + case tok::kw___is_volatile: + case tok::kw___is_standard_layout: + case tok::kw___is_signed: + case tok::kw___is_unsigned: + case tok::kw___is_literal_type: + case tok::kw___is_pod: + case tok::kw___is_polymorphic: + case tok::kw___is_trivial: + case tok::kw___is_union: case tok::kw___has_trivial_constructor: case tok::kw___has_trivial_copy: case tok::kw___has_trivial_assign: @@ -998,9 +1073,19 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___builtin_types_compatible_p: case tok::kw___is_base_of: + case tok::kw___is_same: + case tok::kw___is_convertible: case tok::kw___is_convertible_to: return ParseBinaryTypeTrait(); + case tok::kw___array_rank: + case tok::kw___array_extent: + return ParseArrayTypeTrait(); + + case tok::kw___is_lvalue_expr: + case tok::kw___is_rvalue_expr: + return ParseExpressionTrait(); + case tok::at: { SourceLocation AtLoc = ConsumeToken(); return ParseObjCAtExpression(AtLoc); @@ -1256,10 +1341,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } } -/// 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). +/// ParseExprAfterUnaryExprOrTypeTrait - We parsed a typeof/sizeof/alignof/ +/// vec_step 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). /// /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression @@ -1273,15 +1358,20 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /// typeof ( type-name ) /// [GNU/C++] typeof unary-expression /// +/// [OpenCL 1.1 6.11.12] vec_step built-in function: +/// vec_step ( expressions ) +/// vec_step ( type-name ) +/// ExprResult -Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, - bool &isCastExpr, - ParsedType &CastTy, - SourceRange &CastRange) { +Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, + bool &isCastExpr, + ParsedType &CastTy, + SourceRange &CastRange) { assert((OpTok.is(tok::kw_typeof) || OpTok.is(tok::kw_sizeof) || - OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof)) && - "Not a typeof/sizeof/alignof expression!"); + OpTok.is(tok::kw___alignof) || OpTok.is(tok::kw_alignof) || + OpTok.is(tok::kw_vec_step)) && + "Not a typeof/sizeof/alignof/vec_step expression!"); ExprResult Operand; @@ -1345,7 +1435,7 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, } -/// ParseSizeofAlignofExpression - Parse a sizeof or alignof expression. +/// ParseUnaryExprOrTypeTraitExpression - Parse a sizeof or alignof expression. /// unary-expression: [C99 6.5.3] /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' @@ -1353,10 +1443,10 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, /// [GNU] '__alignof' unary-expression /// [GNU] '__alignof' '(' type-name ')' /// [C++0x] 'alignof' '(' type-id ')' -ExprResult Parser::ParseSizeofAlignofExpression() { +ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() { assert((Tok.is(tok::kw_sizeof) || Tok.is(tok::kw___alignof) - || Tok.is(tok::kw_alignof)) && - "Not a sizeof/alignof expression!"); + || Tok.is(tok::kw_alignof) || Tok.is(tok::kw_vec_step)) && + "Not a sizeof/alignof/vec_step expression!"); Token OpTok = Tok; ConsumeToken(); @@ -1403,24 +1493,31 @@ ExprResult Parser::ParseSizeofAlignofExpression() { bool isCastExpr; ParsedType CastTy; SourceRange CastRange; - ExprResult Operand = ParseExprAfterTypeofSizeofAlignof(OpTok, - isCastExpr, - CastTy, - CastRange); + ExprResult Operand = ParseExprAfterUnaryExprOrTypeTrait(OpTok, + isCastExpr, + CastTy, + CastRange); + + UnaryExprOrTypeTrait ExprKind = UETT_SizeOf; + if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw___alignof)) + ExprKind = UETT_AlignOf; + else if (OpTok.is(tok::kw_vec_step)) + ExprKind = UETT_VecStep; if (isCastExpr) - return Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(), - OpTok.is(tok::kw_sizeof), - /*isType=*/true, - CastTy.getAsOpaquePtr(), - CastRange); + return Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), + ExprKind, + /*isType=*/true, + CastTy.getAsOpaquePtr(), + CastRange); // If we get here, the operand to the sizeof/alignof was an expresion. if (!Operand.isInvalid()) - Operand = Actions.ActOnSizeOfAlignOfExpr(OpTok.getLocation(), - OpTok.is(tok::kw_sizeof), - /*isType=*/false, - Operand.release(), CastRange); + Operand = Actions.ActOnUnaryExprOrTypeTraitExpr(OpTok.getLocation(), + ExprKind, + /*isType=*/false, + Operand.release(), + CastRange); return move(Operand); } @@ -1618,15 +1715,18 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, ConsumeCodeCompletionToken(); return ExprError(); } + + // None of these cases should fall through with an invalid Result + // unless they've already reported an error. if (ExprType >= CompoundStmt && Tok.is(tok::l_brace)) { Diag(Tok, diag::ext_gnu_statement_expr); - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); StmtResult Stmt(ParseCompoundStatement(attrs, true)); ExprType = CompoundStmt; // If the substmt parsed correctly, build the AST node. - if (!Stmt.isInvalid() && Tok.is(tok::r_paren)) + if (!Stmt.isInvalid()) Result = Actions.ActOnStmtExpr(OpenLoc, Stmt.take(), Tok.getLocation()); } else if (ExprType >= CompoundLiteral && @@ -1724,6 +1824,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, Result = ParseExpression(); ExprType = SimpleExpr; + + // Don't build a paren expression unless we actually match a ')'. if (!Result.isInvalid() && Tok.is(tok::r_paren)) Result = Actions.ActOnParenExpr(OpenLoc, Tok.getLocation(), Result.take()); } @@ -1784,6 +1886,100 @@ ExprResult Parser::ParseStringLiteralExpression() { return Actions.ActOnStringLiteral(&StringToks[0], StringToks.size()); } +/// ParseGenericSelectionExpression - Parse a C1X generic-selection +/// [C1X 6.5.1.1]. +/// +/// generic-selection: +/// _Generic ( assignment-expression , generic-assoc-list ) +/// generic-assoc-list: +/// generic-association +/// generic-assoc-list , generic-association +/// generic-association: +/// type-name : assignment-expression +/// default : assignment-expression +ExprResult Parser::ParseGenericSelectionExpression() { + assert(Tok.is(tok::kw__Generic) && "_Generic keyword expected"); + SourceLocation KeyLoc = ConsumeToken(); + + if (!getLang().C1X) + Diag(KeyLoc, diag::ext_c1x_generic_selection); + + SourceLocation LParenLoc = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen, "")) + return ExprError(); + + ExprResult ControllingExpr; + { + // C1X 6.5.1.1p3 "The controlling expression of a generic selection is + // not evaluated." + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + ControllingExpr = ParseAssignmentExpression(); + if (ControllingExpr.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + } + + if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "")) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + SourceLocation DefaultLoc; + TypeVector Types(Actions); + ExprVector Exprs(Actions); + while (1) { + ParsedType Ty; + if (Tok.is(tok::kw_default)) { + // C1X 6.5.1.1p2 "A generic selection shall have no more than one default + // generic association." + if (!DefaultLoc.isInvalid()) { + Diag(Tok, diag::err_duplicate_default_assoc); + Diag(DefaultLoc, diag::note_previous_default_assoc); + SkipUntil(tok::r_paren); + return ExprError(); + } + DefaultLoc = ConsumeToken(); + Ty = ParsedType(); + } else { + ColonProtectionRAIIObject X(*this); + TypeResult TR = ParseTypeName(); + if (TR.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + Ty = TR.release(); + } + Types.push_back(Ty); + + if (ExpectAndConsume(tok::colon, diag::err_expected_colon, "")) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + // FIXME: These expressions should be parsed in a potentially potentially + // evaluated context. + ExprResult ER(ParseAssignmentExpression()); + if (ER.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + Exprs.push_back(ER.release()); + + if (Tok.isNot(tok::comma)) + break; + ConsumeToken(); + } + + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + if (RParenLoc.isInvalid()) + return ExprError(); + + return Actions.ActOnGenericSelectionExpr(KeyLoc, DefaultLoc, RParenLoc, + ControllingExpr.release(), + move_arg(Types), move_arg(Exprs)); +} + /// ParseExpressionList - Used for C/C++ (argument-)expression-list. /// /// argument-expression-list: @@ -1837,7 +2033,7 @@ void Parser::ParseBlockId() { } // Parse the specifier-qualifier-list piece. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); // Parse the block-declarator. @@ -1845,7 +2041,7 @@ void Parser::ParseBlockId() { ParseDeclarator(DeclaratorInfo); // We do this for: ^ __attribute__((noreturn)) {, as DS has the attributes. - DeclaratorInfo.addAttributes(DS.takeAttributes()); + DeclaratorInfo.takeAttributes(DS.getAttributes(), SourceLocation()); MaybeParseGNUAttributes(DeclaratorInfo); @@ -1881,7 +2077,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { Actions.ActOnBlockStart(CaretLoc, getCurScope()); // Parse the return type if present. - DeclSpec DS; + DeclSpec DS(AttrFactory); Declarator ParamInfo(DS, Declarator::BlockLiteralContext); // 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. @@ -1913,16 +2109,17 @@ ExprResult Parser::ParseBlockLiteralExpression() { ParseBlockId(); } else { // Otherwise, pretend we saw (void). - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), - true, false, + ParsedAttributes attrs(AttrFactory); + ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false, SourceLocation(), 0, 0, 0, true, SourceLocation(), - false, SourceLocation(), - false, 0, 0, 0, + EST_None, + SourceLocation(), + 0, 0, 0, 0, CaretLoc, CaretLoc, ParamInfo), - CaretLoc); + attrs, CaretLoc); MaybeParseGNUAttributes(ParamInfo); @@ -1940,6 +2137,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { } StmtResult Stmt(ParseCompoundStatementBody()); + BlockScope.Exit(); if (!Stmt.isInvalid()) Result = Actions.ActOnBlockStmtExpr(CaretLoc, Stmt.take(), getCurScope()); else |