summaryrefslogtreecommitdiff
path: root/lib/Parse
diff options
context:
space:
mode:
authorEd Schouten <ed@FreeBSD.org>2009-06-27 10:45:02 +0000
committerEd Schouten <ed@FreeBSD.org>2009-06-27 10:45:02 +0000
commit4ebdf5c4f587daef4e0be499802eac3a7a49bf2f (patch)
tree2c5a83521a20c02e7805581a174008aa9bc23579 /lib/Parse
parentf698f7e71940663e26a4806a96fb0bdfa160c886 (diff)
Notes
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/AttributeList.cpp3
-rw-r--r--lib/Parse/DeclSpec.cpp1
-rw-r--r--lib/Parse/MinimalAction.cpp1
-rw-r--r--lib/Parse/ParseDecl.cpp60
-rw-r--r--lib/Parse/ParseDeclCXX.cpp77
-rw-r--r--lib/Parse/ParseExprCXX.cpp154
-rw-r--r--lib/Parse/ParseObjc.cpp4
-rw-r--r--lib/Parse/ParseTemplate.cpp32
-rw-r--r--lib/Parse/ParseTentative.cpp7
-rw-r--r--lib/Parse/Parser.cpp26
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.