diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 74 |
1 files changed, 52 insertions, 22 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ac643af1490..21bdd945f06 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8533,12 +8533,18 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, - AttributeList *AttrList, - SourceLocation TypenameLoc) { + SourceLocation EllipsisLoc, + AttributeList *AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + if (SS.isEmpty()) { + Diag(Name.getLocStart(), diag::err_using_requires_qualname); + return nullptr; + } + switch (Name.getKind()) { case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_Identifier: @@ -8584,14 +8590,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); } - if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || - DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) - return nullptr; + if (EllipsisLoc.isInvalid()) { + if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || + DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) + return nullptr; + } else { + if (!SS.getScopeRep()->containsUnexpandedParameterPack() && + !TargetNameInfo.containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc()); + EllipsisLoc = SourceLocation(); + } + } - NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, - TargetNameInfo, AttrList, - /* IsInstantiation */ false, - TypenameLoc.isValid(), TypenameLoc); + NamedDecl *UD = + BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc, + SS, TargetNameInfo, EllipsisLoc, AttrList, + /*IsInstantiation*/false); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); @@ -8654,6 +8669,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, diag::err_using_decl_nested_name_specifier_is_current_class) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); + Using->setInvalidDecl(); return true; } @@ -8663,6 +8679,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, << cast<CXXRecordDecl>(CurContext) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); + Using->setInvalidDecl(); return true; } } @@ -8686,7 +8703,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // We can have UsingDecls in our Previous results because we use the same // LookupResult for checking whether the UsingDecl itself is a valid // redeclaration. - if (isa<UsingDecl>(D)) + if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D)) continue; if (IsEquivalentForUsingDecl(Context, D, Target)) { @@ -8732,6 +8749,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Target->getLocation(), diag::note_using_decl_target); Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8744,6 +8762,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(Tag->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8753,6 +8772,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(NonTag->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8960,23 +8980,19 @@ private: /// the lookup differently for these declarations. NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, + SourceLocation TypenameLoc, CXXScopeSpec &SS, DeclarationNameInfo NameInfo, + SourceLocation EllipsisLoc, AttributeList *AttrList, - bool IsInstantiation, - bool HasTypenameKeyword, - SourceLocation TypenameLoc) { + bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); // FIXME: We ignore attributes for now. - if (SS.isEmpty()) { - Diag(IdentLoc, diag::err_using_requires_qualname); - return nullptr; - } - // For an inheriting constructor declaration, the name of the using // declaration is the name of a constructor in this class, not in the // base class. @@ -9042,16 +9058,17 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, DeclContext *LookupContext = computeDeclContext(SS); NamedDecl *D; NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!LookupContext) { + if (!LookupContext || EllipsisLoc.isValid()) { if (HasTypenameKeyword) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, QualifierLoc, - IdentLoc, NameInfo.getName()); + IdentLoc, NameInfo.getName(), + EllipsisLoc); } else { D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, - QualifierLoc, NameInfo); + QualifierLoc, NameInfo, EllipsisLoc); } D->setAccess(AS); CurContext->addDecl(D); @@ -9211,6 +9228,19 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } +NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, + ArrayRef<NamedDecl *> Expansions) { + assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) || + isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) || + isa<UsingPackDecl>(InstantiatedFrom)); + + auto *UPD = + UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions); + UPD->setAccess(InstantiatedFrom->getAccess()); + CurContext->addDecl(UPD); + return UPD; +} + /// Additional checks for a using declaration referring to a constructor name. bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { assert(!UD->hasTypename() && "expecting a constructor name"); @@ -9264,7 +9294,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // scope? if (Qual->isDependent() && !HasTypenameKeyword) { for (auto *D : Prev) { - if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D)) { + if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) { bool OldCouldBeEnumerator = isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D); Diag(NameLoc, |