summaryrefslogtreecommitdiffstats
path: root/lib/Parse
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-03-03 17:28:16 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-03-03 17:28:16 +0000
commitdf90325d4c0a65ee64d2dae3ed9b5b34f7418533 (patch)
treee1a885aadfd80632f5bd70d4bd2d37e715e35a79 /lib/Parse
parentfd035e6496665b1f1197868e21cb0a4594e8db6e (diff)
downloadFreeBSD-src-df90325d4c0a65ee64d2dae3ed9b5b34f7418533.zip
FreeBSD-src-df90325d4c0a65ee64d2dae3ed9b5b34f7418533.tar.gz
Update clang to 97654.
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/AttributeList.cpp4
-rw-r--r--lib/Parse/ParseDecl.cpp231
-rw-r--r--lib/Parse/ParseDeclCXX.cpp63
-rw-r--r--lib/Parse/ParseExpr.cpp30
-rw-r--r--lib/Parse/ParseExprCXX.cpp190
-rw-r--r--lib/Parse/ParseObjc.cpp26
-rw-r--r--lib/Parse/ParseTentative.cpp19
-rw-r--r--lib/Parse/Parser.cpp50
8 files changed, 462 insertions, 151 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp
index df48e3a..b96dff5 100644
--- a/lib/Parse/AttributeList.cpp
+++ b/lib/Parse/AttributeList.cpp
@@ -57,6 +57,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
// FIXME: Hand generating this is neither smart nor efficient.
return llvm::StringSwitch<AttributeList::Kind>(AttrName)
.Case("weak", AT_weak)
+ .Case("weakref", AT_weakref)
.Case("pure", AT_pure)
.Case("mode", AT_mode)
.Case("used", AT_used)
@@ -82,6 +83,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("stdcall", AT_stdcall)
.Case("annotate", AT_annotate)
.Case("fastcall", AT_fastcall)
+ .Case("ibaction", AT_IBAction)
.Case("iboutlet", AT_IBOutlet)
.Case("noreturn", AT_noreturn)
.Case("noinline", AT_noinline)
@@ -111,7 +113,9 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) {
.Case("analyzer_noreturn", AT_analyzer_noreturn)
.Case("warn_unused_result", AT_warn_unused_result)
.Case("carries_dependency", AT_carries_dependency)
+ .Case("ns_returns_not_retained", AT_ns_returns_not_retained)
.Case("ns_returns_retained", AT_ns_returns_retained)
+ .Case("cf_returns_not_retained", AT_cf_returns_not_retained)
.Case("cf_returns_retained", AT_cf_returns_retained)
.Case("reqd_work_group_size", AT_reqd_wg_size)
.Case("no_instrument_function", AT_no_instrument_function)
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 8aa6936..12c5b6c 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -564,10 +564,10 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D,
}
if (Init.isInvalid()) {
- SkipUntil(tok::semi, true, true);
- return DeclPtrTy();
- }
- Actions.AddInitializerToDecl(ThisDecl, move(Init));
+ SkipUntil(tok::comma, true, true);
+ Actions.ActOnInitializerError(ThisDecl);
+ } else
+ Actions.AddInitializerToDecl(ThisDecl, move(Init));
}
} else if (Tok.is(tok::l_paren)) {
// Parse C++ direct initializer: '(' expression-list ')'
@@ -738,7 +738,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
// Parse this as a tag as if the missing tag were present.
if (TagKind == tok::kw_enum)
- ParseEnumSpecifier(Loc, DS, AS);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
else
ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS);
return true;
@@ -859,10 +859,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
return;
case tok::coloncolon: // ::foo::bar
- // Annotate C++ scope specifiers. If we get one, loop.
- if (TryAnnotateCXXScopeToken(true))
- continue;
- goto DoneWithDeclSpec;
+ // C++ scope specifier. Annotate and loop, or bail out on error.
+ if (TryAnnotateCXXScopeToken(true)) {
+ if (!DS.hasTypeSpecifier())
+ DS.SetTypeSpecError();
+ goto DoneWithDeclSpec;
+ }
+ if (Tok.is(tok::coloncolon)) // ::new or ::delete
+ goto DoneWithDeclSpec;
+ continue;
case tok::annot_cxxscope: {
if (DS.hasTypeSpecifier())
@@ -1020,8 +1025,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
case tok::identifier: {
// In C++, check to see if this is a scope specifier like foo::bar::, if
// so handle it as such. This is important for ctor parsing.
- if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true))
- continue;
+ if (getLang().CPlusPlus) {
+ if (TryAnnotateCXXScopeToken(true)) {
+ if (!DS.hasTypeSpecifier())
+ DS.SetTypeSpecError();
+ goto DoneWithDeclSpec;
+ }
+ if (!Tok.is(tok::identifier))
+ continue;
+ }
// This identifier can only be a typedef name if we haven't already seen
// a type-specifier. Without this check we misparse:
@@ -1294,7 +1306,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// enum-specifier:
case tok::kw_enum:
ConsumeToken();
- ParseEnumSpecifier(Loc, DS, AS);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS);
continue;
// cv-qualifier:
@@ -1313,7 +1325,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// C++ typename-specifier:
case tok::kw_typename:
- if (TryAnnotateTypeOrScopeToken())
+ if (TryAnnotateTypeOrScopeToken()) {
+ DS.SetTypeSpecError();
+ goto DoneWithDeclSpec;
+ }
+ if (!Tok.is(tok::kw_typename))
continue;
break;
@@ -1423,10 +1439,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
- TemplateInfo, SuppressDeclarations);
- // Otherwise, not a type specifier.
- return false;
+ return true;
+ if (Tok.is(tok::identifier))
+ return false;
+ return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ TemplateInfo, SuppressDeclarations);
case tok::coloncolon: // ::foo::bar
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
@@ -1435,10 +1452,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
- TemplateInfo, SuppressDeclarations);
- // Otherwise, not a type specifier.
- return false;
+ return true;
+ return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
+ TemplateInfo, SuppressDeclarations);
// simple-type-specifier:
case tok::annot_typename: {
@@ -1556,7 +1572,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid,
// enum-specifier:
case tok::kw_enum:
ConsumeToken();
- ParseEnumSpecifier(Loc, DS);
+ ParseEnumSpecifier(Loc, DS, TemplateInfo, AS_none);
return true;
// cv-qualifier:
@@ -1834,6 +1850,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
/// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier
///
void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
+ const ParsedTemplateInfo &TemplateInfo,
AccessSpecifier AS) {
// Parse the tag portion of this.
if (Tok.is(tok::code_completion)) {
@@ -1848,8 +1865,11 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
Attr.reset(ParseGNUAttributes());
CXXScopeSpec SS;
- if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) {
- if (Tok.isNot(tok::identifier)) {
+ if (getLang().CPlusPlus) {
+ if (ParseOptionalCXXScopeSpecifier(SS, 0, false))
+ return;
+
+ if (SS.isSet() && Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
if (Tok.isNot(tok::l_brace)) {
// Has no name and is not a definition.
@@ -1869,6 +1889,15 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
+ // enums cannot be templates.
+ if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
+ Diag(Tok, diag::err_enum_template);
+
+ // Skip the rest of this declarator, up until the comma or semicolon.
+ SkipUntil(tok::comma, true);
+ return;
+ }
+
// If an identifier is present, consume and remember it.
IdentifierInfo *Name = 0;
SourceLocation NameLoc;
@@ -2002,6 +2031,47 @@ bool Parser::isTypeQualifier() const {
}
}
+/// isKnownToBeTypeSpecifier - Return true if we know that the specified token
+/// is definitely a type-specifier. Return false if it isn't part of a type
+/// specifier or if we're not sure.
+bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {
+ switch (Tok.getKind()) {
+ default: return false;
+ // type-specifiers
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw__Complex:
+ case tok::kw__Imaginary:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_wchar_t:
+ case tok::kw_char16_t:
+ case tok::kw_char32_t:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw__Bool:
+ case tok::kw__Decimal32:
+ case tok::kw__Decimal64:
+ case tok::kw__Decimal128:
+ case tok::kw___vector:
+
+ // struct-or-union-specifier (C99) or class-specifier (C++)
+ case tok::kw_class:
+ case tok::kw_struct:
+ case tok::kw_union:
+ // enum-specifier
+ case tok::kw_enum:
+
+ // typedef-name
+ case tok::annot_typename:
+ return true;
+ }
+}
+
/// isTypeSpecifierQualifier - Return true if the current token could be the
/// start of a specifier-qualifier-list.
bool Parser::isTypeSpecifierQualifier() {
@@ -2016,21 +2086,19 @@ bool Parser::isTypeSpecifierQualifier() {
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return isTypeSpecifierQualifier();
- // Otherwise, not a type specifier.
- return false;
+ return true;
+ if (Tok.is(tok::identifier))
+ return false;
+ return isTypeSpecifierQualifier();
case tok::coloncolon: // ::foo::bar
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
return false;
- // Annotate typenames and C++ scope specifiers. If we get one, just
- // recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return isTypeSpecifierQualifier();
- // Otherwise, not a type specifier.
- return false;
+ return true;
+ return isTypeSpecifierQualifier();
// GNU attributes support.
case tok::kw___attribute:
@@ -2101,14 +2169,15 @@ bool Parser::isDeclarationSpecifier() {
if (TryAltiVecVectorToken())
return true;
// Fall through.
-
case tok::kw_typename: // typename T::type
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return isDeclarationSpecifier();
- // Otherwise, not a declaration specifier.
- return false;
+ return true;
+ if (Tok.is(tok::identifier))
+ return false;
+ return isDeclarationSpecifier();
+
case tok::coloncolon: // ::foo::bar
if (NextToken().is(tok::kw_new) || // ::new
NextToken().is(tok::kw_delete)) // ::delete
@@ -2117,9 +2186,8 @@ bool Parser::isDeclarationSpecifier() {
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return isDeclarationSpecifier();
- // Otherwise, not a declaration specifier.
- return false;
+ return true;
+ return isDeclarationSpecifier();
// storage-class-specifier
case tok::kw_typedef:
@@ -2200,7 +2268,10 @@ bool Parser::isConstructorDeclarator() {
// Parse the C++ scope specifier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, 0, true);
+ if (ParseOptionalCXXScopeSpecifier(SS, 0, true)) {
+ TPA.Revert();
+ return false;
+ }
// Parse the constructor name.
if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) {
@@ -2351,7 +2422,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
(Tok.is(tok::coloncolon) || Tok.is(tok::identifier) ||
Tok.is(tok::annot_cxxscope))) {
CXXScopeSpec SS;
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) {
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); // ignore fail
+
+ if (SS.isSet()) {
if (Tok.isNot(tok::star)) {
// The scope spec really belongs to the direct-declarator.
D.getCXXScopeSpec() = SS;
@@ -2507,9 +2580,13 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
if (getLang().CPlusPlus && D.mayHaveIdentifier()) {
// ParseDeclaratorInternal might already have parsed the scope.
- bool afterCXXScope = D.getCXXScopeSpec().isSet() ||
+ bool afterCXXScope = D.getCXXScopeSpec().isSet();
+ if (!afterCXXScope) {
ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0,
true);
+ afterCXXScope = D.getCXXScopeSpec().isSet();
+ }
+
if (afterCXXScope) {
if (Actions.ShouldEnterDeclaratorScope(CurScope, D.getCXXScopeSpec()))
// Change the declaration context for name lookup, until this function
@@ -2588,7 +2665,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
"Haven't past the location of the identifier yet?");
// Don't parse attributes unless we have an identifier.
- if (D.getIdentifier() && getLang().CPlusPlus
+ if (D.getIdentifier() && getLang().CPlusPlus0x
&& isCXX0XAttributeSpecifier(true)) {
SourceLocation AttrEndLoc;
CXX0XAttributeList Attr = ParseCXX0XAttributes();
@@ -2799,7 +2876,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// K&R-style function: void foo(a,b,c)
if (!getLang().CPlusPlus && Tok.is(tok::identifier)
&& !TryAltiVecVectorToken()) {
- if (!TryAnnotateTypeOrScopeToken()) {
+ if (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) {
// K&R identifier lists can't have typedefs as identifiers, per
// C99 6.7.5.3p11.
if (RequiresArg) {
@@ -3238,3 +3315,69 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
DiagID, Operand.release()))
Diag(StartLoc, DiagID) << PrevSpec;
}
+
+
+/// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called
+/// from TryAltiVecVectorToken.
+bool Parser::TryAltiVecVectorTokenOutOfLine() {
+ Token Next = NextToken();
+ switch (Next.getKind()) {
+ default: return false;
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw___pixel:
+ Tok.setKind(tok::kw___vector);
+ return true;
+ case tok::identifier:
+ if (Next.getIdentifierInfo() == Ident_pixel) {
+ Tok.setKind(tok::kw___vector);
+ return true;
+ }
+ return false;
+ }
+}
+
+bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,
+ const char *&PrevSpec, unsigned &DiagID,
+ bool &isInvalid) {
+ if (Tok.getIdentifierInfo() == Ident_vector) {
+ Token Next = NextToken();
+ switch (Next.getKind()) {
+ case tok::kw_short:
+ case tok::kw_long:
+ case tok::kw_signed:
+ case tok::kw_unsigned:
+ case tok::kw_void:
+ case tok::kw_char:
+ case tok::kw_int:
+ case tok::kw_float:
+ case tok::kw_double:
+ case tok::kw_bool:
+ case tok::kw___pixel:
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ return true;
+ case tok::identifier:
+ if (Next.getIdentifierInfo() == Ident_pixel) {
+ isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID);
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ } else if (Tok.getIdentifierInfo() == Ident_pixel &&
+ DS.isTypeAltiVecVector()) {
+ isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID);
+ return true;
+ }
+ return false;
+}
+
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 51ee6a4..bfb75d2 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -167,9 +167,7 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
assert(Tok.is(tok::string_literal) && "Not a string literal!");
llvm::SmallVector<char, 8> LangBuffer;
// LangBuffer is guaranteed to be big enough.
- LangBuffer.resize(Tok.getLength());
- const char *LangBufPtr = &LangBuffer[0];
- unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
+ llvm::StringRef Lang = PP.getSpelling(Tok, LangBuffer);
SourceLocation Loc = ConsumeStringToken();
@@ -177,7 +175,7 @@ Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
DeclPtrTy LinkageSpec
= Actions.ActOnStartLinkageSpecification(CurScope,
/*FIXME: */SourceLocation(),
- Loc, LangBufPtr, StrSize,
+ Loc, Lang.data(), Lang.size(),
Tok.is(tok::l_brace)? Tok.getLocation()
: SourceLocation());
@@ -464,8 +462,7 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
/// simple-template-id
///
Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
- const CXXScopeSpec *SS,
- bool DestrExpected) {
+ const CXXScopeSpec *SS) {
// Check whether we have a template-id that names a type.
if (Tok.is(tok::annot_template_id)) {
TemplateIdAnnotation *TemplateId
@@ -536,8 +533,7 @@ Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
// We have an identifier; check whether it is actually a type.
TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
if (!Type) {
- Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
- : diag::err_expected_class_name);
+ Diag(IdLoc, diag::err_expected_class_name);
return true;
}
@@ -647,7 +643,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// "FOO : BAR" is not a potential typo for "FOO::BAR".
ColonProtectionRAIIObject X(*this);
- if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+ if (SS.isSet())
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
Diag(Tok, diag::err_expected_ident);
}
@@ -943,7 +940,9 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
//
// This switch enumerates the valid "follow" set for definition.
if (TUK == Action::TUK_Definition) {
+ bool ExpectedSemi = true;
switch (Tok.getKind()) {
+ default: break;
case tok::semi: // struct foo {...} ;
case tok::star: // struct foo {...} * P;
case tok::amp: // struct foo {...} & R = ...
@@ -954,24 +953,46 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
case tok::annot_template_id: // struct foo {...} a<int> ::b;
case tok::l_paren: // struct foo {...} ( x);
case tok::comma: // __builtin_offsetof(struct foo{...} ,
+ ExpectedSemi = false;
+ break;
+ // Type qualifiers
+ case tok::kw_const: // struct foo {...} const x;
+ case tok::kw_volatile: // struct foo {...} volatile x;
+ case tok::kw_restrict: // struct foo {...} restrict x;
+ case tok::kw_inline: // struct foo {...} inline foo() {};
// Storage-class specifiers
case tok::kw_static: // struct foo {...} static x;
case tok::kw_extern: // struct foo {...} extern x;
case tok::kw_typedef: // struct foo {...} typedef x;
case tok::kw_register: // struct foo {...} register x;
case tok::kw_auto: // struct foo {...} auto x;
- // Type qualifiers
- case tok::kw_const: // struct foo {...} const x;
- case tok::kw_volatile: // struct foo {...} volatile x;
- case tok::kw_restrict: // struct foo {...} restrict x;
- case tok::kw_inline: // struct foo {...} inline foo() {};
+ // As shown above, type qualifiers and storage class specifiers absolutely
+ // can occur after class specifiers according to the grammar. However,
+ // almost noone actually writes code like this. If we see one of these,
+ // it is much more likely that someone missed a semi colon and the
+ // type/storage class specifier we're seeing is part of the *next*
+ // intended declaration, as in:
+ //
+ // struct foo { ... }
+ // typedef int X;
+ //
+ // We'd really like to emit a missing semicolon error instead of emitting
+ // an error on the 'int' saying that you can't have two type specifiers in
+ // the same declaration of X. Because of this, we look ahead past this
+ // token to see if it's a type specifier. If so, we know the code is
+ // otherwise invalid, so we can produce the expected semi error.
+ if (!isKnownToBeTypeSpecifier(NextToken()))
+ ExpectedSemi = false;
break;
case tok::r_brace: // struct bar { struct foo {...} }
// Missing ';' at end of struct is accepted as an extension in C mode.
- if (!getLang().CPlusPlus) break;
- // FALL THROUGH.
- default:
+ if (!getLang().CPlusPlus)
+ ExpectedSemi = false;
+ break;
+ }
+
+ if (ExpectedSemi) {
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
TagType == DeclSpec::TST_class ? "class"
: TagType == DeclSpec::TST_struct? "struct" : "union");
@@ -980,7 +1001,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// ';' after the definition.
PP.EnterToken(Tok);
Tok.setKind(tok::semi);
- break;
}
}
}
@@ -1064,7 +1084,8 @@ Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
// Parse optional '::' and optional nested-name-specifier.
CXXScopeSpec SS;
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
+ ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0,
+ /*EnteringContext=*/false);
// The location of the base class itself.
SourceLocation BaseLoc = Tok.getLocation();
@@ -1122,7 +1143,7 @@ void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
LateMethod->DefaultArgs.reserve(FTI.NumArgs);
for (unsigned I = 0; I < ParamIdx; ++I)
LateMethod->DefaultArgs.push_back(
- LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param));
+ LateParsedDefaultArgument(FTI.ArgInfo[I].Param));
}
// Add this parameter to the list of parameters (it or may
@@ -1165,7 +1186,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Access declarations.
if (!TemplateInfo.Kind &&
(Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
- TryAnnotateCXXScopeToken() &&
+ !TryAnnotateCXXScopeToken() &&
Tok.is(tok::annot_cxxscope)) {
bool isAccessDecl = false;
if (NextToken().is(tok::identifier))
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index c763c2c..af91021 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -626,6 +626,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
Next.is(tok::l_paren)) {
// If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ if (!Tok.is(tok::identifier))
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
}
}
@@ -790,7 +792,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
if (SavedKind == tok::kw_typename) {
// postfix-expression: typename-specifier '(' expression-list[opt] ')'
- if (!TryAnnotateTypeOrScopeToken())
+ if (TryAnnotateTypeOrScopeToken())
return ExprError();
}
@@ -852,6 +854,8 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
// ::foo::bar -> global qualified name etc. If TryAnnotateTypeOrScopeToken
// annotates the token, tail recurse.
if (TryAnnotateTypeOrScopeToken())
+ return ExprError();
+ if (!Tok.is(tok::coloncolon))
return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
// ::new -> [C++] new-expression
@@ -996,12 +1000,16 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
CXXScopeSpec SS;
Action::TypeTy *ObjectType = 0;
+ bool MayBePseudoDestructor = false;
if (getLang().CPlusPlus && !LHS.isInvalid()) {
LHS = Actions.ActOnStartCXXMemberReference(CurScope, move(LHS),
- OpLoc, OpKind, ObjectType);
+ OpLoc, OpKind, ObjectType,
+ MayBePseudoDestructor);
if (LHS.isInvalid())
break;
- ParseOptionalCXXScopeSpecifier(SS, ObjectType, false);
+
+ ParseOptionalCXXScopeSpecifier(SS, ObjectType, false,
+ &MayBePseudoDestructor);
}
if (Tok.is(tok::code_completion)) {
@@ -1012,6 +1020,17 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
ConsumeToken();
}
+ if (MayBePseudoDestructor) {
+ LHS = ParseCXXPseudoDestructor(move(LHS), OpLoc, OpKind, SS,
+ ObjectType);
+ break;
+ }
+
+ // Either the action has told is that this cannot be a
+ // pseudo-destructor expression (based on the type of base
+ // expression), or we didn't see a '~' in the right place. We
+ // can still parse a destructor name here, but in that case it
+ // names a real destructor.
UnqualifiedId Name;
if (ParseUnqualifiedId(SS,
/*EnteringContext=*/false,
@@ -1022,10 +1041,9 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {
return ExprError();
if (!LHS.isInvalid())
- LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc, OpKind,
- SS, Name, ObjCImpDecl,
+ LHS = Actions.ActOnMemberAccessExpr(CurScope, move(LHS), OpLoc,
+ OpKind, SS, Name, ObjCImpDecl,
Tok.is(tok::l_paren));
-
break;
}
case tok::plusplus: // postfix-expression: postfix-expression '++'
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 0dbe1ea..f1e989f 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -45,10 +45,21 @@ using namespace clang;
/// \param EnteringContext whether we will be entering into the context of
/// the nested-name-specifier after parsing it.
///
-/// \returns true if a scope specifier was parsed.
+/// \param MayBePseudoDestructor When non-NULL, points to a flag that
+/// indicates whether this nested-name-specifier may be part of a
+/// pseudo-destructor name. In this case, the flag will be set false
+/// if we don't actually end up parsing a destructor name. Moreorover,
+/// if we do end up determining that we are parsing a destructor name,
+/// the last component of the nested-name-specifier is not parsed as
+/// part of the scope specifier.
+
+/// member access expression, e.g., the \p T:: in \p p->T::m.
+///
+/// \returns true if there was an error parsing a scope specifier
bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
Action::TypeTy *ObjectType,
- bool EnteringContext) {
+ bool EnteringContext,
+ bool *MayBePseudoDestructor) {
assert(getLang().CPlusPlus &&
"Call sites of this function should be guarded by checking for C++");
@@ -56,7 +67,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
SS.setScopeRep(Tok.getAnnotationValue());
SS.setRange(Tok.getAnnotationRange());
ConsumeToken();
- return true;
+ return false;
}
bool HasScopeSpecifier = false;
@@ -75,6 +86,12 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
HasScopeSpecifier = true;
}
+ bool CheckForDestructor = false;
+ if (MayBePseudoDestructor && *MayBePseudoDestructor) {
+ CheckForDestructor = true;
+ *MayBePseudoDestructor = false;
+ }
+
while (true) {
if (HasScopeSpecifier) {
// C++ [basic.lookup.classref]p5:
@@ -151,10 +168,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
= Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
ObjectType, EnteringContext);
if (!Template)
- break;
+ return true;
if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
&SS, TemplateName, TemplateKWLoc, false))
- break;
+ return true;
continue;
}
@@ -169,6 +186,10 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// convert it into a type within the nested-name-specifier.
TemplateIdAnnotation *TemplateId
= static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde)) {
+ *MayBePseudoDestructor = true;
+ return false;
+ }
if (TemplateId->Kind == TNK_Type_template ||
TemplateId->Kind == TNK_Dependent_template_name) {
@@ -217,21 +238,29 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
// If we get foo:bar, this is almost certainly a typo for foo::bar. Recover
// and emit a fixit hint for it.
- if (Next.is(tok::colon) && !ColonIsSacred &&
- Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
- EnteringContext) &&
- // If the token after the colon isn't an identifier, it's still an
- // error, but they probably meant something else strange so don't
- // recover like this.
- PP.LookAhead(1).is(tok::identifier)) {
- Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
- << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
-
- // Recover as if the user wrote '::'.
- Next.setKind(tok::coloncolon);
+ if (Next.is(tok::colon) && !ColonIsSacred) {
+ if (Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
+ EnteringContext) &&
+ // If the token after the colon isn't an identifier, it's still an
+ // error, but they probably meant something else strange so don't
+ // recover like this.
+ PP.LookAhead(1).is(tok::identifier)) {
+ Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
+ << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
+
+ // Recover as if the user wrote '::'.
+ Next.setKind(tok::coloncolon);
+ }
}
if (Next.is(tok::coloncolon)) {
+ if (CheckForDestructor && GetLookAheadToken(2).is(tok::tilde) &&
+ !Actions.isNonTypeNestedNameSpecifier(CurScope, SS, Tok.getLocation(),
+ II, ObjectType)) {
+ *MayBePseudoDestructor = true;
+ return false;
+ }
+
// We have an identifier followed by a '::'. Lookup this name
// as the name in a nested-name-specifier.
SourceLocation IdLoc = ConsumeToken();
@@ -274,7 +303,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
ConsumeToken();
if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName,
SourceLocation(), false))
- break;
+ return true;
continue;
}
}
@@ -284,7 +313,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
break;
}
- return HasScopeSpecifier;
+ // Even if we didn't see any pieces of a nested-name-specifier, we
+ // still check whether there is a tilde in this position, which
+ // indicates a potential pseudo-destructor.
+ if (CheckForDestructor && Tok.is(tok::tilde))
+ *MayBePseudoDestructor = true;
+
+ return false;
}
/// ParseCXXIdExpression - Handle id-expression.
@@ -479,6 +514,77 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
return move(Result);
}
+/// \brief Parse a C++ pseudo-destructor expression after the base,
+/// . or -> operator, and nested-name-specifier have already been
+/// parsed.
+///
+/// postfix-expression: [C++ 5.2]
+/// postfix-expression . pseudo-destructor-name
+/// postfix-expression -> pseudo-destructor-name
+///
+/// pseudo-destructor-name:
+/// ::[opt] nested-name-specifier[opt] type-name :: ~type-name
+/// ::[opt] nested-name-specifier template simple-template-id ::
+/// ~type-name
+/// ::[opt] nested-name-specifier[opt] ~type-name
+///
+Parser::OwningExprResult
+Parser::ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc,
+ tok::TokenKind OpKind,
+ CXXScopeSpec &SS,
+ Action::TypeTy *ObjectType) {
+ // We're parsing either a pseudo-destructor-name or a dependent
+ // member access that has the same form as a
+ // pseudo-destructor-name. We parse both in the same way and let
+ // the action model sort them out.
+ //
+ // Note that the ::[opt] nested-name-specifier[opt] has already
+ // been parsed, and if there was a simple-template-id, it has
+ // been coalesced into a template-id annotation token.
+ UnqualifiedId FirstTypeName;
+ SourceLocation CCLoc;
+ if (Tok.is(tok::identifier)) {
+ FirstTypeName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
+ CCLoc = ConsumeToken();
+ } else if (Tok.is(tok::annot_template_id)) {
+ FirstTypeName.setTemplateId(
+ (TemplateIdAnnotation *)Tok.getAnnotationValue());
+ ConsumeToken();
+ assert(Tok.is(tok::coloncolon) &&"ParseOptionalCXXScopeSpecifier fail");
+ CCLoc = ConsumeToken();
+ } else {
+ FirstTypeName.setIdentifier(0, SourceLocation());
+ }
+
+ // Parse the tilde.
+ assert(Tok.is(tok::tilde) && "ParseOptionalCXXScopeSpecifier fail");
+ SourceLocation TildeLoc = ConsumeToken();
+ if (!Tok.is(tok::identifier)) {
+ Diag(Tok, diag::err_destructor_tilde_identifier);
+ return ExprError();
+ }
+
+ // Parse the second type.
+ UnqualifiedId SecondTypeName;
+ IdentifierInfo *Name = Tok.getIdentifierInfo();
+ SourceLocation NameLoc = ConsumeToken();
+ SecondTypeName.setIdentifier(Name, NameLoc);
+
+ // If there is a '<', the second type name is a template-id. Parse
+ // it as such.
+ if (Tok.is(tok::less) &&
+ ParseUnqualifiedIdTemplateId(SS, Name, NameLoc, false, ObjectType,
+ SecondTypeName, /*AssumeTemplateName=*/true))
+ return ExprError();
+
+ return Actions.ActOnPseudoDestructorExpr(CurScope, move(Base), OpLoc, OpKind,
+ SS, FirstTypeName, CCLoc,
+ TildeLoc, SecondTypeName,
+ Tok.is(tok::l_paren));
+}
+
/// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
///
/// boolean-literal: [C++ 2.13.5]
@@ -773,6 +879,7 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
ParsedTemplateInfo(), /*SuppressDeclarations*/true))
{}
+ DS.Finish(Diags, PP);
return false;
}
@@ -804,13 +911,17 @@ bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
/// that precedes the '<'. If template arguments were parsed successfully,
/// will be updated with the template-id.
///
+/// \param AssumeTemplateId When true, this routine will assume that the name
+/// refers to a template without performing name lookup to verify.
+///
/// \returns true if a parse error occurred, false otherwise.
bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
IdentifierInfo *Name,
SourceLocation NameLoc,
bool EnteringContext,
TypeTy *ObjectType,
- UnqualifiedId &Id) {
+ UnqualifiedId &Id,
+ bool AssumeTemplateId) {
assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
TemplateTy Template;
@@ -819,8 +930,16 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_LiteralOperatorId:
- TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext,
- Template);
+ if (AssumeTemplateId) {
+ Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS,
+ Id, ObjectType,
+ EnteringContext);
+ TNK = TNK_Dependent_template_name;
+ if (!Template.get())
+ return true;
+ } else
+ TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType,
+ EnteringContext, Template);
break;
case UnqualifiedId::IK_ConstructorName: {
@@ -846,13 +965,8 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
EnteringContext, Template);
if (TNK == TNK_Non_template && Id.DestructorName == 0) {
- // The identifier following the destructor did not refer to a template
- // or to a type. Complain.
- if (ObjectType)
- Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << Name;
- else
- Diag(NameLoc, diag::err_destructor_class_name);
+ Diag(NameLoc, diag::err_destructor_template_id)
+ << Name << SS.getRange();
return true;
}
}
@@ -1258,7 +1372,7 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
// Parse the class-name.
if (Tok.isNot(tok::identifier)) {
- Diag(Tok, diag::err_destructor_class_name);
+ Diag(Tok, diag::err_destructor_tilde_identifier);
return true;
}
@@ -1273,17 +1387,13 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
}
// Note that this is a destructor name.
- Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
- CurScope, &SS, false, ObjectType);
- if (!Ty) {
- if (ObjectType)
- Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << ClassName;
- else
- Diag(ClassNameLoc, diag::err_destructor_class_name);
+ Action::TypeTy *Ty = Actions.getDestructorName(TildeLoc, *ClassName,
+ ClassNameLoc, CurScope,
+ SS, ObjectType,
+ EnteringContext);
+ if (!Ty)
return true;
- }
-
+
Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
return false;
}
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index d1c9be2..7ab0e71 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -188,7 +188,10 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
ProtocolRefs.size(),
ProtocolLocs.data(),
EndProtoLoc);
-
+ if (Tok.is(tok::l_brace))
+ ParseObjCClassInstanceVariables(CategoryType, tok::objc_private,
+ atLoc);
+
ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
return CategoryType;
}
@@ -229,7 +232,7 @@ Parser::DeclPtrTy Parser::ParseObjCAtInterfaceDeclaration(
EndProtoLoc, attrList);
if (Tok.is(tok::l_brace))
- ParseObjCClassInstanceVariables(ClsType, atLoc);
+ ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, atLoc);
ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
return ClsType;
@@ -772,6 +775,12 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
if (Tok.is(tok::l_paren))
ReturnType = ParseObjCTypeName(DSRet);
+ // If attributes exist before the method, parse them.
+ llvm::OwningPtr<AttributeList> MethodAttrs;
+ if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
+ MethodAttrs.reset(ParseGNUAttributes());
+
+ // Now parse the selector.
SourceLocation selLoc;
IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);
@@ -787,9 +796,9 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
llvm::SmallVector<Declarator, 8> CargNames;
if (Tok.isNot(tok::colon)) {
// If attributes exist after the method, parse them.
- llvm::OwningPtr<AttributeList> MethodAttrs;
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs.reset(ParseGNUAttributes());
+ MethodAttrs.reset(addAttributeLists(MethodAttrs.take(),
+ ParseGNUAttributes()));
Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
DeclPtrTy Result
@@ -863,9 +872,9 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDecl(SourceLocation mLoc,
// FIXME: Add support for optional parmameter list...
// If attributes exist after the method, parse them.
- llvm::OwningPtr<AttributeList> MethodAttrs;
if (getLang().ObjC2 && Tok.is(tok::kw___attribute))
- MethodAttrs.reset(ParseGNUAttributes());
+ MethodAttrs.reset(addAttributeLists(MethodAttrs.take(),
+ ParseGNUAttributes()));
if (KeyIdents.size() == 0)
return DeclPtrTy();
@@ -959,6 +968,7 @@ ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &Protocols,
/// struct-declaration
///
void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
+ tok::ObjCKeywordKind visibility,
SourceLocation atLoc) {
assert(Tok.is(tok::l_brace) && "expected {");
llvm::SmallVector<DeclPtrTy, 32> AllIvarDecls;
@@ -967,7 +977,6 @@ void Parser::ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl,
SourceLocation LBraceLoc = ConsumeBrace(); // the "{"
- tok::ObjCKeywordKind visibility = tok::objc_protected;
// While we still have something to read, read the instance variables.
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
// Each iteration of this loop reads one objc-instance-variable-decl.
@@ -1222,7 +1231,8 @@ Parser::DeclPtrTy Parser::ParseObjCAtImplementationDeclaration(
superClassId, superClassLoc);
if (Tok.is(tok::l_brace)) // we have ivars
- ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/, atLoc);
+ ParseObjCClassInstanceVariables(ImplClsType/*FIXME*/,
+ tok::objc_protected, atLoc);
ObjCImpDecl = ImplClsType;
PendingObjCImpDecl.push_back(ObjCImpDecl);
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 6251a2f..516a9a6 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -491,7 +491,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
while (1) {
if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
- TryAnnotateCXXScopeToken(true);
+ if (TryAnnotateCXXScopeToken(true))
+ return TPResult::Error();
if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
@@ -681,9 +682,10 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return isCXXDeclarationSpecifier();
- // Otherwise, not a typename.
- return TPResult::False();
+ return TPResult::Error();
+ if (Tok.is(tok::identifier))
+ return TPResult::False();
+ return isCXXDeclarationSpecifier();
case tok::coloncolon: { // ::foo::bar
const Token &Next = NextToken();
@@ -694,9 +696,8 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
// Annotate typenames and C++ scope specifiers. If we get one, just
// recurse to handle whatever we get.
if (TryAnnotateTypeOrScopeToken())
- return isCXXDeclarationSpecifier();
- // Otherwise, not a typename.
- return TPResult::False();
+ return TPResult::Error();
+ return isCXXDeclarationSpecifier();
}
// decl-specifier:
@@ -762,7 +763,9 @@ Parser::TPResult Parser::isCXXDeclarationSpecifier() {
case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
// We've already annotated a scope; try to annotate a type.
- if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename)))
+ if (TryAnnotateTypeOrScopeToken())
+ return TPResult::Error();
+ if (!Tok.is(tok::annot_typename))
return TPResult::False();
// If that succeeded, fallthrough into the generic simple-type-id case.
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 30899c5..e7a771e 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -274,6 +274,7 @@ void Parser::EnterScope(unsigned ScopeFlags) {
} else {
CurScope = new Scope(CurScope, ScopeFlags);
}
+ CurScope->setNumErrorsAtStart(Diags.getNumErrors());
}
/// ExitScope - Pop a scope off the scope stack.
@@ -743,10 +744,11 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) {
// Handle the full declarator list.
while (1) {
// If attributes are present, parse them.
- llvm::OwningPtr<AttributeList> AttrList;
- if (Tok.is(tok::kw___attribute))
- // FIXME: attach attributes too.
- AttrList.reset(ParseGNUAttributes());
+ if (Tok.is(tok::kw___attribute)) {
+ SourceLocation Loc;
+ AttributeList *AttrList = ParseGNUAttributes(&Loc);
+ ParmDeclarator.AddAttributes(AttrList, Loc);
+ }
// Ask the actions module to compute the type for this declarator.
Action::DeclPtrTy Param =
@@ -890,8 +892,7 @@ 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 or an unrecoverable error
-/// occurs.
+/// This returns true if an error occurred.
///
/// 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.
@@ -909,11 +910,11 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// simple-template-id
SourceLocation TypenameLoc = ConsumeToken();
CXXScopeSpec SS;
- bool HadNestedNameSpecifier
- = ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
- if (!HadNestedNameSpecifier) {
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false))
+ return true;
+ if (!SS.isSet()) {
Diag(Tok.getLocation(), diag::err_expected_qualified_after_typename);
- return false;
+ return true;
}
TypeResult Ty;
@@ -927,7 +928,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
if (TemplateId->Kind == TNK_Function_template) {
Diag(Tok, diag::err_typename_refers_to_non_type_template)
<< Tok.getAnnotationRange();
- return false;
+ return true;
}
AnnotateTemplateIdTokenAsType(0);
@@ -941,7 +942,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
} else {
Diag(Tok, diag::err_expected_type_name_after_typename)
<< SS.getRange();
- return false;
+ return true;
}
SourceLocation EndLoc = Tok.getLastLoc();
@@ -950,7 +951,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
Tok.setAnnotationEndLoc(EndLoc);
Tok.setLocation(TypenameLoc);
PP.AnnotateCachedTokens(Tok);
- return true;
+ return false;
}
// Remembers whether the token was originally a scope annotation.
@@ -958,7 +959,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
CXXScopeSpec SS;
if (getLang().CPlusPlus)
- ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext);
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+ return true;
if (Tok.is(tok::identifier)) {
// Determine whether the identifier is a type name.
@@ -975,7 +977,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// In case the tokens were cached, have Preprocessor replace
// them with the annotation token.
PP.AnnotateCachedTokens(Tok);
- return true;
+ return false;
}
if (!getLang().CPlusPlus) {
@@ -1000,7 +1002,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// 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);
+ return true;
}
}
}
@@ -1020,12 +1022,12 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// to produce a type annotation token. Update the template-id
// annotation token to a type annotation token now.
AnnotateTemplateIdTokenAsType(&SS);
- return true;
+ return false;
}
}
if (SS.isEmpty())
- return Tok.isNot(tok::identifier) && Tok.isNot(tok::coloncolon);
+ return false;
// 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
@@ -1043,7 +1045,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) {
// just reverted back to the state we were in before being called.
if (!wasScopeAnnotation)
PP.AnnotateCachedTokens(Tok);
- return true;
+ return false;
}
/// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only
@@ -1060,10 +1062,10 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
"Cannot be a type or scope token!");
CXXScopeSpec SS;
- if (!ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
- // If the token left behind is not an identifier, we either had an error or
- // successfully turned it into an annotation token.
- return Tok.isNot(tok::identifier);
+ if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, EnteringContext))
+ return true;
+ if (!SS.isSet())
+ return false;
// Push the current token back into the token stream (or revert it if it is
// cached) and use an annotation scope token for current token.
@@ -1078,7 +1080,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) {
// In case the tokens were cached, have Preprocessor replace them with the
// annotation token.
PP.AnnotateCachedTokens(Tok);
- return true;
+ return false;
}
// Anchor the Parser::FieldCallback vtable to this translation unit.
OpenPOWER on IntegriCloud