diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-02-20 13:06:31 +0000 |
commit | bca07a4524feb4edec581062d631a13116320a24 (patch) | |
tree | a9243275843fbeaa590afc07ee888e006b8d54ea /lib/Parse/ParseExprCXX.cpp | |
parent | 998bc5802ecdd65ce3b270f6c69a8ae8557f0a10 (diff) | |
download | src-bca07a4524feb4edec581062d631a13116320a24.tar.gz src-bca07a4524feb4edec581062d631a13116320a24.zip |
Notes
Diffstat (limited to 'lib/Parse/ParseExprCXX.cpp')
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 160 |
1 files changed, 136 insertions, 24 deletions
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 5041a212924a..e73578f23e36 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -13,6 +13,7 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" +#include "RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "llvm/Support/ErrorHandling.h" @@ -500,9 +501,9 @@ ExprResult Parser::ParseCXXTypeid() { TypeResult Ty = ParseTypeName(); // Match the ')'. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - if (Ty.isInvalid()) + if (Ty.isInvalid() || RParenLoc.isInvalid()) return ExprError(); Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true, @@ -524,8 +525,10 @@ ExprResult Parser::ParseCXXTypeid() { if (Result.isInvalid()) SkipUntil(tok::r_paren); else { - MatchRHSPunctuation(tok::r_paren, LParenLoc); - + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + if (RParenLoc.isInvalid()) + return ExprError(); + Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, Result.release(), RParenLoc); } @@ -534,6 +537,54 @@ ExprResult Parser::ParseCXXTypeid() { return move(Result); } +/// ParseCXXUuidof - This handles the Microsoft C++ __uuidof expression. +/// +/// '__uuidof' '(' expression ')' +/// '__uuidof' '(' type-id ')' +/// +ExprResult Parser::ParseCXXUuidof() { + assert(Tok.is(tok::kw___uuidof) && "Not '__uuidof'!"); + + SourceLocation OpLoc = ConsumeToken(); + SourceLocation LParenLoc = Tok.getLocation(); + SourceLocation RParenLoc; + + // __uuidof expressions are always parenthesized. + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, + "__uuidof")) + return ExprError(); + + ExprResult Result; + + if (isTypeIdInParens()) { + TypeResult Ty = ParseTypeName(); + + // Match the ')'. + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + if (Ty.isInvalid()) + return ExprError(); + + Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/true, + Ty.get().getAsOpaquePtr(), RParenLoc); + } else { + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + Result = ParseExpression(); + + // Match the ')'. + if (Result.isInvalid()) + SkipUntil(tok::r_paren); + else { + RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + + Result = Actions.ActOnCXXUuidof(OpLoc, LParenLoc, /*isType=*/false, + Result.release(), RParenLoc); + } + } + + return move(Result); +} + /// \brief Parse a C++ pseudo-destructor expression after the base, /// . or -> operator, and nested-name-specifier have already been /// parsed. @@ -670,6 +721,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); assert(Tok.is(tok::l_paren) && "Expected '('!"); + GreaterThanIsOperatorScope G(GreaterThanIsOperator, true); + SourceLocation LParenLoc = ConsumeParen(); ExprVector Exprs(Actions); @@ -691,9 +744,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); - return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep, - LParenLoc, move_arg(Exprs), - CommaLocs.data(), RParenLoc); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, LParenLoc, move_arg(Exprs), + RParenLoc); } /// ParseCXXCondition - if/switch/while condition expression. @@ -761,24 +813,22 @@ bool Parser::ParseCXXCondition(ExprResult &ExprOut, } // If attributes are present, parse them. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - DeclaratorInfo.AddAttributes(AttrList, Loc); - } + MaybeParseGNUAttributes(DeclaratorInfo); // Type-check the declaration itself. DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(getCurScope(), - DeclaratorInfo); + DeclaratorInfo); DeclOut = Dcl.get(); ExprOut = ExprError(); - + // '=' assignment-expression - if (Tok.is(tok::equal)) { - SourceLocation EqualLoc = ConsumeToken(); + if (isTokenEqualOrMistypedEqualEqual( + diag::err_invalid_equalequal_after_declarator)) { + ConsumeToken(); ExprResult AssignExpr(ParseAssignmentExpression()); if (!AssignExpr.isInvalid()) - Actions.AddInitializerToDecl(DeclOut, AssignExpr.take()); + Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false, + DS.getTypeSpecType() == DeclSpec::TST_auto); } else { // FIXME: C++0x allows a braced-init-list Diag(Tok, diag::err_expected_equal_after_declarator); @@ -862,9 +912,24 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { // type-name case tok::annot_typename: { - DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, - getTypeAnnotation(Tok)); - break; + if (getTypeAnnotation(Tok)) + DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, + getTypeAnnotation(Tok)); + else + DS.SetTypeSpecError(); + + DS.SetRangeEnd(Tok.getAnnotationEndLoc()); + ConsumeToken(); + + // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id' + // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an + // Objective-C interface. If we don't have Objective-C or a '<', this is + // just a normal reference to a typedef name. + if (Tok.is(tok::less) && getLang().ObjC1) + ParseObjCProtocolQualifiers(DS); + + DS.Finish(Diags, PP); + return; } // builtin types @@ -943,7 +1008,7 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { // Parse one or more of the type specifiers. if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, ParsedTemplateInfo(), /*SuppressDeclarations*/true)) { - Diag(Tok, diag::err_operator_missing_type_specifier); + Diag(Tok, diag::err_expected_type); return true; } @@ -1667,7 +1732,8 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { first = false; SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc); - D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, + D.AddTypeInfo(DeclaratorChunk::getArray(0, ParsedAttributes(), + /*static=*/false, /*star=*/false, Size.release(), LLoc, RLoc), RLoc); @@ -1738,7 +1804,7 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { switch(kind) { - default: assert(false && "Not a known unary type trait."); + default: llvm_unreachable("Not a known unary type trait"); case tok::kw___has_nothrow_assign: return UTT_HasNothrowAssign; case tok::kw___has_nothrow_copy: return UTT_HasNothrowCopy; case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor; @@ -1758,6 +1824,15 @@ static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) { } } +static BinaryTypeTrait BinaryTypeTraitFromTokKind(tok::TokenKind kind) { + switch(kind) { + default: llvm_unreachable("Not a known binary type trait"); + case tok::kw___is_base_of: return BTT_IsBaseOf; + case tok::kw___builtin_types_compatible_p: return BTT_TypeCompatible; + case tok::kw___is_convertible_to: return BTT_IsConvertibleTo; + } +} + /// ParseUnaryTypeTrait - Parse the built-in unary type-trait /// pseudo-functions that allow implementation of the TR1/C++0x type traits /// templates. @@ -1783,7 +1858,44 @@ ExprResult Parser::ParseUnaryTypeTrait() { if (Ty.isInvalid()) return ExprError(); - return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen); + return Actions.ActOnUnaryTypeTrait(UTT, Loc, Ty.get(), RParen); +} + +/// ParseBinaryTypeTrait - Parse the built-in binary type-trait +/// pseudo-functions that allow implementation of the TR1/C++0x type traits +/// templates. +/// +/// primary-expression: +/// [GNU] binary-type-trait '(' type-id ',' type-id ')' +/// +ExprResult Parser::ParseBinaryTypeTrait() { + BinaryTypeTrait BTT = BinaryTypeTraitFromTokKind(Tok.getKind()); + SourceLocation Loc = ConsumeToken(); + + SourceLocation LParen = Tok.getLocation(); + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + return ExprError(); + + TypeResult LhsTy = ParseTypeName(); + if (LhsTy.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + if (ExpectAndConsume(tok::comma, diag::err_expected_comma)) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + TypeResult RhsTy = ParseTypeName(); + if (RhsTy.isInvalid()) { + SkipUntil(tok::r_paren); + return ExprError(); + } + + SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen); + + return Actions.ActOnBinaryTypeTrait(BTT, Loc, LhsTy.get(), RhsTy.get(), RParen); } /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a |