summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
committerdim <dim@FreeBSD.org>2014-03-21 17:53:59 +0000
commit9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch)
treec978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
parent03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff)
downloadFreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip
FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports all of the features in the current working draft of the upcoming C++ standard, provisionally named C++1y. The code generator's performance is greatly increased, and the loop auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The PowerPC backend has made several major improvements to code generation quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ backends have all seen major feature work. Release notes for llvm and clang can be found here: <http://llvm.org/releases/3.4/docs/ReleaseNotes.html> <http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html> MFC 262121 (by emaste): Update lldb for clang/llvm 3.4 import This commit largely restores the lldb source to the upstream r196259 snapshot with the addition of threaded inferior support and a few bug fixes. Specific upstream lldb revisions restored include: SVN git 181387 779e6ac 181703 7bef4e2 182099 b31044e 182650 f2dcf35 182683 0d91b80 183862 15c1774 183929 99447a6 184177 0b2934b 184948 4dc3761 184954 007e7bc 186990 eebd175 Sponsored by: DARPA, AFRL MFC 262186 (by emaste): Fix mismerge in r262121 A break statement was lost in the merge. The error had no functional impact, but restore it to reduce the diff against upstream. MFC 262303: Pull in r197521 from upstream clang trunk (by rdivacky): Use the integrated assembler by default on FreeBSD/ppc and ppc64. Requested by: jhibbits MFC 262611: Pull in r196874 from upstream llvm trunk: Fix a crash that occurs when PWD is invalid. MCJIT needs to be able to run in hostile environments, even when PWD is invalid. There's no need to crash MCJIT in this case. The obvious fix is to simply leave MCContext's CompilationDir empty when PWD can't be determined. This way, MCJIT clients, and other clients that link with LLVM don't need a valid working directory. If we do want to guarantee valid CompilationDir, that should be done only for clients of getCompilationDir(). This is as simple as checking for an empty string. The only current use of getCompilationDir is EmitGenDwarfInfo, which won't conceivably run with an invalid working dir. However, in the purely hypothetically and untestable case that this happens, the AT_comp_dir will be omitted from the compilation_unit DIE. This should help fix assertions occurring with ports-mgmt/tinderbox, when it is using jails, and sometimes invalidates clang's current working directory. Reported by: decke MFC 262809: Pull in r203007 from upstream clang trunk: Don't produce an alias between destructors with different calling conventions. Fixes pr19007. (Please note that is an LLVM PR identifier, not a FreeBSD one.) This should fix Firefox and/or libxul crashes (due to problems with regparm/stdcall calling conventions) on i386. Reported by: multiple users on freebsd-current PR: bin/187103 MFC 263048: Repair recognition of "CC" as an alias for the C++ compiler, since it was silently broken by upstream for a Windows-specific use-case. Apparently some versions of CMake still rely on this archaic feature... Reported by: rakuco MFC 263049: Garbage collect the old way of adding the libstdc++ include directories in clang's InitHeaderSearch.cpp. This has been superseded by David Chisnall's commit in r255321. Moreover, if libc++ is used, the libstdc++ include directories should not be in the search path at all. These directories are now only used if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp427
1 files changed, 282 insertions, 145 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
index f1fbbb1..dd29f99 100644
--- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp
+++ b/contrib/llvm/tools/clang/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,13 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
<< DeclSpec::getSpecifierName(TagType);
}
- SkipUntil(tok::comma, true);
+ // If we are parsing a definition and stop at a base-clause, continue on
+ // until the semicolon. Continuing from the comma will just trick us into
+ // thinking we are seeing a variable declaration.
+ if (TUK == Sema::TUK_Definition && Tok.is(tok::colon))
+ SkipUntil(tok::semi, StopBeforeMatch);
+ else
+ SkipUntil(tok::comma, StopAtSemi);
return;
}
@@ -1465,7 +1486,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 +1495,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 +1566,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 +1676,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 +1835,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 +1873,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 +1902,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 +1939,7 @@ bool Parser::isCXX11FinalKeyword() const {
/// virt-specifier:
/// override
/// final
+/// [MS] sealed
///
/// pure-specifier:
/// '= 0'
@@ -1908,12 +1956,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 +2000,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 +2059,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 +2081,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 +2123,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 +2142,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 +2180,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 +2200,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 +2235,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 +2243,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 +2260,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 +2284,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 +2300,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 +2327,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 +2407,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 +2432,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
/// assignment-expression
/// braced-init-list
///
-/// defaulted/deleted function-definition:
+/// defaulted/deleted function-definition:
/// '=' 'default'
/// '=' 'delete'
///
@@ -2476,20 +2539,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 +2586,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 +2636,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 +2683,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 +2733,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 +2787,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 +2811,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 +2892,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 +2904,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 +2988,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 +3031,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 +3063,8 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
T.consumeClose();
SpecificationRange.setEnd(T.getCloseLocation());
+ diagnoseDynamicExceptionSpecification(*this, SpecificationRange,
+ Exceptions.empty());
return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
}
@@ -3167,7 +3274,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 +3300,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 +3308,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 +3319,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 +3345,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 +3391,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);
}
OpenPOWER on IntegriCloud