diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-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.cpp | 427 |
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); } |