r289905 - [c++1z] P0195R2: Allow multiple using-declarators in a single using-declaration.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 15 16:58:49 PST 2016
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 at +1 {{expected unqualified-id}}
+// expected-error at +1 {{expected unqualified-id}} expected-error at +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;
More information about the cfe-commits
mailing list