aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
commitbfef399519ca9b8a4b4c6b563253bad7e0eeffe0 (patch)
treedf8df0b0067b381eab470a3b8f28d14a552a6340 /lib/Parse/ParseDeclCXX.cpp
parent6a0372513edbc473b538d2f724efac50405d6fef (diff)
downloadsrc-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.tar.gz
src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.zip
Notes
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r--lib/Parse/ParseDeclCXX.cpp421
1 files changed, 276 insertions, 145 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index f1fbbb15fed5..16d06d7d152c 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -15,6 +15,7 @@
#include "RAIIObjectsForParser.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/OperatorKinds.h"
+#include "clang/AST/DeclTemplate.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
@@ -123,13 +124,13 @@ Decl *Parser::ParseNamespace(unsigned Context,
<< SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back());
}
Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
- SkipUntil(tok::r_brace, false);
+ SkipUntil(tok::r_brace);
return 0;
}
if (!ExtraIdent.empty()) {
TentativeParsingAction TPA(*this);
- SkipUntil(tok::r_brace, /*StopAtSemi*/false, /*DontConsume*/true);
+ SkipUntil(tok::r_brace, StopBeforeMatch);
Token rBraceToken = Tok;
TPA.Revert();
@@ -451,20 +452,18 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
Decl **OwnedType) {
CXXScopeSpec SS;
SourceLocation TypenameLoc;
- bool IsTypeName = false;
- ParsedAttributesWithRange Attrs(AttrFactory);
+ bool HasTypenameKeyword = false;
- // FIXME: Simply skip the attributes and diagnose, don't bother parsing them.
- MaybeParseCXX11Attributes(Attrs);
- ProhibitAttributes(Attrs);
- Attrs.clear();
- Attrs.Range = SourceRange();
+ // Check for misplaced attributes before the identifier in an
+ // alias-declaration.
+ ParsedAttributesWithRange MisplacedAttrs(AttrFactory);
+ MaybeParseCXX11Attributes(MisplacedAttrs);
// Ignore optional 'typename'.
// FIXME: This is wrong; we should parse this as a typename-specifier.
if (Tok.is(tok::kw_typename)) {
TypenameLoc = ConsumeToken();
- IsTypeName = true;
+ HasTypenameKeyword = true;
}
// Parse nested-name-specifier.
@@ -508,13 +507,25 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
return 0;
}
+ ParsedAttributesWithRange Attrs(AttrFactory);
+ MaybeParseGNUAttributes(Attrs);
MaybeParseCXX11Attributes(Attrs);
// Maybe this is an alias-declaration.
- bool IsAliasDecl = Tok.is(tok::equal);
TypeResult TypeAlias;
+ bool IsAliasDecl = Tok.is(tok::equal);
if (IsAliasDecl) {
- // TODO: Can GNU attributes appear here?
+ // If we had any misplaced attributes from earlier, this is where they
+ // should have been written.
+ if (MisplacedAttrs.Range.isValid()) {
+ Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
+ << FixItHint::CreateInsertionFromRange(
+ Tok.getLocation(),
+ CharSourceRange::getTokenRange(MisplacedAttrs.Range))
+ << FixItHint::CreateRemoval(MisplacedAttrs.Range);
+ Attrs.takeAllFrom(MisplacedAttrs);
+ }
+
ConsumeToken();
Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
@@ -549,7 +560,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// No removal fixit: can't recover from this.
SkipUntil(tok::semi);
return 0;
- } else if (IsTypeName)
+ } else if (HasTypenameKeyword)
Diag(TypenameLoc, diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SourceRange(TypenameLoc,
SS.isNotEmpty() ? SS.getEndLoc() : TypenameLoc));
@@ -564,6 +575,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
} else {
// C++11 attributes are not allowed on a using-declaration, but GNU ones
// are.
+ ProhibitAttributes(MisplacedAttrs);
ProhibitAttributes(Attrs);
// Parse (optional) attributes (most likely GNU strong-using extension).
@@ -593,11 +605,11 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
// "typename" keyword is allowed for identifiers only,
// because it may be a type definition.
- if (IsTypeName && Name.getKind() != UnqualifiedId::IK_Identifier) {
+ if (HasTypenameKeyword && Name.getKind() != UnqualifiedId::IK_Identifier) {
Diag(Name.getSourceRange().getBegin(), diag::err_typename_identifiers_only)
<< FixItHint::CreateRemoval(SourceRange(TypenameLoc));
- // Proceed parsing, but reset the IsTypeName flag.
- IsTypeName = false;
+ // Proceed parsing, but reset the HasTypenameKeyword flag.
+ HasTypenameKeyword = false;
}
if (IsAliasDecl) {
@@ -610,9 +622,10 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
TypeAlias);
}
- return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
- Name, Attrs.getList(),
- IsTypeName, TypenameLoc);
+ return Actions.ActOnUsingDeclaration(getCurScope(), AS,
+ /* HasUsingKeyword */ true, UsingLoc,
+ SS, Name, Attrs.getList(),
+ HasTypenameKeyword, TypenameLoc);
}
/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
@@ -729,8 +742,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
Result = ParseExpression();
if (Result.isInvalid()) {
DS.SetTypeSpecError();
- if (SkipUntil(tok::r_paren, /*StopAtSemi=*/true,
- /*DontConsume=*/true)) {
+ if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
EndLoc = ConsumeParen();
} else {
if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) {
@@ -813,7 +825,7 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
TypeResult Result = ParseTypeName();
if (Result.isInvalid()) {
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return;
}
@@ -827,6 +839,7 @@ void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
DiagID, Result.release()))
Diag(StartLoc, DiagID) << PrevSpec;
+ DS.setTypeofParensRange(T.getRange());
}
/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
@@ -917,8 +930,13 @@ Parser::TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
<< Id;
}
- if (!Template)
+ if (!Template) {
+ TemplateArgList TemplateArgs;
+ SourceLocation LAngleLoc, RAngleLoc;
+ ParseTemplateIdAfterTemplateName(TemplateTy(), IdLoc, SS,
+ true, LAngleLoc, TemplateArgs, RAngleLoc);
return true;
+ }
// Form the template name
UnqualifiedId TemplateName;
@@ -979,8 +997,8 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
Tok.is(tok::kw___virtual_inheritance)) {
IdentifierInfo *AttrName = Tok.getIdentifierInfo();
SourceLocation AttrNameLoc = ConsumeToken();
- attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0,
- SourceLocation(), 0, 0, AttributeList::AS_GNU);
+ attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, 0,
+ AttributeList::AS_GNU);
}
}
@@ -1140,8 +1158,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
ParsedAttributesWithRange attrs(AttrFactory);
// If attributes exist after tag, parse them.
- if (Tok.is(tok::kw___attribute))
- ParseGNUAttributes(attrs);
+ MaybeParseGNUAttributes(attrs);
// If declspecs exist after tag, parse them.
while (Tok.is(tok::kw___declspec))
@@ -1151,7 +1168,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (Tok.is(tok::kw___single_inheritance) ||
Tok.is(tok::kw___multiple_inheritance) ||
Tok.is(tok::kw___virtual_inheritance))
- ParseMicrosoftInheritanceClassAttributes(attrs);
+ ParseMicrosoftInheritanceClassAttributes(attrs);
// If C++0x attributes exist here, parse them.
// FIXME: Are we consistent with the ordering of parsing of different
@@ -1180,15 +1197,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Tok.is(tok::kw___is_scalar) ||
Tok.is(tok::kw___is_signed) ||
Tok.is(tok::kw___is_unsigned) ||
- Tok.is(tok::kw___is_void))) {
+ Tok.is(tok::kw___is_void)))
// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
// name of struct templates, but some are keywords in GCC >= 4.3
// and Clang. Therefore, when we see the token sequence "struct
// X", make X into a normal identifier rather than a keyword, to
// allow libstdc++ 4.2 and libc++ to work properly.
- Tok.getIdentifierInfo()->RevertTokenIDToIdentifier();
- Tok.setKind(tok::identifier);
- }
+ TryKeywordIdentFallback(true);
// Parse the (optional) nested-name-specifier.
CXXScopeSpec &SS = DS.getTypeSpecScope();
@@ -1231,7 +1246,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
<< (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
<< (TagType == DeclSpec::TST_class? 0
: TagType == DeclSpec::TST_struct? 1
- : TagType == DeclSpec::TST_interface? 2
+ : TagType == DeclSpec::TST_union? 2
: 3)
<< Name
<< SourceRange(LAngleLoc, RAngleLoc);
@@ -1272,10 +1287,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
Range.setBegin(SS.getBeginLoc());
Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
- << Name << static_cast<int>(TemplateId->Kind) << Range;
+ << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;
DS.SetTypeSpecError();
- SkipUntil(tok::semi, false, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
return;
}
}
@@ -1323,7 +1338,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// Skip everything up to the semicolon, so that this looks like a proper
// friend class (or template thereof) declaration.
- SkipUntil(tok::semi, true, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
TUK = Sema::TUK_Friend;
} else {
// Okay, this is a class definition.
@@ -1342,12 +1357,12 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
while (true) {
if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
ConsumeBracket();
- if (!SkipUntil(tok::r_square))
+ if (!SkipUntil(tok::r_square, StopAtSemi))
break;
} else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) {
ConsumeToken();
ConsumeParen();
- if (!SkipUntil(tok::r_paren))
+ if (!SkipUntil(tok::r_paren, StopAtSemi))
break;
} else {
break;
@@ -1412,7 +1427,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
<< DeclSpec::getSpecifierName(TagType);
}
- SkipUntil(tok::comma, true);
+ SkipUntil(tok::comma, StopAtSemi);
return;
}
@@ -1465,7 +1480,6 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// This is an explicit specialization or a class template
// partial specialization.
TemplateParameterLists FakedParamLists;
-
if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
// This looks like an explicit instantiation, because we have
// something like
@@ -1475,25 +1489,31 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
// but it actually has a definition. Most likely, this was
// meant to be an explicit specialization, but the user forgot
// the '<>' after 'template'.
- assert(TUK == Sema::TUK_Definition && "Expected a definition here");
-
- SourceLocation LAngleLoc
- = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
- Diag(TemplateId->TemplateNameLoc,
- diag::err_explicit_instantiation_with_definition)
- << SourceRange(TemplateInfo.TemplateLoc)
- << FixItHint::CreateInsertion(LAngleLoc, "<>");
-
- // Create a fake template parameter list that contains only
- // "template<>", so that we treat this construct as a class
- // template specialization.
- FakedParamLists.push_back(
- Actions.ActOnTemplateParameterList(0, SourceLocation(),
- TemplateInfo.TemplateLoc,
- LAngleLoc,
- 0, 0,
- LAngleLoc));
- TemplateParams = &FakedParamLists;
+ // It this is friend declaration however, since it cannot have a
+ // template header, it is most likely that the user meant to
+ // remove the 'template' keyword.
+ assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) &&
+ "Expected a definition here");
+
+ if (TUK == Sema::TUK_Friend) {
+ Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation);
+ TemplateParams = 0;
+ } else {
+ SourceLocation LAngleLoc =
+ PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+ Diag(TemplateId->TemplateNameLoc,
+ diag::err_explicit_instantiation_with_definition)
+ << SourceRange(TemplateInfo.TemplateLoc)
+ << FixItHint::CreateInsertion(LAngleLoc, "<>");
+
+ // Create a fake template parameter list that contains only
+ // "template<>", so that we treat this construct as a class
+ // template specialization.
+ FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
+ LAngleLoc));
+ TemplateParams = &FakedParamLists;
+ }
}
// Build the class template specialization.
@@ -1540,6 +1560,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
ProhibitAttributes(attrs);
+ if (TUK == Sema::TUK_Definition &&
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
+ // If the declarator-id is not a template-id, issue a diagnostic and
+ // recover by ignoring the 'template' keyword.
+ Diag(Tok, diag::err_template_defn_explicit_instantiation)
+ << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
+ TemplateParams = 0;
+ }
+
bool IsDependent = false;
// Don't pass down template parameter lists if this is just a tag
@@ -1641,7 +1670,7 @@ void Parser::ParseBaseClause(Decl *ClassDecl) {
if (Result.isInvalid()) {
// Skip the rest of this base specifier, up until the comma or
// opening brace.
- SkipUntil(tok::comma, tok::l_brace, true, true);
+ SkipUntil(tok::comma, tok::l_brace, StopAtSemi | StopBeforeMatch);
} else {
// Add this to our array of base specifiers.
BaseInfo.push_back(Result.get());
@@ -1800,12 +1829,17 @@ VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
// Initialize the contextual keywords.
if (!Ident_final) {
Ident_final = &PP.getIdentifierTable().get("final");
+ if (getLangOpts().MicrosoftExt)
+ Ident_sealed = &PP.getIdentifierTable().get("sealed");
Ident_override = &PP.getIdentifierTable().get("override");
}
if (II == Ident_override)
return VirtSpecifiers::VS_Override;
+ if (II == Ident_sealed)
+ return VirtSpecifiers::VS_Sealed;
+
if (II == Ident_final)
return VirtSpecifiers::VS_Final;
}
@@ -1833,14 +1867,18 @@ void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
<< PrevSpec
<< FixItHint::CreateRemoval(Tok.getLocation());
- if (IsInterface && Specifier == VirtSpecifiers::VS_Final) {
+ if (IsInterface && (Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_Sealed)) {
Diag(Tok.getLocation(), diag::err_override_control_interface)
<< VirtSpecifiers::getSpecifierName(Specifier);
+ } else if (Specifier == VirtSpecifiers::VS_Sealed) {
+ Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword);
} else {
- Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_override_control_keyword :
- diag::ext_override_control_keyword)
- << VirtSpecifiers::getSpecifierName(Specifier);
+ Diag(Tok.getLocation(),
+ getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_override_control_keyword
+ : diag::ext_override_control_keyword)
+ << VirtSpecifiers::getSpecifierName(Specifier);
}
ConsumeToken();
}
@@ -1858,10 +1896,13 @@ bool Parser::isCXX11FinalKeyword() const {
// Initialize the contextual keywords.
if (!Ident_final) {
Ident_final = &PP.getIdentifierTable().get("final");
+ if (getLangOpts().MicrosoftExt)
+ Ident_sealed = &PP.getIdentifierTable().get("sealed");
Ident_override = &PP.getIdentifierTable().get("override");
}
-
- return Tok.getIdentifierInfo() == Ident_final;
+
+ return Tok.getIdentifierInfo() == Ident_final ||
+ Tok.getIdentifierInfo() == Ident_sealed;
}
/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
@@ -1892,6 +1933,7 @@ bool Parser::isCXX11FinalKeyword() const {
/// virt-specifier:
/// override
/// final
+/// [MS] sealed
///
/// pure-specifier:
/// '= 0'
@@ -1908,12 +1950,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
Diag(Tok, diag::err_at_defs_cxx);
else
Diag(Tok, diag::err_at_in_class);
-
+
ConsumeToken();
- SkipUntil(tok::r_brace);
+ SkipUntil(tok::r_brace, StopAtSemi);
return;
}
-
+
// Access declarations.
bool MalformedTypeSpec = false;
if (!TemplateInfo.Kind &&
@@ -1952,10 +1994,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
return;
Actions.ActOnUsingDeclaration(getCurScope(), AS,
- false, SourceLocation(),
+ /* HasUsingKeyword */ false,
+ SourceLocation(),
SS, Name,
/* AttrList */ 0,
- /* IsTypeName */ false,
+ /* HasTypenameKeyword */ false,
SourceLocation());
return;
}
@@ -2010,7 +2053,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (Tok.is(tok::kw_namespace)) {
Diag(UsingLoc, diag::err_using_namespace_in_class);
- SkipUntil(tok::semi, true, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
} else {
SourceLocation DeclEnd;
// Otherwise, it must be a using-declaration or an alias-declaration.
@@ -2032,6 +2075,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
&CommonLateParsedAttrs);
+ // If we had a free-standing type definition with a missing semicolon, we
+ // may get this far before the problem becomes obvious.
+ if (DS.hasTagDefinition() &&
+ TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&
+ DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class,
+ &CommonLateParsedAttrs))
+ return;
+
MultiTemplateParamsArg TemplateParams(
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
@@ -2066,7 +2117,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// Error parsing the declarator?
if (!DeclaratorInfo.hasName()) {
// If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
return;
@@ -2085,7 +2136,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
EqualLoc = ConsumeToken();
Init = ParseInitializer();
if (Init.isInvalid())
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
else
HasInitializer = true;
}
@@ -2123,7 +2174,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (!DeclaratorInfo.isFunctionDeclarator()) {
Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);
ConsumeBrace();
- SkipUntil(tok::r_brace, /*StopAtSemi*/false);
+ SkipUntil(tok::r_brace);
// Consume the optional ';'
if (Tok.is(tok::semi))
@@ -2143,11 +2194,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
VS, DefinitionKind, Init);
- for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
- CommonLateParsedAttrs[i]->addDecl(FunDecl);
- }
- for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
- LateParsedAttrs[i]->addDecl(FunDecl);
+ if (FunDecl) {
+ for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
+ CommonLateParsedAttrs[i]->addDecl(FunDecl);
+ }
+ for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
+ LateParsedAttrs[i]->addDecl(FunDecl);
+ }
}
LateParsedAttrs.clear();
@@ -2176,7 +2229,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
ConsumeToken();
BitfieldSize = ParseConstantExpression();
if (BitfieldSize.isInvalid())
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
}
// If a simple-asm-expr is present, parse it.
@@ -2184,7 +2237,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SourceLocation Loc;
ExprResult AsmLabel(ParseSimpleAsm(&Loc));
if (AsmLabel.isInvalid())
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
DeclaratorInfo.setAsmLabel(AsmLabel.release());
DeclaratorInfo.SetRangeEnd(Loc);
@@ -2201,7 +2254,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if ((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && !HasInitializer) {
if (BitfieldSize.get()) {
Diag(Tok, diag::err_bitfield_member_init);
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
} else {
HasInitializer = true;
if (!DeclaratorInfo.isDeclarationOfFunction() &&
@@ -2225,7 +2278,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
SmallVector<SourceRange, 4> Ranges;
DeclaratorInfo.getCXX11AttributeRanges(Ranges);
if (!Ranges.empty()) {
- for (SmallVector<SourceRange, 4>::iterator I = Ranges.begin(),
+ for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
E = Ranges.end(); I != E; ++I) {
Diag((*I).getBegin(), diag::err_attributes_not_allowed)
<< *I;
@@ -2241,28 +2294,25 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
TemplateParams,
BitfieldSize.release(),
VS, HasInClassInit);
- if (AccessAttrs)
- Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs,
- false, true);
- }
-
- // Set the Decl for any late parsed attributes
- for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
- CommonLateParsedAttrs[i]->addDecl(ThisDecl);
- }
- for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
- LateParsedAttrs[i]->addDecl(ThisDecl);
+
+ if (VarTemplateDecl *VT =
+ ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : 0)
+ // Re-direct this decl to refer to the templated decl so that we can
+ // initialize it.
+ ThisDecl = VT->getTemplatedDecl();
+
+ if (ThisDecl && AccessAttrs)
+ Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);
}
- LateParsedAttrs.clear();
// Handle the initializer.
if (HasInClassInit != ICIS_NoInit &&
DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
DeclSpec::SCS_static) {
// The initializer was deferred; parse it and cache the tokens.
- Diag(Tok, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_nonstatic_member_init :
- diag::ext_nonstatic_member_init);
+ Diag(Tok, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_nonstatic_member_init
+ : diag::ext_nonstatic_member_init);
if (DeclaratorInfo.isArrayOfUnknownBound()) {
// C++11 [dcl.array]p3: An array bound may also be omitted when the
@@ -2271,38 +2321,46 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
// A brace-or-equal-initializer for a member-declarator is not an
// initializer in the grammar, so this is ill-formed.
Diag(Tok, diag::err_incomplete_array_member_init);
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
+
+ // Avoid later warnings about a class member of incomplete type.
if (ThisDecl)
- // Avoid later warnings about a class member of incomplete type.
ThisDecl->setInvalidDecl();
} else
ParseCXXNonStaticMemberInitializer(ThisDecl);
} else if (HasInitializer) {
// Normal initializer.
if (!Init.isUsable())
- Init = ParseCXXMemberInitializer(ThisDecl,
- DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
-
+ Init = ParseCXXMemberInitializer(
+ ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
+
if (Init.isInvalid())
- SkipUntil(tok::comma, true, true);
+ SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
else if (ThisDecl)
Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid(),
DS.containsPlaceholderType());
- } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static) {
+ } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static)
// No initializer.
Actions.ActOnUninitializedDecl(ThisDecl, DS.containsPlaceholderType());
- }
-
+
if (ThisDecl) {
+ if (!ThisDecl->isInvalidDecl()) {
+ // Set the Decl for any late parsed attributes
+ for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i)
+ CommonLateParsedAttrs[i]->addDecl(ThisDecl);
+
+ for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i)
+ LateParsedAttrs[i]->addDecl(ThisDecl);
+ }
Actions.FinalizeDeclaration(ThisDecl);
DeclsInGroup.push_back(ThisDecl);
+
+ if (DeclaratorInfo.isFunctionDeclarator() &&
+ DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
+ DeclSpec::SCS_typedef)
+ HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);
}
-
- if (ThisDecl && DeclaratorInfo.isFunctionDeclarator() &&
- DeclaratorInfo.getDeclSpec().getStorageClassSpec()
- != DeclSpec::SCS_typedef) {
- HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);
- }
+ LateParsedAttrs.clear();
DeclaratorInfo.complete(ThisDecl);
@@ -2343,14 +2401,13 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
if (ExpectSemi &&
ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
// Skip to end of block or statement.
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
// If we stopped at a ';', eat it.
if (Tok.is(tok::semi)) ConsumeToken();
return;
}
- Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup.data(),
- DeclsInGroup.size());
+ Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
}
/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or
@@ -2369,7 +2426,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
/// assignment-expression
/// braced-init-list
///
-/// defaulted/deleted function-definition:
+/// defaulted/deleted function-definition:
/// '=' 'default'
/// '=' 'delete'
///
@@ -2476,20 +2533,27 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
SourceLocation FinalLoc;
+ bool IsFinalSpelledSealed = false;
// Parse the optional 'final' keyword.
if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
- assert(isCXX11FinalKeyword() && "not a class definition");
+ VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
+ assert((Specifier == VirtSpecifiers::VS_Final ||
+ Specifier == VirtSpecifiers::VS_Sealed) &&
+ "not a class definition");
FinalLoc = ConsumeToken();
+ IsFinalSpelledSealed = Specifier == VirtSpecifiers::VS_Sealed;
- if (TagType == DeclSpec::TST_interface) {
+ if (TagType == DeclSpec::TST_interface)
Diag(FinalLoc, diag::err_override_control_interface)
- << "final";
- } else {
- Diag(FinalLoc, getLangOpts().CPlusPlus11 ?
- diag::warn_cxx98_compat_override_control_keyword :
- diag::ext_override_control_keyword) << "final";
- }
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ else if (Specifier == VirtSpecifiers::VS_Final)
+ Diag(FinalLoc, getLangOpts().CPlusPlus11
+ ? diag::warn_cxx98_compat_override_control_keyword
+ : diag::ext_override_control_keyword)
+ << VirtSpecifiers::getSpecifierName(Specifier);
+ else if (Specifier == VirtSpecifiers::VS_Sealed)
+ Diag(FinalLoc, diag::ext_ms_sealed_keyword);
// Parse any C++11 attributes after 'final' keyword.
// These attributes are not allowed to appear here,
@@ -2516,6 +2580,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
if (TagDecl)
Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc,
+ IsFinalSpelledSealed,
T.getOpenLocation());
// C++ 11p3: Members of a class defined with the keyword class are private
@@ -2565,6 +2630,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
continue;
}
+ // If we see a namespace here, a close brace was missing somewhere.
+ if (Tok.is(tok::kw_namespace)) {
+ DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
+ break;
+ }
+
AccessSpecifier AS = getAccessSpecifierIfPresent();
if (AS != AS_none) {
// Current token is a C++ access specifier.
@@ -2606,15 +2677,13 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
continue;
}
- // FIXME: Make sure we don't have a template here.
-
// Parse all the comma separated declarators.
ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList());
}
T.consumeClose();
} else {
- SkipUntil(tok::r_brace, false, false);
+ SkipUntil(tok::r_brace);
}
// If attributes exist after class contents, parse them.
@@ -2658,6 +2727,27 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
ClassScope.Exit();
}
+void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {
+ assert(Tok.is(tok::kw_namespace));
+
+ // FIXME: Suggest where the close brace should have gone by looking
+ // at indentation changes within the definition body.
+ Diag(D->getLocation(),
+ diag::err_missing_end_of_definition) << D;
+ Diag(Tok.getLocation(),
+ diag::note_missing_end_of_definition_before) << D;
+
+ // Push '};' onto the token stream to recover.
+ PP.EnterToken(Tok);
+
+ Tok.startToken();
+ Tok.setLocation(PP.getLocForEndOfToken(PrevTokLocation));
+ Tok.setKind(tok::semi);
+ PP.EnterToken(Tok);
+
+ Tok.setKind(tok::r_brace);
+}
+
/// ParseConstructorInitializer - Parse a C++ constructor initializer,
/// which explicitly initializes the members or base classes of a
/// class (C++ [class.base.init]). For example, the three initializers
@@ -2691,9 +2781,8 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
do {
if (Tok.is(tok::code_completion)) {
- Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
- MemInitializers.data(),
- MemInitializers.size());
+ Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
+ MemInitializers);
return cutOffParsing();
} else {
MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
@@ -2716,7 +2805,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
} else {
// Skip over garbage, until we get to '{'. Don't eat the '{'.
Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
- SkipUntil(tok::l_brace, true, true);
+ SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
break;
}
} while (true);
@@ -2797,7 +2886,7 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
ExprVector ArgExprs;
CommaLocsTy CommaLocs;
if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
@@ -2809,9 +2898,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
TemplateTypeTy, DS, IdLoc,
- T.getOpenLocation(), ArgExprs.data(),
- ArgExprs.size(), T.getCloseLocation(),
- EllipsisLoc);
+ T.getOpenLocation(), ArgExprs,
+ T.getCloseLocation(), EllipsisLoc);
}
Diag(Tok, getLangOpts().CPlusPlus11 ? diag::err_expected_lparen_or_lbrace
@@ -2894,6 +2982,16 @@ Parser::tryParseExceptionSpecification(
return Result;
}
+static void diagnoseDynamicExceptionSpecification(
+ Parser &P, const SourceRange &Range, bool IsNoexcept) {
+ if (P.getLangOpts().CPlusPlus11) {
+ const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
+ P.Diag(Range.getBegin(), diag::warn_exception_spec_deprecated) << Range;
+ P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated)
+ << Replacement << FixItHint::CreateReplacement(Range, Replacement);
+ }
+}
+
/// ParseDynamicExceptionSpecification - Parse a C++
/// dynamic-exception-specification (C++ [except.spec]).
///
@@ -2927,6 +3025,7 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
T.consumeClose();
SpecificationRange.setEnd(T.getCloseLocation());
+ diagnoseDynamicExceptionSpecification(*this, SpecificationRange, false);
return EST_MSAny;
}
@@ -2958,6 +3057,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
T.consumeClose();
SpecificationRange.setEnd(T.getCloseLocation());
+ diagnoseDynamicExceptionSpecification(*this, SpecificationRange,
+ Exceptions.empty());
return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
}
@@ -3167,7 +3268,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
if (!AttrName) {
Diag(Tok.getLocation(), diag::err_expected_ident);
- SkipUntil(tok::r_square, tok::comma, true, true);
+ SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);
continue;
}
}
@@ -3193,7 +3294,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
// FIXME: handle other formats of c++11 attribute arguments
ConsumeParen();
- SkipUntil(tok::r_paren, false);
+ SkipUntil(tok::r_paren);
}
}
@@ -3201,8 +3302,7 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
attrs.addNew(AttrName,
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
AttrLoc),
- ScopeName, ScopeLoc, 0,
- SourceLocation(), 0, 0, AttributeList::AS_CXX11);
+ ScopeName, ScopeLoc, 0, 0, AttributeList::AS_CXX11);
if (Tok.is(tok::ellipsis)) {
ConsumeToken();
@@ -3213,11 +3313,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
}
if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
- SkipUntil(tok::r_square, false);
+ SkipUntil(tok::r_square);
if (endLoc)
*endLoc = Tok.getLocation();
if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
- SkipUntil(tok::r_square, false);
+ SkipUntil(tok::r_square);
}
/// ParseCXX11Attributes - Parse a C++11 attribute-specifier-seq.
@@ -3239,6 +3339,37 @@ void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
attrs.Range = SourceRange(StartLoc, *endLoc);
}
+void Parser::DiagnoseAndSkipCXX11Attributes() {
+ if (!isCXX11AttributeSpecifier())
+ return;
+
+ // Start and end location of an attribute or an attribute list.
+ SourceLocation StartLoc = Tok.getLocation();
+ SourceLocation EndLoc;
+
+ do {
+ if (Tok.is(tok::l_square)) {
+ BalancedDelimiterTracker T(*this, tok::l_square);
+ T.consumeOpen();
+ T.skipToEnd();
+ EndLoc = T.getCloseLocation();
+ } else {
+ assert(Tok.is(tok::kw_alignas) && "not an attribute specifier");
+ ConsumeToken();
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ if (!T.consumeOpen())
+ T.skipToEnd();
+ EndLoc = T.getCloseLocation();
+ }
+ } while (isCXX11AttributeSpecifier());
+
+ if (EndLoc.isValid()) {
+ SourceRange Range(StartLoc, EndLoc);
+ Diag(StartLoc, diag::err_attributes_not_allowed)
+ << Range;
+ }
+}
+
/// ParseMicrosoftAttributes - Parse a Microsoft attribute [Attr]
///
/// [MS] ms-attribute:
@@ -3254,7 +3385,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
while (Tok.is(tok::l_square)) {
// FIXME: If this is actually a C++11 attribute, parse it as one.
ConsumeBracket();
- SkipUntil(tok::r_square, true, true);
+ SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);
if (endLoc) *endLoc = Tok.getLocation();
ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);
}