Author: rsmith Date: Thu Dec 15 18:58:48 2016 New Revision: 289905 URL: http://llvm.org/viewvc/llvm-project?rev=289905&view=rev Log: [c++1z] P0195R2: Allow multiple using-declarators in a single using-declaration.
Added: cfe/trunk/test/Parser/cxx1z-using-declaration.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td cfe/trunk/include/clang/Parse/Parser.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseDecl.cpp cfe/trunk/lib/Parse/ParseDeclCXX.cpp cfe/trunk/lib/Parse/ParseTemplate.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/Parser/cxx0x-decl.cpp Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Thu Dec 15 18:58:48 2016 @@ -741,6 +741,15 @@ def err_alias_declaration_not_identifier def err_alias_declaration_specialization : Error< "%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">; +// C++1z using-declaration pack expansions +def ext_multi_using_declaration : ExtWarn< + "use of multiple declarators in a single using declaration is " + "a C++1z extension">, InGroup<CXX1z>; +def warn_cxx1z_compat_multi_using_declaration : Warning< + "use of multiple declarators in a single using declaration is " + "incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; + // C++11 override control def ext_override_control_keyword : ExtWarn< "'%0' keyword is a C++11 extension">, InGroup<CXX11>; Modified: cfe/trunk/include/clang/Parse/Parser.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/include/clang/Parse/Parser.h (original) +++ cfe/trunk/include/clang/Parse/Parser.h Thu Dec 15 18:58:48 2016 @@ -1261,6 +1261,11 @@ private: ParsedAttributesWithRange(AttributeFactory &factory) : ParsedAttributes(factory) {} + void clear() { + ParsedAttributes::clear(); + Range = SourceRange(); + } + SourceRange Range; }; @@ -2418,21 +2423,41 @@ private: BalancedDelimiterTracker &Tracker); Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context); Decl *ParseExportDeclaration(); - Decl *ParseUsingDirectiveOrDeclaration(unsigned Context, - const ParsedTemplateInfo &TemplateInfo, - SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs, - Decl **OwnedType = nullptr); + DeclGroupPtrTy ParseUsingDirectiveOrDeclaration( + unsigned Context, const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs); Decl *ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, ParsedAttributes &attrs); - Decl *ParseUsingDeclaration(unsigned Context, - const ParsedTemplateInfo &TemplateInfo, - SourceLocation UsingLoc, - SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none, - Decl **OwnedType = nullptr); + + struct UsingDeclarator { + SourceLocation TypenameLoc; + CXXScopeSpec SS; + SourceLocation TemplateKWLoc; + UnqualifiedId Name; + + void clear() { + TypenameLoc = TemplateKWLoc = SourceLocation(); + SS.clear(); + Name.clear(); + } + }; + + bool ParseUsingDeclarator(unsigned Context, UsingDeclarator &D); + DeclGroupPtrTy ParseUsingDeclaration(unsigned Context, + const ParsedTemplateInfo &TemplateInfo, + SourceLocation UsingLoc, + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none); + Decl *ParseAliasTemplate(const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd, AccessSpecifier AS, + ParsedAttributesWithRange &MisplacedAttrs1); + Decl *ParseAliasDeclarationAfterDeclarator( + const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, + UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS, + ParsedAttributes &Attrs, Decl **OwnedType = nullptr); + Decl *ParseStaticAssertDeclaration(SourceLocation &DeclEnd); Decl *ParseNamespaceAlias(SourceLocation NamespaceLoc, SourceLocation AliasLoc, IdentifierInfo *Alias, Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Dec 15 18:58:48 2016 @@ -4341,12 +4341,10 @@ public: Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, - bool HasUsingKeyword, SourceLocation UsingLoc, CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool HasTypenameKeyword, SourceLocation TypenameLoc); Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, Modified: cfe/trunk/lib/Parse/ParseDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDecl.cpp (original) +++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Dec 15 18:58:48 2016 @@ -1506,7 +1506,6 @@ Parser::DeclGroupPtrTy Parser::ParseDecl ObjCDeclContextSwitch ObjCDC(*this); Decl *SingleDecl = nullptr; - Decl *OwnedType = nullptr; switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: @@ -1526,9 +1525,8 @@ Parser::DeclGroupPtrTy Parser::ParseDecl ProhibitAttributes(attrs); return ParseNamespace(Context, DeclEnd); case tok::kw_using: - SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), - DeclEnd, attrs, &OwnedType); - break; + return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), + DeclEnd, attrs); case tok::kw_static_assert: case tok::kw__Static_assert: ProhibitAttributes(attrs); @@ -1539,9 +1537,8 @@ Parser::DeclGroupPtrTy Parser::ParseDecl } // This routine returns a DeclGroup, if the thing we parsed only contains a - // single decl, convert it now. Alias declarations can also declare a type; - // include that too if it is present. - return Actions.ConvertDeclToDeclGroup(SingleDecl, OwnedType); + // single decl, convert it now. + return Actions.ConvertDeclToDeclGroup(SingleDecl); } /// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl] Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original) +++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Thu Dec 15 18:58:48 2016 @@ -421,11 +421,11 @@ Decl *Parser::ParseExportDeclaration() { /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or /// using-directive. Assumes that current token is 'using'. -Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, +Parser::DeclGroupPtrTy +Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, - SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs, - Decl **OwnedType) { + SourceLocation &DeclEnd, + ParsedAttributesWithRange &attrs) { assert(Tok.is(tok::kw_using) && "Not using token"); ObjCDeclContextSwitch ObjCDC(*this); @@ -447,7 +447,8 @@ Decl *Parser::ParseUsingDirectiveOrDecla << 0 /* directive */ << R << FixItHint::CreateRemoval(R); } - return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs); + Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs); + return Actions.ConvertDeclToDeclGroup(UsingDir); } // Otherwise, it must be a using-declaration or an alias-declaration. @@ -456,7 +457,7 @@ Decl *Parser::ParseUsingDirectiveOrDecla ProhibitAttributes(attrs); return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, - AS_none, OwnedType); + AS_none); } /// ParseUsingDirective - Parse C++ using-directive, assumes @@ -522,58 +523,31 @@ Decl *Parser::ParseUsingDirective(unsign IdentLoc, NamespcName, attrs.getList()); } -/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration. -/// Assumes that 'using' was already seen. +/// Parse a using-declarator (or the identifier in a C++11 alias-declaration). /// -/// using-declaration: [C++ 7.3.p3: namespace.udecl] -/// 'using' 'typename'[opt] ::[opt] nested-name-specifier -/// unqualified-id -/// 'using' :: unqualified-id +/// using-declarator: +/// 'typename'[opt] nested-name-specifier unqualified-id /// -/// alias-declaration: C++11 [dcl.dcl]p1 -/// 'using' identifier attribute-specifier-seq[opt] = type-id ; -/// -Decl *Parser::ParseUsingDeclaration(unsigned Context, - const ParsedTemplateInfo &TemplateInfo, - SourceLocation UsingLoc, - SourceLocation &DeclEnd, - AccessSpecifier AS, - Decl **OwnedType) { - CXXScopeSpec SS; - SourceLocation TypenameLoc; - bool HasTypenameKeyword = false; - - // Check for misplaced attributes before the identifier in an - // alias-declaration. - ParsedAttributesWithRange MisplacedAttrs(AttrFactory); - MaybeParseCXX11Attributes(MisplacedAttrs); +bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { + D.clear(); // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. - if (TryConsumeToken(tok::kw_typename, TypenameLoc)) - HasTypenameKeyword = true; + TryConsumeToken(tok::kw_typename, D.TypenameLoc); if (Tok.is(tok::kw___super)) { Diag(Tok.getLocation(), diag::err_super_in_using_declaration); - SkipUntil(tok::semi); - return nullptr; + return true; } // Parse nested-name-specifier. IdentifierInfo *LastII = nullptr; - ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false, + ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false, /*MayBePseudoDtor=*/nullptr, /*IsTypename=*/false, /*LastII=*/&LastII); - - // Check nested-name specifier. - if (SS.isInvalid()) { - SkipUntil(tok::semi); - return nullptr; - } - - SourceLocation TemplateKWLoc; - UnqualifiedId Name; + if (D.SS.isInvalid()) + return true; // Parse the unqualified-id. We allow parsing of both constructor and // destructor names and allow the action module to diagnose any semantic @@ -587,31 +561,68 @@ Decl *Parser::ParseUsingDeclaration(unsi // constructor. if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext && Tok.is(tok::identifier) && NextToken().is(tok::semi) && - SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && - !SS.getScopeRep()->getAsNamespace() && - !SS.getScopeRep()->getAsNamespaceAlias()) { + D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && + !D.SS.getScopeRep()->getAsNamespace() && + !D.SS.getScopeRep()->getAsNamespaceAlias()) { SourceLocation IdLoc = ConsumeToken(); - ParsedType Type = Actions.getInheritingConstructorName(SS, IdLoc, *LastII); - Name.setConstructorName(Type, IdLoc, IdLoc); - } else if (ParseUnqualifiedId( - SS, /*EnteringContext=*/false, - /*AllowDestructorName=*/true, - /*AllowConstructorName=*/!(Tok.is(tok::identifier) && - NextToken().is(tok::equal)), - nullptr, TemplateKWLoc, Name)) { - SkipUntil(tok::semi); - return nullptr; + ParsedType Type = + Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII); + D.Name.setConstructorName(Type, IdLoc, IdLoc); + } else { + if (ParseUnqualifiedId( + D.SS, /*EnteringContext=*/false, + /*AllowDestructorName=*/true, + /*AllowConstructorName=*/!(Tok.is(tok::identifier) && + NextToken().is(tok::equal)), + nullptr, D.TemplateKWLoc, D.Name)) + return true; } + // FIXME: Parse optional ellipsis + + return false; +} + +/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration. +/// Assumes that 'using' was already seen. +/// +/// using-declaration: [C++ 7.3.p3: namespace.udecl] +/// 'using' using-declarator-list[opt] ; +/// +/// using-declarator-list: [C++1z] +/// using-declarator '...'[opt] +/// using-declarator-list ',' using-declarator '...'[opt] +/// +/// using-declarator-list: [C++98-14] +/// using-declarator +/// +/// alias-declaration: C++11 [dcl.dcl]p1 +/// 'using' identifier attribute-specifier-seq[opt] = type-id ; +/// +Parser::DeclGroupPtrTy +Parser::ParseUsingDeclaration(unsigned Context, + const ParsedTemplateInfo &TemplateInfo, + SourceLocation UsingLoc, SourceLocation &DeclEnd, + AccessSpecifier AS) { + // Check for misplaced attributes before the identifier in an + // alias-declaration. + ParsedAttributesWithRange MisplacedAttrs(AttrFactory); + MaybeParseCXX11Attributes(MisplacedAttrs); + + UsingDeclarator D; + bool InvalidDeclarator = ParseUsingDeclarator(Context, D); + ParsedAttributesWithRange Attrs(AttrFactory); MaybeParseGNUAttributes(Attrs); MaybeParseCXX11Attributes(Attrs); // Maybe this is an alias-declaration. - TypeResult TypeAlias; - bool IsAliasDecl = Tok.is(tok::equal); - Decl *DeclFromDeclSpec = nullptr; - if (IsAliasDecl) { + if (Tok.is(tok::equal)) { + if (InvalidDeclarator) { + SkipUntil(tok::semi); + return nullptr; + } + // If we had any misplaced attributes from earlier, this is where they // should have been written. if (MisplacedAttrs.Range.isValid()) { @@ -623,109 +634,209 @@ Decl *Parser::ParseUsingDeclaration(unsi Attrs.takeAllFrom(MisplacedAttrs); } - ConsumeToken(); + Decl *DeclFromDeclSpec = nullptr; + Decl *AD = ParseAliasDeclarationAfterDeclarator( + TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec); + return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec); + } - Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_alias_declaration : - diag::ext_alias_declaration); - - // Type alias templates cannot be specialized. - int SpecKind = -1; - if (TemplateInfo.Kind == ParsedTemplateInfo::Template && - Name.getKind() == UnqualifiedId::IK_TemplateId) - SpecKind = 0; - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) - SpecKind = 1; - if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) - SpecKind = 2; - if (SpecKind != -1) { - SourceRange Range; - if (SpecKind == 0) - Range = SourceRange(Name.TemplateId->LAngleLoc, - Name.TemplateId->RAngleLoc); - else - Range = TemplateInfo.getSourceRange(); - Diag(Range.getBegin(), diag::err_alias_declaration_specialization) - << SpecKind << Range; - SkipUntil(tok::semi); - return nullptr; - } + // C++11 attributes are not allowed on a using-declaration, but GNU ones + // are. + ProhibitAttributes(MisplacedAttrs); + ProhibitAttributes(Attrs); - // Name must be an identifier. - if (Name.getKind() != UnqualifiedId::IK_Identifier) { - Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier); - // No removal fixit: can't recover from this. - SkipUntil(tok::semi); - return nullptr; - } else if (HasTypenameKeyword) - Diag(TypenameLoc, diag::err_alias_declaration_not_identifier) - << FixItHint::CreateRemoval(SourceRange(TypenameLoc, - SS.isNotEmpty() ? SS.getEndLoc() : TypenameLoc)); - else if (SS.isNotEmpty()) - Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) - << FixItHint::CreateRemoval(SS.getRange()); + // Diagnose an attempt to declare a templated using-declaration. + // In C++11, alias-declarations can be templates: + // template <...> using id = type; + if (TemplateInfo.Kind) { + SourceRange R = TemplateInfo.getSourceRange(); + Diag(UsingLoc, diag::err_templated_using_directive_declaration) + << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); - TypeAlias = ParseTypeName(nullptr, TemplateInfo.Kind - ? Declarator::AliasTemplateContext - : Declarator::AliasDeclContext, - AS, &DeclFromDeclSpec, &Attrs); - if (OwnedType) - *OwnedType = DeclFromDeclSpec; - } else { - // C++11 attributes are not allowed on a using-declaration, but GNU ones - // are. - ProhibitAttributes(MisplacedAttrs); - ProhibitAttributes(Attrs); + // Unfortunately, we have to bail out instead of recovering by + // ignoring the parameters, just in case the nested name specifier + // depends on the parameters. + return nullptr; + } + SmallVector<Decl *, 8> DeclsInGroup; + while (true) { // Parse (optional) attributes (most likely GNU strong-using extension). MaybeParseGNUAttributes(Attrs); + + if (InvalidDeclarator) + SkipUntil(tok::comma, tok::semi, StopBeforeMatch); + else { + // "typename" keyword is allowed for identifiers only, + // because it may be a type definition. + if (D.TypenameLoc.isValid() && + D.Name.getKind() != UnqualifiedId::IK_Identifier) { + Diag(D.Name.getSourceRange().getBegin(), + diag::err_typename_identifiers_only) + << FixItHint::CreateRemoval(SourceRange(D.TypenameLoc)); + // Proceed parsing, but discard the typename keyword. + D.TypenameLoc = SourceLocation(); + } + + Decl *UD = + Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, D.SS, + D.Name, Attrs.getList(), D.TypenameLoc); + if (UD) + DeclsInGroup.push_back(UD); + } + + if (!TryConsumeToken(tok::comma)) + break; + + // Parse another using-declarator. + Attrs.clear(); + InvalidDeclarator = ParseUsingDeclarator(Context, D); } + if (DeclsInGroup.size() > 1) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ? + diag::warn_cxx1z_compat_multi_using_declaration : + diag::ext_multi_using_declaration); + // Eat ';'. DeclEnd = Tok.getLocation(); if (ExpectAndConsume(tok::semi, diag::err_expected_after, !Attrs.empty() ? "attributes list" - : IsAliasDecl ? "alias declaration" - : "using declaration")) + : "using declaration")) SkipUntil(tok::semi); - // Diagnose an attempt to declare a templated using-declaration. - // In C++11, alias-declarations can be templates: - // template <...> using id = type; - if (TemplateInfo.Kind && !IsAliasDecl) { + return Actions.BuildDeclaratorGroup(DeclsInGroup, /*MayContainAuto*/false); +} + +Decl *Parser::ParseAliasTemplate(const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd, AccessSpecifier AS, + ParsedAttributesWithRange &MisplacedAttrs1) { + assert(Tok.is(tok::kw_using) && "Not using token"); + ObjCDeclContextSwitch ObjCDC(*this); + + // Eat 'using'. + SourceLocation UsingLoc = ConsumeToken(); + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteUsing(getCurScope()); + cutOffParsing(); + return nullptr; + } + + // 'using namespace' means this is a using-directive. + if (Tok.is(tok::kw_namespace)) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_directive_declaration) - << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); + << 0 /* directive */ << R; + SkipUntil(tok::semi); + return nullptr; + } - // Unfortunately, we have to bail out instead of recovering by - // ignoring the parameters, just in case the nested name specifier - // depends on the parameters. + // Check for misplaced attributes before the identifier. + ParsedAttributesWithRange MisplacedAttrs2(AttrFactory); + MaybeParseCXX11Attributes(MisplacedAttrs2); + + // FIXME: Just parse an identifier here? + UsingDeclarator D; + if (ParseUsingDeclarator(Declarator::FileContext, D)) { + SkipUntil(tok::semi); + return nullptr; + } + + ParsedAttributesWithRange Attrs(AttrFactory); + + // If we had any misplaced attributes from earlier, this is where they + // should have been written. + for (auto *MisplacedAttrs : {&MisplacedAttrs1, &MisplacedAttrs2}) { + 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); + } + } + + MaybeParseGNUAttributes(Attrs); + MaybeParseCXX11Attributes(Attrs); + + return ParseAliasDeclarationAfterDeclarator(TemplateInfo, UsingLoc, D, + DeclEnd, AS, Attrs); +} + +Decl *Parser::ParseAliasDeclarationAfterDeclarator( + const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, + UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS, + ParsedAttributes &Attrs, Decl **OwnedType) { + if (ExpectAndConsume(tok::equal)) { + SkipUntil(tok::semi); return nullptr; } - // "typename" keyword is allowed for identifiers only, - // because it may be a type definition. - 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 HasTypenameKeyword flag. - HasTypenameKeyword = false; - } - - if (IsAliasDecl) { - TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; - MultiTemplateParamsArg TemplateParamsArg( - TemplateParams ? TemplateParams->data() : nullptr, - TemplateParams ? TemplateParams->size() : 0); - return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, - UsingLoc, Name, Attrs.getList(), - TypeAlias, DeclFromDeclSpec); - } - - return Actions.ActOnUsingDeclaration(getCurScope(), AS, - /* HasUsingKeyword */ true, UsingLoc, - SS, Name, Attrs.getList(), - HasTypenameKeyword, TypenameLoc); + Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ? + diag::warn_cxx98_compat_alias_declaration : + diag::ext_alias_declaration); + + // Type alias templates cannot be specialized. + int SpecKind = -1; + if (TemplateInfo.Kind == ParsedTemplateInfo::Template && + D.Name.getKind() == UnqualifiedId::IK_TemplateId) + SpecKind = 0; + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) + SpecKind = 1; + if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) + SpecKind = 2; + if (SpecKind != -1) { + SourceRange Range; + if (SpecKind == 0) + Range = SourceRange(D.Name.TemplateId->LAngleLoc, + D.Name.TemplateId->RAngleLoc); + else + Range = TemplateInfo.getSourceRange(); + Diag(Range.getBegin(), diag::err_alias_declaration_specialization) + << SpecKind << Range; + SkipUntil(tok::semi); + return nullptr; + } + + // Name must be an identifier. + if (D.Name.getKind() != UnqualifiedId::IK_Identifier) { + Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier); + // No removal fixit: can't recover from this. + SkipUntil(tok::semi); + return nullptr; + } else if (D.TypenameLoc.isValid()) + Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier) + << FixItHint::CreateRemoval(SourceRange( + D.TypenameLoc, + D.SS.isNotEmpty() ? D.SS.getEndLoc() : D.TypenameLoc)); + else if (D.SS.isNotEmpty()) + Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) + << FixItHint::CreateRemoval(D.SS.getRange()); + + Decl *DeclFromDeclSpec = nullptr; + TypeResult TypeAlias = + ParseTypeName(nullptr, + TemplateInfo.Kind ? Declarator::AliasTemplateContext + : Declarator::AliasDeclContext, + AS, &DeclFromDeclSpec, &Attrs); + if (OwnedType) + *OwnedType = DeclFromDeclSpec; + + // Eat ';'. + DeclEnd = Tok.getLocation(); + if (ExpectAndConsume(tok::semi, diag::err_expected_after, + !Attrs.empty() ? "attributes list" + : "alias declaration")) + SkipUntil(tok::semi); + + TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; + MultiTemplateParamsArg TemplateParamsArg( + TemplateParams ? TemplateParams->data() : nullptr, + TemplateParams ? TemplateParams->size() : 0); + return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, + UsingLoc, D.Name, Attrs.getList(), + TypeAlias, DeclFromDeclSpec); } /// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration. @@ -2376,10 +2487,8 @@ Parser::ParseCXXClassMemberDeclaration(A } return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( - getCurScope(), AS, - /* HasUsingKeyword */ false, SourceLocation(), SS, Name, - /* AttrList */ nullptr, - /* HasTypenameKeyword */ false, SourceLocation()))); + getCurScope(), AS, /*UsingLoc*/SourceLocation(), SS, Name, + /*AttrList*/nullptr, /*TypenameLoc*/SourceLocation()))); } } @@ -2434,8 +2543,8 @@ Parser::ParseCXXClassMemberDeclaration(A } SourceLocation DeclEnd; // Otherwise, it must be a using-declaration or an alias-declaration. - return DeclGroupPtrTy::make(DeclGroupRef(ParseUsingDeclaration( - Declarator::MemberContext, TemplateInfo, UsingLoc, DeclEnd, AS))); + return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo, + UsingLoc, DeclEnd, AS); } // Hold late-parsed attributes so we can attach a Decl to them later. Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseTemplate.cpp (original) +++ cfe/trunk/lib/Parse/ParseTemplate.cpp Thu Dec 15 18:58:48 2016 @@ -196,9 +196,12 @@ Parser::ParseSingleDeclarationAfterTempl ParsedAttributesWithRange prefixAttrs(AttrFactory); MaybeParseCXX11Attributes(prefixAttrs); - if (Tok.is(tok::kw_using)) - return ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd, - prefixAttrs); + if (Tok.is(tok::kw_using)) { + // FIXME: We should return the DeclGroup to the caller. + ParseUsingDirectiveOrDeclaration(Context, TemplateInfo, DeclEnd, + prefixAttrs); + return nullptr; + } // Parse the declaration specifiers, stealing any diagnostics from // the template parameters. Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Dec 15 18:58:48 2016 @@ -8532,12 +8532,10 @@ void Sema::PushUsingDirective(Scope *S, Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, - bool HasUsingKeyword, SourceLocation UsingLoc, CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool HasTypenameKeyword, SourceLocation TypenameLoc) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); @@ -8579,7 +8577,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope return nullptr; // Warn about access declarations. - if (!HasUsingKeyword) { + if (UsingLoc.isInvalid()) { Diag(Name.getLocStart(), getLangOpts().CPlusPlus11 ? diag::err_access_decl : diag::warn_access_decl_deprecated) @@ -8593,7 +8591,7 @@ Decl *Sema::ActOnUsingDeclaration(Scope NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, TargetNameInfo, AttrList, /* IsInstantiation */ false, - HasTypenameKeyword, TypenameLoc); + TypenameLoc.isValid(), TypenameLoc); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); Modified: cfe/trunk/test/Parser/cxx0x-decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-decl.cpp?rev=289905&r1=289904&r2=289905&view=diff ============================================================================== --- cfe/trunk/test/Parser/cxx0x-decl.cpp (original) +++ cfe/trunk/test/Parser/cxx0x-decl.cpp Thu Dec 15 18:58:48 2016 @@ -136,5 +136,5 @@ template<int ...N> void NoMissingSemicol ... [N]); // This must be at the end of the file; we used to look ahead past the EOF token here. -// expected-error@+1 {{expected unqualified-id}} +// expected-error@+1 {{expected unqualified-id}} expected-error@+1{{expected ';'}} using Added: cfe/trunk/test/Parser/cxx1z-using-declaration.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx1z-using-declaration.cpp?rev=289905&view=auto ============================================================================== --- cfe/trunk/test/Parser/cxx1z-using-declaration.cpp (added) +++ cfe/trunk/test/Parser/cxx1z-using-declaration.cpp Thu Dec 15 18:58:48 2016 @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -std=c++1z -verify %s + +namespace A { + int m, n; +}; + +namespace B { + using A::m, A::n, A::n; + int q = m + n; +} + +struct X { + int x1, x2, y, z; // expected-note {{conflicting}} +}; +struct Y { + int x1, x2, y, z; // expected-note {{target}} +}; +struct Z : X, Y { + using X::x1, + blah::blah, // expected-error {{undeclared}} + X::x2, // expected-note {{previous}} + Y::y, + X::x2, // expected-error {{redeclaration}} + X::z, + Y::z; // expected-error {{conflicts with}} +}; +int X::*px1 = &Z::x1; +int X::*px2 = &Z::x2; +int Y::*py = &Z::y; +int X::*pz = &Z::z; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits