diff options
| author | Ed Schouten <ed@FreeBSD.org> | 2009-06-27 10:45:02 +0000 |
|---|---|---|
| committer | Ed Schouten <ed@FreeBSD.org> | 2009-06-27 10:45:02 +0000 |
| commit | 4ebdf5c4f587daef4e0be499802eac3a7a49bf2f (patch) | |
| tree | 2c5a83521a20c02e7805581a174008aa9bc23579 /lib/Parse | |
| parent | f698f7e71940663e26a4806a96fb0bdfa160c886 (diff) | |
Notes
Diffstat (limited to 'lib/Parse')
| -rw-r--r-- | lib/Parse/AttributeList.cpp | 3 | ||||
| -rw-r--r-- | lib/Parse/DeclSpec.cpp | 1 | ||||
| -rw-r--r-- | lib/Parse/MinimalAction.cpp | 1 | ||||
| -rw-r--r-- | lib/Parse/ParseDecl.cpp | 60 | ||||
| -rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 77 | ||||
| -rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 154 | ||||
| -rw-r--r-- | lib/Parse/ParseObjc.cpp | 4 | ||||
| -rw-r--r-- | lib/Parse/ParseTemplate.cpp | 32 | ||||
| -rw-r--r-- | lib/Parse/ParseTentative.cpp | 7 | ||||
| -rw-r--r-- | lib/Parse/Parser.cpp | 26 |
10 files changed, 265 insertions, 100 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 3fb6f950efc4..5ee668a31723 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -118,6 +118,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { case 13: if (!memcmp(Str, "address_space", 13)) return AT_address_space; if (!memcmp(Str, "always_inline", 13)) return AT_always_inline; + if (!memcmp(Str, "vec_type_hint", 13)) return IgnoredAttribute; break; case 14: if (!memcmp(Str, "objc_exception", 14)) return AT_objc_exception; @@ -136,6 +137,8 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { if (!memcmp(Str, "ns_returns_retained", 19)) return AT_ns_returns_retained; if (!memcmp(Str, "cf_returns_retained", 19)) return AT_cf_returns_retained; break; + case 20: + if (!memcmp(Str, "reqd_work_group_size", 20)) return AT_reqd_wg_size; case 22: if (!memcmp(Str, "no_instrument_function", 22)) return AT_no_instrument_function; diff --git a/lib/Parse/DeclSpec.cpp b/lib/Parse/DeclSpec.cpp index d8c6986f9ea6..8b3b2851c1e0 100644 --- a/lib/Parse/DeclSpec.cpp +++ b/lib/Parse/DeclSpec.cpp @@ -173,6 +173,7 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T) { case DeclSpec::TST_typename: return "type-name"; case DeclSpec::TST_typeofType: case DeclSpec::TST_typeofExpr: return "typeof"; + case DeclSpec::TST_auto: return "auto"; } } diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 9ded366b29f9..648e2da54bfe 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -48,6 +48,7 @@ Action::DeclPtrTy Action::ActOnUsingDeclaration(Scope *CurScope, const CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *TargetName, + OverloadedOperatorKind Op, AttributeList *AttrList, bool IsTypeName) { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 426f56f4380e..ff602e8ba79b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -149,13 +149,35 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { } } } else { // not an identifier + switch (Tok.getKind()) { + case tok::r_paren: // parse a possibly empty comma separated list of expressions - if (Tok.is(tok::r_paren)) { // __attribute__(( nonnull() )) ConsumeParen(); // ignore the right paren loc for now CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); - } else { + break; + case tok::kw_char: + case tok::kw_wchar_t: + case tok::kw_bool: + case tok::kw_short: + case tok::kw_int: + case tok::kw_long: + case tok::kw_signed: + case tok::kw_unsigned: + case tok::kw_float: + case tok::kw_double: + case tok::kw_void: + case tok::kw_typeof: + // If it's a builtin type name, eat it and expect a rparen + // __attribute__(( vec_type_hint(char) )) + ConsumeToken(); + CurrAttr = new AttributeList(AttrName, AttrNameLoc, + 0, SourceLocation(), 0, 0, CurrAttr); + if (Tok.is(tok::r_paren)) + ConsumeParen(); + break; + default: // __attribute__(( aligned(16) )) ExprVector ArgExprs(Actions); bool ArgExprsOk = true; @@ -181,6 +203,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { SourceLocation(), ArgExprs.take(), ArgExprs.size(), CurrAttr); } + break; } } } else { @@ -371,7 +394,8 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, /// According to the standard grammar, =default and =delete are function /// definitions, but that definitely doesn't fit with the parser here. /// -Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) { +Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, + const ParsedTemplateInfo &TemplateInfo) { // If a simple-asm-expr is present, parse it. if (Tok.is(tok::kw_asm)) { SourceLocation Loc; @@ -393,7 +417,13 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D) { } // Inform the current actions module that we just parsed this declarator. - DeclPtrTy ThisDecl = Actions.ActOnDeclarator(CurScope, D); + DeclPtrTy ThisDecl = TemplateInfo.TemplateParams? + Actions.ActOnTemplateDeclarator(CurScope, + Action::MultiTemplateParamsArg(Actions, + TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()), + D) + : Actions.ActOnDeclarator(CurScope, D); // Parse declarator '=' initializer. if (Tok.is(tok::equal)) { @@ -896,7 +926,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec); break; case tok::kw_auto: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec); + if (getLang().CPlusPlus0x) + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + else + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec); break; case tok::kw_register: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec); @@ -1018,6 +1051,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseTypeofSpecifier(DS); continue; + case tok::kw_decltype: + ParseDecltypeSpecifier(DS); + continue; + case tok::less: // GCC ObjC supports types like "<SomeProtocol>" as a synonym for // "id<SomeProtocol>". This is hopelessly old fashioned and dangerous, @@ -1095,6 +1132,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// [GNU] typeof-specifier /// [OBJC] class-name objc-protocol-refs[opt] [TODO] /// [OBJC] typedef-name objc-protocol-refs[opt] [TODO] +/// [C++0x] 'decltype' ( expression ) bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, const char *&PrevSpec, const ParsedTemplateInfo &TemplateInfo) { @@ -1235,6 +1273,18 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, ParseTypeofSpecifier(DS); return true; + // C++0x decltype support. + case tok::kw_decltype: + ParseDecltypeSpecifier(DS); + return true; + + // C++0x auto support. + case tok::kw_auto: + if (!getLang().CPlusPlus0x) + return false; + + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + break; case tok::kw___ptr64: case tok::kw___w64: case tok::kw___cdecl: diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 44f231a66786..225f9261ef8f 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/OperatorKinds.h" #include "clang/Parse/Parser.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/DeclSpec.h" @@ -274,8 +275,6 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, ParseOptionalCXXScopeSpecifier(SS); AttributeList *AttrList = 0; - IdentifierInfo *TargetName = 0; - SourceLocation IdentLoc = SourceLocation(); // Check nested-name specifier. if (SS.isInvalid()) { @@ -287,17 +286,33 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, SkipUntil(tok::semi); return DeclPtrTy(); } - if (Tok.isNot(tok::identifier)) { + + IdentifierInfo *TargetName = 0; + OverloadedOperatorKind Op = OO_None; + SourceLocation IdentLoc; + + if (Tok.is(tok::kw_operator)) { + IdentLoc = Tok.getLocation(); + + Op = TryParseOperatorFunctionId(); + if (!Op) { + // If there was an invalid operator, skip to end of decl, and eat ';'. + SkipUntil(tok::semi); + return DeclPtrTy(); + } + } else if (Tok.is(tok::identifier)) { + // Parse identifier. + TargetName = Tok.getIdentifierInfo(); + IdentLoc = ConsumeToken(); + } else { + // FIXME: Use a better diagnostic here. Diag(Tok, diag::err_expected_ident_in_using); + // If there was invalid identifier, skip to end of decl, and eat ';'. SkipUntil(tok::semi); return DeclPtrTy(); } - // Parse identifier. - TargetName = Tok.getIdentifierInfo(); - IdentLoc = ConsumeToken(); - // Parse (optional) attributes (most likely GNU strong-using extension). if (Tok.is(tok::kw___attribute)) AttrList = ParseAttributes(); @@ -308,7 +323,8 @@ Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context, AttrList ? "attributes list" : "namespace name", tok::semi); return Actions.ActOnUsingDeclaration(CurScope, UsingLoc, SS, - IdentLoc, TargetName, AttrList, IsTypeName); + IdentLoc, TargetName, Op, + AttrList, IsTypeName); } /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion. @@ -355,6 +371,51 @@ Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){ move(AssertMessage)); } +/// ParseDecltypeSpecifier - Parse a C++0x decltype specifier. +/// +/// 'decltype' ( expression ) +/// +void Parser::ParseDecltypeSpecifier(DeclSpec &DS) { + assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier"); + + SourceLocation StartLoc = ConsumeToken(); + SourceLocation LParenLoc = Tok.getLocation(); + + if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, + "decltype")) { + SkipUntil(tok::r_paren); + return; + } + + // Parse the expression + + // C++0x [dcl.type.simple]p4: + // The operand of the decltype specifier is an unevaluated operand. + EnterExpressionEvaluationContext Unevaluated(Actions, + Action::Unevaluated); + OwningExprResult Result = ParseExpression(); + if (Result.isInvalid()) { + SkipUntil(tok::r_paren); + return; + } + + // Match the ')' + SourceLocation RParenLoc; + if (Tok.is(tok::r_paren)) + RParenLoc = ConsumeParen(); + else + MatchRHSPunctuation(tok::r_paren, LParenLoc); + + if (RParenLoc.isInvalid()) + return; + + const char *PrevSpec = 0; + // Check for duplicate type specifiers (e.g. "int decltype(a)"). + if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec, + Result.release())) + Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; +} + /// ParseClassName - Parse a C++ class-name, which names a class. Note /// that we only check that the result names a type; semantic analysis /// will need to verify that the type names a class. The result is diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 2be44a4e77a0..d89f1e172ffb 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -59,81 +59,39 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { while (true) { // nested-name-specifier: - // type-name '::' - // namespace-name '::' - // nested-name-specifier identifier '::' - if (Tok.is(tok::identifier) && NextToken().is(tok::coloncolon)) { - // We have an identifier followed by a '::'. Lookup this name - // as the name in a nested-name-specifier. - IdentifierInfo *II = Tok.getIdentifierInfo(); - SourceLocation IdLoc = ConsumeToken(); - assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); - SourceLocation CCLoc = ConsumeToken(); + // nested-name-specifier 'template'[opt] simple-template-id '::' + + // Parse the optional 'template' keyword, then make sure we have + // 'identifier <' after it. + if (Tok.is(tok::kw_template)) { + SourceLocation TemplateKWLoc = ConsumeToken(); - if (!HasScopeSpecifier) { - SS.setBeginLoc(IdLoc); - HasScopeSpecifier = true; + if (Tok.isNot(tok::identifier)) { + Diag(Tok.getLocation(), + diag::err_id_after_template_in_nested_name_spec) + << SourceRange(TemplateKWLoc); + break; } - if (SS.isInvalid()) - continue; + if (NextToken().isNot(tok::less)) { + Diag(NextToken().getLocation(), + diag::err_less_after_template_name_in_nested_name_spec) + << Tok.getIdentifierInfo()->getName() + << SourceRange(TemplateKWLoc, Tok.getLocation()); + break; + } + + TemplateTy Template + = Actions.ActOnDependentTemplateName(TemplateKWLoc, + *Tok.getIdentifierInfo(), + Tok.getLocation(), SS); + if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, + &SS, TemplateKWLoc, false)) + break; - SS.setScopeRep( - Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, *II)); - SS.setEndLoc(CCLoc); continue; } - - // nested-name-specifier: - // type-name '::' - // nested-name-specifier 'template'[opt] simple-template-id '::' - if ((Tok.is(tok::identifier) && NextToken().is(tok::less)) || - Tok.is(tok::kw_template)) { - // Parse the optional 'template' keyword, then make sure we have - // 'identifier <' after it. - if (Tok.is(tok::kw_template)) { - SourceLocation TemplateKWLoc = ConsumeToken(); - - if (Tok.isNot(tok::identifier)) { - Diag(Tok.getLocation(), - diag::err_id_after_template_in_nested_name_spec) - << SourceRange(TemplateKWLoc); - break; - } - - if (NextToken().isNot(tok::less)) { - Diag(NextToken().getLocation(), - diag::err_less_after_template_name_in_nested_name_spec) - << Tok.getIdentifierInfo()->getName() - << SourceRange(TemplateKWLoc, Tok.getLocation()); - break; - } - - TemplateTy Template - = Actions.ActOnDependentTemplateName(TemplateKWLoc, - *Tok.getIdentifierInfo(), - Tok.getLocation(), - SS); - AnnotateTemplateIdToken(Template, TNK_Dependent_template_name, - &SS, TemplateKWLoc, false); - continue; - } - - TemplateTy Template; - TemplateNameKind TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(), - CurScope, Template, &SS); - if (TNK) { - // We have found a template name, so annotate this this token - // with a template-id annotation. We do not permit the - // template-id to be translated into a type annotation, - // because some clients (e.g., the parsing of class template - // specializations) still want to see the original template-id - // token. - AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), false); - continue; - } - } - + if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { // We have // @@ -172,8 +130,62 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { SS.setScopeRep(0); SS.setEndLoc(CCLoc); continue; - } else - assert(false && "FIXME: Only type template names supported here"); + } + + assert(false && "FIXME: Only type template names supported here"); + } + + + // The rest of the nested-name-specifier possibilities start with + // tok::identifier. + if (Tok.isNot(tok::identifier)) + break; + + IdentifierInfo &II = *Tok.getIdentifierInfo(); + + // nested-name-specifier: + // type-name '::' + // namespace-name '::' + // nested-name-specifier identifier '::' + Token Next = NextToken(); + if (Next.is(tok::coloncolon)) { + // We have an identifier followed by a '::'. Lookup this name + // as the name in a nested-name-specifier. + SourceLocation IdLoc = ConsumeToken(); + assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!"); + SourceLocation CCLoc = ConsumeToken(); + + if (!HasScopeSpecifier) { + SS.setBeginLoc(IdLoc); + HasScopeSpecifier = true; + } + + if (SS.isInvalid()) + continue; + + SS.setScopeRep( + Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II)); + SS.setEndLoc(CCLoc); + continue; + } + + // nested-name-specifier: + // type-name '<' + if (Next.is(tok::less)) { + TemplateTy Template; + if (TemplateNameKind TNK = Actions.isTemplateName(II, CurScope, + Template, &SS)) { + // We have found a template name, so annotate this this token + // with a template-id annotation. We do not permit the + // template-id to be translated into a type annotation, + // because some clients (e.g., the parsing of class template + // specializations) still want to see the original template-id + // token. + if (AnnotateTemplateIdToken(Template, TNK, &SS, SourceLocation(), + false)) + break; + continue; + } } // We don't have any tokens that form the beginning of a diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index cb7fe58807af..013e26b891e1 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -771,10 +771,12 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc, if (getLang().ObjC2 && Tok.is(tok::kw___attribute)) MethodAttrs = ParseAttributes(); + if (KeyIdents.size() == 0) + return DeclPtrTy(); Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); return Actions.ActOnMethodDeclaration(mLoc, Tok.getLocation(), - mType, IDecl, DSRet, ReturnType, Sel, + mType, IDecl, DSRet, ReturnType, Sel, &ArgInfos[0], CargNames, MethodAttrs, MethodImplKind, isVariadic); } diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index eabe10f1450e..57a09fbc737f 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -170,7 +170,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // If we have a declaration or declarator list, handle it. if (isDeclarationAfterDeclarator()) { // Parse this declaration. - DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo); + DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(DeclaratorInfo, + TemplateInfo); if (Tok.is(tok::comma)) { Diag(Tok, diag::err_multiple_template_declarators) @@ -200,7 +201,7 @@ Parser::ParseSingleDeclarationAfterTemplate( } return DeclPtrTy(); } - return ParseFunctionDefinition(DeclaratorInfo); + return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo); } if (DeclaratorInfo.isFunctionDeclarator()) @@ -620,7 +621,11 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template, /// replaced with a type annotation token. Otherwise, the /// simple-template-id is always replaced with a template-id /// annotation token. -void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, +/// +/// If an unrecoverable parse error occurs and no annotation token can be +/// formed, this function returns true. +/// +bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, const CXXScopeSpec *SS, SourceLocation TemplateKWLoc, bool AllowTypeAnnotation) { @@ -643,14 +648,19 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, TemplateArgIsType, TemplateArgLocations, RAngleLoc); + + if (Invalid) { + // If we failed to parse the template ID but skipped ahead to a >, we're not + // going to be able to form a token annotation. Eat the '>' if present. + if (Tok.is(tok::greater)) + ConsumeToken(); + return true; + } ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(), TemplateArgIsType.data(), TemplateArgs.size()); - if (Invalid) // FIXME: How to recover from a broken template-id? - return; - // Build the annotation token. if (TNK == TNK_Type_template && AllowTypeAnnotation) { Action::TypeResult Type @@ -658,8 +668,13 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, LAngleLoc, TemplateArgsPtr, &TemplateArgLocations[0], RAngleLoc); - if (Type.isInvalid()) // FIXME: better recovery? - return; + if (Type.isInvalid()) { + // If we failed to parse the template ID but skipped ahead to a >, we're not + // going to be able to form a token annotation. Eat the '>' if present. + if (Tok.is(tok::greater)) + ConsumeToken(); + return true; + } Tok.setKind(tok::annot_typename); Tok.setAnnotationValue(Type.get()); @@ -704,6 +719,7 @@ void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, // In case the tokens were cached, have Preprocessor replace them with the // annotation token. PP.AnnotateCachedTokens(Tok); + return false; } /// \brief Replaces a template-id annotation token with a type diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index f31855b751fc..02687a216c7d 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -543,6 +543,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, /// [GNU] typeof-specifier /// [GNU] '_Complex' /// [C++0x] 'auto' [TODO] +/// [C++0x] 'decltype' ( expression ) /// /// type-name: /// class-name @@ -695,7 +696,7 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { return TPResult::True(); - // GNU typeof support. + // GNU typeof support. case tok::kw_typeof: { if (NextToken().isNot(tok::l_paren)) return TPResult::True(); @@ -716,6 +717,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() { return TPResult::True(); } + // C++0x decltype support. + case tok::kw_decltype: + return TPResult::True(); + default: return TPResult::False(); } diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index a2a66f9255de..29d1d8792e1a 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -590,7 +590,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AccessSpecifier AS) { /// [C++] function-definition: [C++ 8.4] /// decl-specifier-seq[opt] declarator function-try-block /// -Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { +Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D, + const ParsedTemplateInfo &TemplateInfo) { const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); assert(FnTypeInfo.Kind == DeclaratorChunk::Function && "This isn't a function declarator!"); @@ -632,7 +633,13 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. - DeclPtrTy Res = Actions.ActOnStartOfFunctionDef(CurScope, D); + DeclPtrTy Res = TemplateInfo.TemplateParams? + Actions.ActOnStartOfFunctionTemplateDef(CurScope, + Action::MultiTemplateParamsArg(Actions, + TemplateInfo.TemplateParams->data(), + TemplateInfo.TemplateParams->size()), + D) + : Actions.ActOnStartOfFunctionDef(CurScope, D); if (Tok.is(tok::kw_try)) return ParseFunctionTryBlock(Res); @@ -832,7 +839,8 @@ Parser::OwningExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { /// specifier, and another one to get the actual type inside /// ParseDeclarationSpecifiers). /// -/// This returns true if the token was annotated. +/// This returns true if the token was annotated or an unrecoverable error +/// occurs. /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. @@ -927,7 +935,12 @@ bool Parser::TryAnnotateTypeOrScopeToken() { if (TemplateNameKind TNK = Actions.isTemplateName(*Tok.getIdentifierInfo(), CurScope, Template, &SS)) - AnnotateTemplateIdToken(Template, TNK, &SS); + if (AnnotateTemplateIdToken(Template, TNK, &SS)) { + // If an unrecoverable error occurred, we need to return true here, + // because the token stream is in a damaged state. We may not return + // a valid identifier. + return Tok.isNot(tok::identifier); + } } // The current token, which is either an identifier or a @@ -950,7 +963,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { } if (SS.isEmpty()) - return false; + return Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon); // A C++ scope specifier that isn't followed by a typename. // Push the current token back into the token stream (or revert it if it is @@ -971,7 +984,8 @@ bool Parser::TryAnnotateTypeOrScopeToken() { /// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only /// annotates C++ scope specifiers and template-ids. This returns -/// true if the token was annotated. +/// true if the token was annotated or there was an error that could not be +/// recovered from. /// /// Note that this routine emits an error if you call it with ::new or ::delete /// as the current tokens, so only call it in contexts where these are invalid. |
