diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Sema/SemaTemplate.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) | |
download | src-486754660bb926339aefcf012a3f848592babb8b.tar.gz src-486754660bb926339aefcf012a3f848592babb8b.zip |
Vendor import of clang trunk r338150:vendor/clang/clang-trunk-r338150
Notes
Notes:
svn path=/vendor/clang/dist/; revision=336815
svn path=/vendor/clang/clang-trunk-r338150/; revision=336816; tag=vendor/clang/clang-trunk-r338150
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 772 |
1 files changed, 412 insertions, 360 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d94cb0d0f485..dd1163267119 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -46,7 +46,7 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, } namespace clang { -/// \brief [temp.constr.decl]p2: A template's associated constraints are +/// [temp.constr.decl]p2: A template's associated constraints are /// defined as a single constraint-expression derived from the introduced /// constraint-expressions [ ... ]. /// @@ -65,7 +65,7 @@ static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params, return Params->getRequiresClause(); } -/// \brief Determine whether the declaration found is acceptable as the name +/// Determine whether the declaration found is acceptable as the name /// of a template and, if so, return that template declaration. Otherwise, /// returns NULL. static NamedDecl *isAcceptableTemplateName(ASTContext &Context, @@ -105,6 +105,12 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, return nullptr; } + // 'using Dependent::foo;' can resolve to a template name. + // 'using typename Dependent::foo;' cannot (not even if 'foo' is an + // injected-class-name). + if (isa<UnresolvedUsingValueDecl>(D)) + return D; + return nullptr; } @@ -158,7 +164,7 @@ bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R, TemplateNameKind Sema::isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword, - UnqualifiedId &Name, + const UnqualifiedId &Name, ParsedType ObjectTypePtr, bool EnteringContext, TemplateTy &TemplateResult, @@ -169,16 +175,16 @@ TemplateNameKind Sema::isTemplateName(Scope *S, MemberOfUnknownSpecialization = false; switch (Name.getKind()) { - case UnqualifiedId::IK_Identifier: + case UnqualifiedIdKind::IK_Identifier: TName = DeclarationName(Name.Identifier); break; - case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_OperatorFunctionId: TName = Context.DeclarationNames.getCXXOperatorName( Name.OperatorFunctionId.Operator); break; - case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_LiteralOperatorId: TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier); break; @@ -189,8 +195,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S, QualType ObjectType = ObjectTypePtr.get(); LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName); - LookupTemplateName(R, S, SS, ObjectType, EnteringContext, - MemberOfUnknownSpecialization); + if (LookupTemplateName(R, S, SS, ObjectType, EnteringContext, + MemberOfUnknownSpecialization)) + return TNK_Non_template; if (R.empty()) return TNK_Non_template; if (R.isAmbiguous()) { // Suppress diagnostics; we'll redo this lookup later. @@ -213,6 +220,10 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // We'll do this lookup again later. R.suppressDiagnostics(); + } else if (isa<UnresolvedUsingValueDecl>((*R.begin())->getUnderlyingDecl())) { + // We don't yet know whether this is a template-name or not. + MemberOfUnknownSpecialization = true; + return TNK_Non_template; } else { TemplateDecl *TD = cast<TemplateDecl>((*R.begin())->getUnderlyingDecl()); @@ -252,8 +263,10 @@ bool Sema::isDeductionGuideName(Scope *S, const IdentifierInfo &Name, // syntactic form of a deduction guide is enough to identify it even // if we can't look up the template name at all. LookupResult R(*this, DeclarationName(&Name), NameLoc, LookupOrdinaryName); - LookupTemplateName(R, S, SS, /*ObjectType*/QualType(), - /*EnteringContext*/false, MemberOfUnknownSpecialization); + if (LookupTemplateName(R, S, SS, /*ObjectType*/ QualType(), + /*EnteringContext*/ false, + MemberOfUnknownSpecialization)) + return false; if (R.empty()) return false; if (R.isAmbiguous()) { @@ -298,39 +311,40 @@ bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, return true; } -void Sema::LookupTemplateName(LookupResult &Found, +bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS, QualType ObjectType, bool EnteringContext, - bool &MemberOfUnknownSpecialization) { + bool &MemberOfUnknownSpecialization, + SourceLocation TemplateKWLoc) { // Determine where to perform name lookup MemberOfUnknownSpecialization = false; DeclContext *LookupCtx = nullptr; - bool isDependent = false; + bool IsDependent = false; if (!ObjectType.isNull()) { // This nested-name-specifier occurs in a member access expression, e.g., // x->B::f, and we are looking into the type of the object. assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); LookupCtx = computeDeclContext(ObjectType); - isDependent = ObjectType->isDependentType(); - assert((isDependent || !ObjectType->isIncompleteType() || + IsDependent = !LookupCtx; + assert((IsDependent || !ObjectType->isIncompleteType() || ObjectType->castAs<TagType>()->isBeingDefined()) && "Caller should have completed object type"); // Template names cannot appear inside an Objective-C class or object type. if (ObjectType->isObjCObjectOrInterfaceType()) { Found.clear(); - return; + return false; } } else if (SS.isSet()) { // This nested-name-specifier occurs after another nested-name-specifier, // so long into the context associated with the prior nested-name-specifier. LookupCtx = computeDeclContext(SS, EnteringContext); - isDependent = isDependentScopeSpecifier(SS); + IsDependent = !LookupCtx; // The declaration context must be complete. if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx)) - return; + return true; } bool ObjectTypeSearchedInScope = false; @@ -341,34 +355,43 @@ void Sema::LookupTemplateName(LookupResult &Found, // expression or the declaration context associated with a prior // nested-name-specifier. LookupQualifiedName(Found, LookupCtx); - if (!ObjectType.isNull() && Found.empty()) { - // C++ [basic.lookup.classref]p1: - // In a class member access expression (5.2.5), if the . or -> token is - // immediately followed by an identifier followed by a <, the - // identifier must be looked up to determine whether the < is the - // beginning of a template argument list (14.2) or a less-than operator. - // The identifier is first looked up in the class of the object - // expression. If the identifier is not found, it is then looked up in - // the context of the entire postfix-expression and shall name a class - // or function template. - if (S) LookupName(Found, S); - ObjectTypeSearchedInScope = true; + + // FIXME: The C++ standard does not clearly specify what happens in the + // case where the object type is dependent, and implementations vary. In + // Clang, we treat a name after a . or -> as a template-name if lookup + // finds a non-dependent member or member of the current instantiation that + // is a type template, or finds no such members and lookup in the context + // of the postfix-expression finds a type template. In the latter case, the + // name is nonetheless dependent, and we may resolve it to a member of an + // unknown specialization when we come to instantiate the template. + IsDependent |= Found.wasNotFoundInCurrentInstantiation(); + } + + if (!SS.isSet() && (ObjectType.isNull() || Found.empty())) { + // C++ [basic.lookup.classref]p1: + // In a class member access expression (5.2.5), if the . or -> token is + // immediately followed by an identifier followed by a <, the + // identifier must be looked up to determine whether the < is the + // beginning of a template argument list (14.2) or a less-than operator. + // The identifier is first looked up in the class of the object + // expression. If the identifier is not found, it is then looked up in + // the context of the entire postfix-expression and shall name a class + // template. + if (S) + LookupName(Found, S); + + if (!ObjectType.isNull()) { + // FIXME: We should filter out all non-type templates here, particularly + // variable templates and concepts. But the exclusion of alias templates + // and template template parameters is a wording defect. AllowFunctionTemplatesInLookup = false; + ObjectTypeSearchedInScope = true; } - } else if (isDependent && (!S || ObjectType.isNull())) { - // We cannot look into a dependent object type or nested nme - // specifier. - MemberOfUnknownSpecialization = true; - return; - } else { - // Perform unqualified name lookup in the current scope. - LookupName(Found, S); - if (!ObjectType.isNull()) - AllowFunctionTemplatesInLookup = false; + IsDependent |= Found.wasNotFoundInCurrentInstantiation(); } - if (Found.empty() && !isDependent) { + if (Found.empty() && !IsDependent) { // If we did not find any names, attempt to correct any typos. DeclarationName Name = Found.getLookupName(); Found.clear(); @@ -402,11 +425,27 @@ void Sema::LookupTemplateName(LookupResult &Found, } } + NamedDecl *ExampleLookupResult = + Found.empty() ? nullptr : Found.getRepresentativeDecl(); FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup); if (Found.empty()) { - if (isDependent) + if (IsDependent) { MemberOfUnknownSpecialization = true; - return; + return false; + } + + // If a 'template' keyword was used, a lookup that finds only non-template + // names is an error. + if (ExampleLookupResult && TemplateKWLoc.isValid()) { + Diag(Found.getNameLoc(), diag::err_template_kw_refers_to_non_template) + << Found.getLookupName() << SS.getRange(); + Diag(ExampleLookupResult->getUnderlyingDecl()->getLocation(), + diag::note_template_kw_refers_to_non_template) + << Found.getLookupName(); + return true; + } + + return false; } if (S && !ObjectType.isNull() && !ObjectTypeSearchedInScope && @@ -453,6 +492,8 @@ void Sema::LookupTemplateName(LookupResult &Found, } } } + + return false; } void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, @@ -467,20 +508,41 @@ void Sema::diagnoseExprIntendedAsTemplateName(Scope *S, ExprResult TemplateName, DeclContext *LookupCtx = nullptr; NamedDecl *Found = nullptr; + bool MissingTemplateKeyword = false; // Figure out what name we looked up. - if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { + if (auto *DRE = dyn_cast<DeclRefExpr>(TemplateName.get())) { + NameInfo = DRE->getNameInfo(); + SS.Adopt(DRE->getQualifierLoc()); + LookupKind = LookupOrdinaryName; + Found = DRE->getFoundDecl(); + } else if (auto *ME = dyn_cast<MemberExpr>(TemplateName.get())) { NameInfo = ME->getMemberNameInfo(); SS.Adopt(ME->getQualifierLoc()); LookupKind = LookupMemberName; LookupCtx = ME->getBase()->getType()->getAsCXXRecordDecl(); Found = ME->getMemberDecl(); + } else if (auto *DSDRE = + dyn_cast<DependentScopeDeclRefExpr>(TemplateName.get())) { + NameInfo = DSDRE->getNameInfo(); + SS.Adopt(DSDRE->getQualifierLoc()); + MissingTemplateKeyword = true; + } else if (auto *DSME = + dyn_cast<CXXDependentScopeMemberExpr>(TemplateName.get())) { + NameInfo = DSME->getMemberNameInfo(); + SS.Adopt(DSME->getQualifierLoc()); + MissingTemplateKeyword = true; } else { - auto *DRE = cast<DeclRefExpr>(TemplateName.get()); - NameInfo = DRE->getNameInfo(); - SS.Adopt(DRE->getQualifierLoc()); - LookupKind = LookupOrdinaryName; - Found = DRE->getFoundDecl(); + llvm_unreachable("unexpected kind of potential template name"); + } + + // If this is a dependent-scope lookup, diagnose that the 'template' keyword + // was missing. + if (MissingTemplateKeyword) { + Diag(NameInfo.getLocStart(), diag::err_template_kw_missing) + << "" << NameInfo.getName().getAsString() + << SourceRange(Less, Greater); + return; } // Try to correct the name by looking for templates and C++ named casts. @@ -765,7 +827,7 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, llvm_unreachable("Unhandled parsed template argument"); } -/// \brief Translates template arguments as provided by the parser +/// Translates template arguments as provided by the parser /// into template arguments used by semantic analysis. void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, TemplateArgumentListInfo &TemplateArgs) { @@ -783,6 +845,56 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S, SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl); } +/// Convert a parsed type into a parsed template argument. This is mostly +/// trivial, except that we may have parsed a C++17 deduced class template +/// specialization type, in which case we should form a template template +/// argument instead of a type template argument. +ParsedTemplateArgument Sema::ActOnTemplateTypeArgument(TypeResult ParsedType) { + TypeSourceInfo *TInfo; + QualType T = GetTypeFromParser(ParsedType.get(), &TInfo); + if (T.isNull()) + return ParsedTemplateArgument(); + assert(TInfo && "template argument with no location"); + + // If we might have formed a deduced template specialization type, convert + // it to a template template argument. + if (getLangOpts().CPlusPlus17) { + TypeLoc TL = TInfo->getTypeLoc(); + SourceLocation EllipsisLoc; + if (auto PET = TL.getAs<PackExpansionTypeLoc>()) { + EllipsisLoc = PET.getEllipsisLoc(); + TL = PET.getPatternLoc(); + } + + CXXScopeSpec SS; + if (auto ET = TL.getAs<ElaboratedTypeLoc>()) { + SS.Adopt(ET.getQualifierLoc()); + TL = ET.getNamedTypeLoc(); + } + + if (auto DTST = TL.getAs<DeducedTemplateSpecializationTypeLoc>()) { + TemplateName Name = DTST.getTypePtr()->getTemplateName(); + if (SS.isSet()) + Name = Context.getQualifiedTemplateName(SS.getScopeRep(), + /*HasTemplateKeyword*/ false, + Name.getAsTemplateDecl()); + ParsedTemplateArgument Result(SS, TemplateTy::make(Name), + DTST.getTemplateNameLoc()); + if (EllipsisLoc.isValid()) + Result = Result.getTemplatePackExpansion(EllipsisLoc); + return Result; + } + } + + // This is a normal type template argument. Note, if the type template + // argument is an injected-class-name for a template, it has a dual nature + // and can be used as either a type or a template. We handle that in + // convertTypeTemplateArgumentToTemplate. + return ParsedTemplateArgument(ParsedTemplateArgument::Type, + ParsedType.get().getAsOpaquePtr(), + TInfo->getTypeLoc().getLocStart()); +} + /// ActOnTypeParameter - Called when a C++ template type parameter /// (e.g., "typename T") has been parsed. Typename specifies whether /// the keyword "typename" was used to declare the type parameter @@ -854,7 +966,7 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename, return Param; } -/// \brief Check that the type of a non-type template parameter is +/// Check that the type of a non-type template parameter is /// well-formed. /// /// \returns the (possibly-promoted) parameter type if valid; @@ -933,9 +1045,9 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, auto CheckValidDeclSpecifiers = [this, &D] { // C++ [temp.param] // p1 - // template-parameter:
- // ...
- // parameter-declaration
+ // template-parameter: + // ... + // parameter-declaration // p2 // ... A storage class shall not be specified in a template-parameter // declaration. @@ -1151,17 +1263,13 @@ static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); } -DeclResult -Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList** OuterTemplateParamLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -1212,7 +1320,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams)) Invalid = true; } else if (TUK != TUK_Friend && TUK != TUK_Reference) - diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc); + diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false); LookupQualifiedName(Previous, SemanticContext); } else { @@ -1501,8 +1609,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (TUK == TUK_Definition) NewClass->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); if (PrevClassTemplate) mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); @@ -1885,6 +1992,8 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, // FIXME: Add a kind for this to give more meaningful diagnostics. But can // this substitution process actually fail? InstantiatingTemplate BuildingDeductionGuides(*this, Loc, Template); + if (BuildingDeductionGuides.isInvalid()) + return; // Convert declared constructors into deduction guide templates. // FIXME: Skip constructors for which deduction must necessarily fail (those @@ -1925,7 +2034,7 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template, ->setIsCopyDeductionCandidate(); } -/// \brief Diagnose the presence of a default template argument on a +/// Diagnose the presence of a default template argument on a /// template parameter, which is ill-formed in certain contexts. /// /// \returns true if the default template argument should be dropped. @@ -1981,7 +2090,7 @@ static bool DiagnoseDefaultTemplateArgument(Sema &S, llvm_unreachable("Invalid TemplateParamListContext!"); } -/// \brief Check for unexpanded parameter packs within the template parameters +/// Check for unexpanded parameter packs within the template parameters /// of a template template parameter, recursively. static bool DiagnoseUnexpandedParameterPacks(Sema &S, TemplateTemplateParmDecl *TTP) { @@ -2012,7 +2121,7 @@ static bool DiagnoseUnexpandedParameterPacks(Sema &S, return false; } -/// \brief Checks the validity of a template parameter list, possibly +/// Checks the validity of a template parameter list, possibly /// considering the template parameter list from a previous /// declaration. /// @@ -2379,7 +2488,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context, return SourceRange(); } -/// \brief Match the given template parameter lists to the given scope +/// Match the given template parameter lists to the given scope /// specifier, returning the template parameter list that applies to the /// name. /// @@ -3476,7 +3585,7 @@ noteNonDeducibleParameters(Sema &S, TemplateParameterList *TemplateParams, const llvm::SmallBitVector &DeducibleParams) { for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) { if (!DeducibleParams[I]) { - NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I)); + NamedDecl *Param = TemplateParams->getParam(I); if (Param->getDeclName()) S.Diag(Param->getLocation(), diag::note_non_deducible_parameter) << Param->getDeclName(); @@ -3557,7 +3666,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( TemplateParameterList *TemplateParams, StorageClass SC, bool IsPartialSpecialization) { // D must be variable template id. - assert(D.getName().getKind() == UnqualifiedId::IK_TemplateId && + assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId && "Variable template specialization is declared with a template it."); TemplateIdAnnotation *TemplateId = D.getName().TemplateId; @@ -3754,7 +3863,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization( } namespace { -/// \brief A partial specialization whose template arguments have matched +/// A partial specialization whose template arguments have matched /// a given template-id. struct PartialSpecMatchResult { VarTemplatePartialSpecializationDecl *Partial; @@ -3938,6 +4047,16 @@ Sema::CheckVarTemplateId(const CXXScopeSpec &SS, /*FoundD=*/nullptr, TemplateArgs); } +void Sema::diagnoseMissingTemplateArguments(TemplateName Name, + SourceLocation Loc) { + Diag(Loc, diag::err_template_missing_args) + << (int)getTemplateNameKindForDiagnostics(Name) << Name; + if (TemplateDecl *TD = Name.getAsTemplateDecl()) { + Diag(TD->getLocation(), diag::note_template_decl_here) + << TD->getTemplateParameters()->getSourceRange(); + } +} + ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, @@ -3957,11 +4076,23 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, assert(!R.empty() && "empty lookup results when building templateid"); assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); + // Non-function templates require a template argument list. + if (auto *TD = R.getAsSingle<TemplateDecl>()) { + if (!TemplateArgs && !isa<FunctionTemplateDecl>(TD)) { + diagnoseMissingTemplateArguments(TemplateName(TD), R.getNameLoc()); + return ExprError(); + } + } + + auto AnyDependentArguments = [&]() -> bool { + bool InstantiationDependent; + return TemplateArgs && + TemplateSpecializationType::anyDependentTemplateArguments( + *TemplateArgs, InstantiationDependent); + }; + // In C++1y, check variable template ids. - bool InstantiationDependent; - if (R.getAsSingle<VarTemplateDecl>() && - !TemplateSpecializationType::anyDependentTemplateArguments( - *TemplateArgs, InstantiationDependent)) { + if (R.getAsSingle<VarTemplateDecl>() && !AnyDependentArguments()) { return CheckVarTemplateId(SS, R.getLookupNameInfo(), R.getAsSingle<VarTemplateDecl>(), TemplateKWLoc, TemplateArgs); @@ -3997,15 +4128,17 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, bool MemberOfUnknownSpecialization; LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupTemplateName(R, (Scope*)nullptr, SS, QualType(), /*Entering*/ false, - MemberOfUnknownSpecialization); + if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(), + /*Entering*/false, MemberOfUnknownSpecialization, + TemplateKWLoc)) + return ExprError(); if (R.isAmbiguous()) return ExprError(); if (R.empty()) { - Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_non_template) - << NameInfo.getName() << SS.getRange(); + Diag(NameInfo.getLoc(), diag::err_no_member) + << NameInfo.getName() << DC << SS.getRange(); return ExprError(); } @@ -4020,7 +4153,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); } -/// \brief Form a dependent template name. +/// Form a dependent template name. /// /// This action forms a dependent template name given the template /// name and its (presumably dependent) scope specifier. For @@ -4030,7 +4163,7 @@ Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - UnqualifiedId &Name, + const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, TemplateTy &Result, @@ -4068,24 +4201,27 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, TemplateNameKind TNK = isTemplateName(S, SS, TemplateKWLoc.isValid(), Name, ObjectType, EnteringContext, Result, MemberOfUnknownSpecialization); - if (TNK == TNK_Non_template && LookupCtx->isDependentContext() && - isa<CXXRecordDecl>(LookupCtx) && - (!cast<CXXRecordDecl>(LookupCtx)->hasDefinition() || - cast<CXXRecordDecl>(LookupCtx)->hasAnyDependentBases())) { + if (TNK == TNK_Non_template && MemberOfUnknownSpecialization) { // This is a dependent template. Handle it below. } else if (TNK == TNK_Non_template) { - Diag(Name.getLocStart(), - diag::err_template_kw_refers_to_non_template) - << GetNameFromUnqualifiedId(Name).getName() - << Name.getSourceRange() - << TemplateKWLoc; + // Do the lookup again to determine if this is a "nothing found" case or + // a "not a template" case. FIXME: Refactor isTemplateName so we don't + // need to do this. + DeclarationNameInfo DNI = GetNameFromUnqualifiedId(Name); + LookupResult R(*this, DNI.getName(), Name.getLocStart(), + LookupOrdinaryName); + bool MOUS; + if (!LookupTemplateName(R, S, SS, ObjectType.get(), EnteringContext, + MOUS, TemplateKWLoc)) + Diag(Name.getLocStart(), diag::err_no_member) + << DNI.getName() << LookupCtx << SS.getRange(); return TNK_Non_template; } else { // We found something; return it. auto *LookupRD = dyn_cast<CXXRecordDecl>(LookupCtx); if (!AllowInjectedClassName && SS.isSet() && LookupRD && - Name.getKind() == UnqualifiedId::IK_Identifier && Name.Identifier && - LookupRD->getIdentifier() == Name.Identifier) { + Name.getKind() == UnqualifiedIdKind::IK_Identifier && + Name.Identifier && LookupRD->getIdentifier() == Name.Identifier) { // C++14 [class.qual]p2: // In a lookup in which function names are not ignored and the // nested-name-specifier nominates a class C, if the name specified @@ -4107,17 +4243,17 @@ TemplateNameKind Sema::ActOnDependentTemplateName(Scope *S, NestedNameSpecifier *Qualifier = SS.getScopeRep(); switch (Name.getKind()) { - case UnqualifiedId::IK_Identifier: + case UnqualifiedIdKind::IK_Identifier: Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, Name.Identifier)); return TNK_Dependent_template_name; - case UnqualifiedId::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_OperatorFunctionId: Result = TemplateTy::make(Context.getDependentTemplateName(Qualifier, Name.OperatorFunctionId.Operator)); return TNK_Function_template; - case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_LiteralOperatorId: llvm_unreachable("literal operator id cannot have a dependent scope"); default: @@ -4148,16 +4284,13 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, ArgType = Arg.getAsType(); TSI = AL.getTypeSourceInfo(); break; - case TemplateArgument::Template: { + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: { // We have a template type parameter but the template argument // is a template without any arguments. SourceRange SR = AL.getSourceRange(); - TemplateName Name = Arg.getAsTemplate(); - Diag(SR.getBegin(), diag::err_template_missing_args) - << (int)getTemplateNameKindForDiagnostics(Name) << Name << SR; - if (TemplateDecl *Decl = Name.getAsTemplateDecl()) - Diag(Decl->getLocation(), diag::note_template_decl_here); - + TemplateName Name = Arg.getAsTemplateOrTemplatePattern(); + diagnoseMissingTemplateArguments(Name, SR.getEnd()); return true; } case TemplateArgument::Expression: { @@ -4250,7 +4383,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, return false; } -/// \brief Substitute template arguments into the default template argument for +/// Substitute template arguments into the default template argument for /// the given template type parameter. /// /// \param SemaRef the semantic analysis object for which we are performing @@ -4306,7 +4439,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, return ArgType; } -/// \brief Substitute template arguments into the default template argument for +/// Substitute template arguments into the default template argument for /// the given non-type template parameter. /// /// \param SemaRef the semantic analysis object for which we are performing @@ -4354,7 +4487,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); } -/// \brief Substitute template arguments into the default template argument for +/// Substitute template arguments into the default template argument for /// the given template template parameter. /// /// \param SemaRef the semantic analysis object for which we are performing @@ -4418,7 +4551,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, TemplateArgLists); } -/// \brief If the given template parameter has a default template +/// If the given template parameter has a default template /// argument, substitute into that default template argument and /// return the corresponding template argument. TemplateArgumentLoc @@ -4519,7 +4652,7 @@ static TemplateArgumentLoc convertTypeTemplateArgumentToTemplate(TypeLoc TLoc) { return TemplateArgumentLoc(); } -/// \brief Check that the given template argument corresponds to the given +/// Check that the given template argument corresponds to the given /// template parameter. /// /// \param Param The template parameter against which the argument will be @@ -4566,6 +4699,8 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, if (NTTP->isParameterPack() && NTTP->isExpandedParameterPack()) NTTPType = NTTP->getExpansionType(ArgumentPackIndex); + // FIXME: Do we need to substitute into parameters here if they're + // instantiation-dependent but not dependent? if (NTTPType->isDependentType() && !isa<TemplateTemplateParmDecl>(Template) && !Template->getDeclContext()->isDependentContext()) { @@ -4597,11 +4732,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Expression: { TemplateArgument Result; + unsigned CurSFINAEErrors = NumSFINAEErrors; ExprResult Res = CheckTemplateArgument(NTTP, NTTPType, Arg.getArgument().getAsExpr(), Result, CTAK); if (Res.isInvalid()) return true; + // If the current template argument causes an error, give up now. + if (CurSFINAEErrors < NumSFINAEErrors) + return true; // If the resulting expression is new, then use it in place of the // old expression in the template argument. @@ -4705,9 +4844,15 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // Check template template parameters. TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(Param); + TemplateParameterList *Params = TempParm->getTemplateParameters(); + if (TempParm->isExpandedParameterPack()) + Params = TempParm->getExpansionTemplateParameters(ArgumentPackIndex); + // Substitute into the template parameter list of the template // template parameter, since previously-supplied template arguments // may appear within the template template parameter. + // + // FIXME: Skip this if the parameters aren't instantiation-dependent. { // Set up a template instantiation context. LocalInstantiationScope Scope(*this); @@ -4718,10 +4863,9 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, return true; TemplateArgumentList TemplateArgs(TemplateArgumentList::OnStack, Converted); - TempParm = cast_or_null<TemplateTemplateParmDecl>( - SubstDecl(TempParm, CurContext, - MultiLevelTemplateArgumentList(TemplateArgs))); - if (!TempParm) + Params = SubstTemplateParams(Params, CurContext, + MultiLevelTemplateArgumentList(TemplateArgs)); + if (!Params) return true; } @@ -4742,7 +4886,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (CheckTemplateArgument(TempParm, Arg, ArgumentPackIndex)) + if (CheckTemplateTemplateArgument(Params, Arg)) return true; Converted.push_back(Arg.getArgument()); @@ -4770,28 +4914,7 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, return false; } -/// \brief Diagnose an arity mismatch in the -static bool diagnoseArityMismatch(Sema &S, TemplateDecl *Template, - SourceLocation TemplateLoc, - TemplateArgumentListInfo &TemplateArgs) { - TemplateParameterList *Params = Template->getTemplateParameters(); - unsigned NumParams = Params->size(); - unsigned NumArgs = TemplateArgs.size(); - - SourceRange Range; - if (NumArgs > NumParams) - Range = SourceRange(TemplateArgs[NumParams].getLocation(), - TemplateArgs.getRAngleLoc()); - S.Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << (NumArgs > NumParams) - << (int)S.getTemplateNameKindForDiagnostics(TemplateName(Template)) - << Template << Range; - S.Diag(Template->getLocation(), diag::note_template_decl_here) - << Params->getSourceRange(); - return true; -} - -/// \brief Check whether the template parameter is a pack expansion, and if so, +/// Check whether the template parameter is a pack expansion, and if so, /// determine the number of parameters produced by that expansion. For instance: /// /// \code @@ -4844,10 +4967,18 @@ static bool diagnoseMissingArgument(Sema &S, SourceLocation Loc, // FIXME: If there's a more recent default argument that *is* visible, // diagnose that it was declared too late. - return diagnoseArityMismatch(S, TD, Loc, Args); + TemplateParameterList *Params = TD->getTemplateParameters(); + + S.Diag(Loc, diag::err_template_arg_list_different_arity) + << /*not enough args*/0 + << (int)S.getTemplateNameKindForDiagnostics(TemplateName(TD)) + << TD; + S.Diag(TD->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; } -/// \brief Check that the given template argument list is well-formed +/// Check that the given template argument list is well-formed /// for specializing the given template. bool Sema::CheckTemplateArgumentList( TemplateDecl *Template, SourceLocation TemplateLoc, @@ -4896,7 +5027,7 @@ bool Sema::CheckTemplateArgumentList( } else if (ArgIdx == NumArgs && !PartialTemplateArgs) { // Not enough arguments for this parameter pack. Diag(TemplateLoc, diag::err_template_arg_list_different_arity) - << false + << /*not enough args*/0 << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) << Template; Diag(Template->getLocation(), diag::note_template_decl_here) @@ -5091,8 +5222,16 @@ bool Sema::CheckTemplateArgumentList( // If we have any leftover arguments, then there were too many arguments. // Complain and fail. - if (ArgIdx < NumArgs) - return diagnoseArityMismatch(*this, Template, TemplateLoc, NewArgs); + if (ArgIdx < NumArgs) { + Diag(TemplateLoc, diag::err_template_arg_list_different_arity) + << /*too many args*/1 + << (int)getTemplateNameKindForDiagnostics(TemplateName(Template)) + << Template + << SourceRange(NewArgs[ArgIdx].getLocation(), NewArgs.getRAngleLoc()); + Diag(Template->getLocation(), diag::note_template_decl_here) + << Params->getSourceRange(); + return true; + } // No problems found with the new argument list, propagate changes back // to caller. @@ -5197,6 +5336,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) { return Visit(T->getElementType()); } +bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType( + const DependentVectorType *T) { + return Visit(T->getElementType()); +} + bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) { return Visit(T->getElementType()); } @@ -5354,7 +5498,7 @@ bool UnnamedLocalNoLinkageFinder::VisitNestedNameSpecifier( llvm_unreachable("Invalid NestedNameSpecifier::Kind!"); } -/// \brief Check a template argument against its corresponding +/// Check a template argument against its corresponding /// template type parameter. /// /// This routine implements the semantics of C++ [temp.arg.type]. It @@ -5392,7 +5536,7 @@ enum NullPointerValueKind { NPV_Error }; -/// \brief Determine whether the given template argument is a null pointer +/// Determine whether the given template argument is a null pointer /// value of the appropriate type. static NullPointerValueKind isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, @@ -5488,7 +5632,7 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, return NPV_NotNullPointer; } -/// \brief Checks whether the given template argument is compatible with its +/// Checks whether the given template argument is compatible with its /// template parameter. static bool CheckTemplateArgumentIsCompatibleWithParameter( Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *ArgIn, @@ -5545,7 +5689,7 @@ static bool CheckTemplateArgumentIsCompatibleWithParameter( return false; } -/// \brief Checks whether the given template argument is the address +/// Checks whether the given template argument is the address /// of an object or function according to C++ [temp.arg.nontype]p1. static bool CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, @@ -5833,7 +5977,7 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S, return false; } -/// \brief Checks whether the given template argument is a pointer to +/// Checks whether the given template argument is a pointer to /// member constant according to C++ [temp.arg.nontype]p1. static bool CheckTemplateArgumentPointerToMember(Sema &S, NonTypeTemplateParmDecl *Param, @@ -5883,17 +6027,16 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, } // A constant of pointer-to-member type. else if ((DRE = dyn_cast<DeclRefExpr>(Arg))) { - if (ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl())) { - if (VD->getType()->isMemberPointerType()) { - if (isa<NonTypeTemplateParmDecl>(VD)) { - if (Arg->isTypeDependent() || Arg->isValueDependent()) { - Converted = TemplateArgument(Arg); - } else { - VD = cast<ValueDecl>(VD->getCanonicalDecl()); - Converted = TemplateArgument(VD, ParamType); - } - return Invalid; + ValueDecl *VD = DRE->getDecl(); + if (VD->getType()->isMemberPointerType()) { + if (isa<NonTypeTemplateParmDecl>(VD)) { + if (Arg->isTypeDependent() || Arg->isValueDependent()) { + Converted = TemplateArgument(Arg); + } else { + VD = cast<ValueDecl>(VD->getCanonicalDecl()); + Converted = TemplateArgument(VD, ParamType); } + return Invalid; } } @@ -5963,7 +6106,7 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, return true; } -/// \brief Check a template argument against its corresponding +/// Check a template argument against its corresponding /// non-type template parameter. /// /// This routine implements the semantics of C++ [temp.arg.nontype]. @@ -6118,7 +6261,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // -- a predefined __func__ variable if (auto *E = Value.getLValueBase().dyn_cast<const Expr*>()) { if (isa<CXXUuidofExpr>(E)) { - Converted = TemplateArgument(const_cast<Expr*>(E)); + Converted = TemplateArgument(ArgResult.get()); break; } Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref) @@ -6481,14 +6624,13 @@ static void DiagnoseTemplateParameterListArityMismatch( Sema &S, TemplateParameterList *New, TemplateParameterList *Old, Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc); -/// \brief Check a template argument against its corresponding +/// Check a template argument against its corresponding /// template template parameter. /// /// This routine implements the semantics of C++ [temp.arg.template]. /// It returns true if an error occurred, and false otherwise. -bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, - TemplateArgumentLoc &Arg, - unsigned ArgumentPackIndex) { +bool Sema::CheckTemplateTemplateArgument(TemplateParameterList *Params, + TemplateArgumentLoc &Arg) { TemplateName Name = Arg.getArgument().getAsTemplateOrTemplatePattern(); TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template) { @@ -6523,10 +6665,6 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, << Template; } - TemplateParameterList *Params = Param->getTemplateParameters(); - if (Param->isExpandedParameterPack()) - Params = Param->getExpansionTemplateParameters(ArgumentPackIndex); - // C++1z [temp.arg.template]p3: (DR 150) // A template-argument matches a template template-parameter P when P // is at least as specialized as the template-argument A. @@ -6553,7 +6691,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, Arg.getLocation()); } -/// \brief Given a non-type template argument that refers to a +/// Given a non-type template argument that refers to a /// declaration and the type of its corresponding non-type template /// parameter, produce an expression that properly refers to that /// declaration. @@ -6584,7 +6722,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, assert(Arg.getKind() == TemplateArgument::Declaration && "Only declaration template arguments permitted here"); - ValueDecl *VD = cast<ValueDecl>(Arg.getAsDecl()); + ValueDecl *VD = Arg.getAsDecl(); if (VD->getDeclContext()->isRecord() && (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD) || @@ -6676,7 +6814,7 @@ Sema::BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, return BuildDeclRefExpr(VD, T, VK, Loc); } -/// \brief Construct a new expression that refers to the given +/// Construct a new expression that refers to the given /// integral template argument with the given source-location /// information. /// @@ -6701,11 +6839,11 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, Expr *E; if (T->isAnyCharacterType()) { - // This does not need to handle u8 character literals because those are - // of type char, and so can also be covered by an ASCII character literal. CharacterLiteral::CharacterKind Kind; if (T->isWideCharType()) Kind = CharacterLiteral::Wide; + else if (T->isChar8Type() && getLangOpts().Char8) + Kind = CharacterLiteral::UTF8; else if (T->isChar16Type()) Kind = CharacterLiteral::UTF16; else if (T->isChar32Type()) @@ -6736,7 +6874,7 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, return E; } -/// \brief Match two template parameters within template parameter lists. +/// Match two template parameters within template parameter lists. static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, bool Complain, Sema::TemplateParameterListEqualKind Kind, @@ -6839,7 +6977,7 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, return true; } -/// \brief Diagnose a known arity mismatch when comparing template argument +/// Diagnose a known arity mismatch when comparing template argument /// lists. static void DiagnoseTemplateParameterListArityMismatch(Sema &S, @@ -6861,7 +6999,7 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S, << SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc()); } -/// \brief Determine whether the given template parameter lists are +/// Determine whether the given template parameter lists are /// equivalent. /// /// \param New The new template parameter list, typically written in the @@ -6953,7 +7091,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, return true; } -/// \brief Check whether a template can be declared within this scope. +/// Check whether a template can be declared within this scope. /// /// If the template declaration is valid in this scope, returns /// false. Otherwise, issues a diagnostic and returns true. @@ -7002,7 +7140,7 @@ Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { << TemplateParams->getSourceRange(); } -/// \brief Determine what kind of template specialization the given declaration +/// Determine what kind of template specialization the given declaration /// is. static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) { if (!D) @@ -7018,7 +7156,7 @@ static TemplateSpecializationKind getTemplateSpecializationKind(Decl *D) { return TSK_Undeclared; } -/// \brief Check whether a specialization is well-formed in the current +/// Check whether a specialization is well-formed in the current /// context. /// /// This routine determines whether a template specialization can be declared @@ -7072,120 +7210,43 @@ static bool CheckTemplateSpecializationScope(Sema &S, } // C++ [temp.expl.spec]p2: - // An explicit specialization shall be declared in the namespace - // of which the template is a member, or, for member templates, in - // the namespace of which the enclosing class or enclosing class - // template is a member. An explicit specialization of a member - // function, member class or static data member of a class - // template shall be declared in the namespace of which the class - // template is a member. Such a declaration may also be a - // definition. If the declaration is not a definition, the - // specialization may be defined later in the name- space in which - // the explicit specialization was declared, or in a namespace - // that encloses the one in which the explicit specialization was - // declared. + // An explicit specialization may be declared in any scope in which + // the corresponding primary template may be defined. if (S.CurContext->getRedeclContext()->isFunctionOrMethod()) { S.Diag(Loc, diag::err_template_spec_decl_function_scope) << Specialized; return true; } - if (S.CurContext->isRecord() && !IsPartialSpecialization) { - if (S.getLangOpts().MicrosoftExt) { - // Do not warn for class scope explicit specialization during - // instantiation, warning was already emitted during pattern - // semantic analysis. - if (!S.inTemplateInstantiation()) - S.Diag(Loc, diag::ext_function_specialization_in_class) - << Specialized; - } else { - S.Diag(Loc, diag::err_template_spec_decl_class_scope) - << Specialized; - return true; - } - } - - if (S.CurContext->isRecord() && - !S.CurContext->Equals(Specialized->getDeclContext())) { - // Make sure that we're specializing in the right record context. - // Otherwise, things can go horribly wrong. - S.Diag(Loc, diag::err_template_spec_decl_class_scope) - << Specialized; - return true; - } - // C++ [temp.class.spec]p6: - // A class template partial specialization may be declared or redeclared - // in any namespace scope in which its definition may be defined (14.5.1 - // and 14.5.2). - DeclContext *SpecializedContext - = Specialized->getDeclContext()->getEnclosingNamespaceContext(); - DeclContext *DC = S.CurContext->getEnclosingNamespaceContext(); - - // Make sure that this redeclaration (or definition) occurs in an enclosing - // namespace. - // Note that HandleDeclarator() performs this check for explicit - // specializations of function templates, static data members, and member - // functions, so we skip the check here for those kinds of entities. - // FIXME: HandleDeclarator's diagnostics aren't quite as good, though. - // Should we refactor that check, so that it occurs later? - if (!DC->Encloses(SpecializedContext) && - !(isa<FunctionTemplateDecl>(Specialized) || - isa<FunctionDecl>(Specialized) || - isa<VarTemplateDecl>(Specialized) || - isa<VarDecl>(Specialized))) { + // A class template partial specialization may be declared in any + // scope in which the primary template may be defined. + DeclContext *SpecializedContext = + Specialized->getDeclContext()->getRedeclContext(); + DeclContext *DC = S.CurContext->getRedeclContext(); + + // Make sure that this redeclaration (or definition) occurs in the same + // scope or an enclosing namespace. + if (!(DC->isFileContext() ? DC->Encloses(SpecializedContext) + : DC->Equals(SpecializedContext))) { if (isa<TranslationUnitDecl>(SpecializedContext)) S.Diag(Loc, diag::err_template_spec_redecl_global_scope) << EntityKind << Specialized; - else if (isa<NamespaceDecl>(SpecializedContext)) { + else { + auto *ND = cast<NamedDecl>(SpecializedContext); int Diag = diag::err_template_spec_redecl_out_of_scope; - if (S.getLangOpts().MicrosoftExt) + if (S.getLangOpts().MicrosoftExt && !DC->isRecord()) Diag = diag::ext_ms_template_spec_redecl_out_of_scope; S.Diag(Loc, Diag) << EntityKind << Specialized - << cast<NamedDecl>(SpecializedContext); - } else - llvm_unreachable("unexpected namespace context for specialization"); + << ND << isa<CXXRecordDecl>(ND); + } S.Diag(Specialized->getLocation(), diag::note_specialized_entity); - } else if ((!PrevDecl || - getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared || - getTemplateSpecializationKind(PrevDecl) == - TSK_ImplicitInstantiation)) { - // C++ [temp.exp.spec]p2: - // An explicit specialization shall be declared in the namespace of which - // the template is a member, or, for member templates, in the namespace - // of which the enclosing class or enclosing class template is a member. - // An explicit specialization of a member function, member class or - // static data member of a class template shall be declared in the - // namespace of which the class template is a member. - // - // C++11 [temp.expl.spec]p2: - // An explicit specialization shall be declared in a namespace enclosing - // the specialized template. - // C++11 [temp.explicit]p3: - // An explicit instantiation shall appear in an enclosing namespace of its - // template. - if (!DC->InEnclosingNamespaceSetOf(SpecializedContext)) { - bool IsCPlusPlus11Extension = DC->Encloses(SpecializedContext); - if (isa<TranslationUnitDecl>(SpecializedContext)) { - assert(!IsCPlusPlus11Extension && - "DC encloses TU but isn't in enclosing namespace set"); - S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global) - << EntityKind << Specialized; - } else if (isa<NamespaceDecl>(SpecializedContext)) { - int Diag; - if (!IsCPlusPlus11Extension) - Diag = diag::err_template_spec_decl_out_of_scope; - else if (!S.getLangOpts().CPlusPlus11) - Diag = diag::ext_template_spec_decl_out_of_scope; - else - Diag = diag::warn_cxx98_compat_template_spec_decl_out_of_scope; - S.Diag(Loc, Diag) - << EntityKind << Specialized << cast<NamedDecl>(SpecializedContext); - } - S.Diag(Specialized->getLocation(), diag::note_specialized_entity); - } + // Don't allow specializing in the wrong class during error recovery. + // Otherwise, things can go horribly wrong. + if (DC->isRecord()) + return true; } return false; @@ -7211,7 +7272,7 @@ static SourceRange findTemplateParameter(unsigned Depth, TypeLoc TL) { return Checker.MatchLoc; } -/// \brief Subroutine of Sema::CheckTemplatePartialSpecializationArgs +/// Subroutine of Sema::CheckTemplatePartialSpecializationArgs /// that checks non-type template partial specialization arguments. static bool CheckNonTypeTemplatePartialSpecializationArgs( Sema &S, SourceLocation TemplateNameLoc, NonTypeTemplateParmDecl *Param, @@ -7299,7 +7360,7 @@ static bool CheckNonTypeTemplatePartialSpecializationArgs( return false; } -/// \brief Check the non-type template arguments of a class template +/// Check the non-type template arguments of a class template /// partial specialization according to C++ [temp.class.spec]p9. /// /// \param TemplateNameLoc the location of the template name. @@ -7335,16 +7396,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs( return false; } -DeclResult -Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, - TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg - TemplateParameterLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { assert(TUK != TUK_Reference && "References are not specializations"); CXXScopeSpec &SS = TemplateId.SS; @@ -7586,10 +7642,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplate->AddSpecialization(Specialization, InsertPos); if (CurContext->isDependentContext()) { - // -fms-extensions permits specialization of nested classes without - // fully specializing the outer class(es). - assert(getLangOpts().MicrosoftExt && - "Only possible with -fms-extensions!"); TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); CanonType = Context.getTemplateSpecializationType( CanonTemplate, Converted); @@ -7649,8 +7701,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -7717,7 +7768,7 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, return NewDecl; } -/// \brief Strips various properties off an implicit instantiation +/// Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { D->dropAttr<DLLImportAttr>(); @@ -7727,7 +7778,7 @@ static void StripImplicitInstantiation(NamedDecl *D) { FD->setInlineSpecified(false); } -/// \brief Compute the diagnostic location for an explicit instantiation +/// Compute the diagnostic location for an explicit instantiation // declaration or definition. static SourceLocation DiagLocForExplicitInstantiation( NamedDecl* D, SourceLocation PointOfInstantiation) { @@ -7744,7 +7795,7 @@ static SourceLocation DiagLocForExplicitInstantiation( return PrevDiagLoc; } -/// \brief Diagnose cases where we have an explicit template specialization +/// Diagnose cases where we have an explicit template specialization /// before/after an explicit template instantiation, producing diagnostics /// for those cases where they are required and determining whether the /// new specialization/instantiation will have any effect. @@ -7890,7 +7941,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, return false; case TSK_ExplicitInstantiationDeclaration: - // We're explicity instantiating a definition for something for which we + // We're explicitly instantiating a definition for something for which we // were previously asked to suppress instantiations. That's fine. // C++0x [temp.explicit]p4: @@ -7929,7 +7980,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, llvm_unreachable("Missing specialization/instantiation case?"); } -/// \brief Perform semantic analysis for the given dependent function +/// Perform semantic analysis for the given dependent function /// template specialization. /// /// The only possible way to get a dependent function template specialization @@ -7952,24 +8003,41 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, // the correct context. DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); LookupResult::Filter F = Previous.makeFilter(); + enum DiscardReason { NotAFunctionTemplate, NotAMemberOfEnclosing }; + SmallVector<std::pair<DiscardReason, Decl *>, 8> DiscardedCandidates; while (F.hasNext()) { NamedDecl *D = F.next()->getUnderlyingDecl(); - if (!isa<FunctionTemplateDecl>(D) || - !FDLookupContext->InEnclosingNamespaceSetOf( - D->getDeclContext()->getRedeclContext())) + if (!isa<FunctionTemplateDecl>(D)) { + F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAFunctionTemplate, D)); + continue; + } + + if (!FDLookupContext->InEnclosingNamespaceSetOf( + D->getDeclContext()->getRedeclContext())) { F.erase(); + DiscardedCandidates.push_back(std::make_pair(NotAMemberOfEnclosing, D)); + continue; + } } F.done(); - // Should this be diagnosed here? - if (Previous.empty()) return true; + if (Previous.empty()) { + Diag(FD->getLocation(), + diag::err_dependent_function_template_spec_no_match); + for (auto &P : DiscardedCandidates) + Diag(P.second->getLocation(), + diag::note_dependent_function_template_spec_discard_reason) + << P.first; + return true; + } FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(), ExplicitTemplateArgs); return false; } -/// \brief Perform semantic analysis for the given function template +/// Perform semantic analysis for the given function template /// specialization. /// /// This routine performs all of the semantic analysis required for an @@ -8192,7 +8260,7 @@ bool Sema::CheckFunctionTemplateSpecialization( return false; } -/// \brief Perform semantic analysis for the given non-template member +/// Perform semantic analysis for the given non-template member /// specialization. /// /// This routine performs all of the semantic analysis required for an @@ -8402,7 +8470,7 @@ void Sema::CompleteMemberSpecialization(NamedDecl *Member, llvm_unreachable("unknown member specialization kind"); } -/// \brief Check the scope of an explicit instantiation. +/// Check the scope of an explicit instantiation. /// /// \returns true if a serious error occurs, false otherwise. static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, @@ -8456,7 +8524,7 @@ static bool CheckExplicitInstantiationScope(Sema &S, NamedDecl *D, return false; } -/// \brief Determine whether the given scope specifier has a template-id in it. +/// Determine whether the given scope specifier has a template-id in it. static bool ScopeSpecifierHasTemplateId(const CXXScopeSpec &SS) { if (!SS.isSet()) return false; @@ -8502,19 +8570,12 @@ static void dllExportImportClassTemplateSpecialization( } // Explicit instantiation of a class template specialization -DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc, - AttributeList *Attr) { +DeclResult Sema::ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr) { // Find the class template we're specializing TemplateName Name = TemplateD.get(); TemplateDecl *TD = Name.getAsTemplateDecl(); @@ -8555,11 +8616,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, if (TSK == TSK_ExplicitInstantiationDeclaration) { // Check for dllexport class template instantiation declarations. - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLExport) { + for (const ParsedAttr &AL : Attr) { + if (AL.getKind() == ParsedAttr::AT_DLLExport) { Diag(ExternLoc, diag::warn_attribute_dllexport_explicit_instantiation_decl); - Diag(A->getLoc(), diag::note_attribute); + Diag(AL.getLoc(), diag::note_attribute); break; } } @@ -8579,10 +8640,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Check for dllimport class template instantiation definitions. bool DLLImport = ClassTemplate->getTemplatedDecl()->getAttr<DLLImportAttr>(); - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLImport) + for (const ParsedAttr &AL : Attr) { + if (AL.getKind() == ParsedAttr::AT_DLLImport) DLLImport = true; - if (A->getKind() == AttributeList::AT_DLLExport) { + if (AL.getKind() == ParsedAttr::AT_DLLExport) { // dllexport trumps dllimport here. DLLImport = false; break; @@ -8692,8 +8753,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setBraceRange(SourceRange()); bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>(); - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add the explicit instantiation into its lexical context. However, // since explicit instantiations are never found by name lookup, we @@ -8791,15 +8851,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Explicit instantiation of a member class of a class template. DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr) { +Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr) { bool Owned = false; bool IsDependent = false; @@ -9044,7 +9100,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, return true; } - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { // C++1y [temp.explicit]p3: // If the explicit instantiation is for a variable, the unqualified-id // in the declaration shall be a template-id. @@ -9101,8 +9157,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (PrevTemplate) { // Merge attributes. - if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, Prev, Attr); + ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); } if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateVariableDefinition(D.getIdentifierLoc(), Prev); @@ -9126,7 +9181,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // argument list into our AST format. bool HasExplicitTemplateArgs = false; TemplateArgumentListInfo TemplateArgs; - if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) { TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId); HasExplicitTemplateArgs = true; } @@ -9138,7 +9193,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // template. UnresolvedSet<8> TemplateMatches; FunctionDecl *NonTemplateMatch = nullptr; - AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { @@ -9186,7 +9240,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (LangOpts.CUDA && IdentifyCUDATarget(Specialization, /* IgnoreImplicitHDAttributes = */ true) != - IdentifyCUDATarget(Attr)) { + IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); @@ -9265,8 +9319,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, return (Decl*) nullptr; } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes()); // In MSVC mode, dllimported explicit instantiation definitions are treated as // instantiation declarations. @@ -9292,7 +9345,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // // C++98 has the same restriction, just worded differently. FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate(); - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId && !FunTmpl && + if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId && !FunTmpl && D.getCXXScopeSpec().isSet() && !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) Diag(D.getIdentifierLoc(), @@ -9478,8 +9531,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, EnableIfTy.getAs<TemplateSpecializationTypeLoc>(); if (!EnableIfTSTLoc || EnableIfTSTLoc.getNumArgs() == 0) return false; - const TemplateSpecializationType *EnableIfTST = - cast<TemplateSpecializationType>(EnableIfTSTLoc.getTypePtr()); + const TemplateSpecializationType *EnableIfTST = EnableIfTSTLoc.getTypePtr(); // ... which names a complete class template declaration... const TemplateDecl *EnableIfDecl = @@ -9511,7 +9563,7 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, return true; } -/// \brief Build the type that describes a C++ typename specifier, +/// Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, @@ -9686,7 +9738,7 @@ namespace { : TreeTransform<CurrentInstantiationRebuilder>(SemaRef), Loc(Loc), Entity(Entity) { } - /// \brief Determine whether the given type \p T has already been + /// Determine whether the given type \p T has already been /// transformed. /// /// For the purposes of type reconstruction, a type has already been @@ -9695,14 +9747,14 @@ namespace { return T.isNull() || !T->isDependentType(); } - /// \brief Returns the location of the entity whose type is being + /// Returns the location of the entity whose type is being /// rebuilt. SourceLocation getBaseLocation() { return Loc; } - /// \brief Returns the name of the entity whose type is being rebuilt. + /// Returns the name of the entity whose type is being rebuilt. DeclarationName getBaseEntity() { return Entity; } - /// \brief Sets the "base" location and entity when that + /// Sets the "base" location and entity when that /// information is known based on another transformation. void setBase(SourceLocation Loc, DeclarationName Entity) { this->Loc = Loc; @@ -9716,7 +9768,7 @@ namespace { }; } // end anonymous namespace -/// \brief Rebuilds a type within the context of the current instantiation. +/// Rebuilds a type within the context of the current instantiation. /// /// The type \p T is part of the type of an out-of-line member definition of /// a class template (or class template partial specialization) that was parsed @@ -9774,7 +9826,7 @@ bool Sema::RebuildNestedNameSpecifierInCurrentInstantiation(CXXScopeSpec &SS) { return false; } -/// \brief Rebuild the template parameters now that we know we're in a current +/// Rebuild the template parameters now that we know we're in a current /// instantiation. bool Sema::RebuildTemplateParamsInCurrentInstantiation( TemplateParameterList *Params) { @@ -9813,7 +9865,7 @@ bool Sema::RebuildTemplateParamsInCurrentInstantiation( return false; } -/// \brief Produces a formatted string that describes the binding of +/// Produces a formatted string that describes the binding of /// template parameters to template arguments. std::string Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, @@ -9891,7 +9943,7 @@ bool Sema::IsInsideALocalClassWithinATemplateFunction() { } namespace { -/// \brief Walk the path from which a declaration was instantiated, and check +/// Walk the path from which a declaration was instantiated, and check /// that every explicit specialization along that path is visible. This enforces /// C++ [temp.expl.spec]/6: /// @@ -10027,7 +10079,7 @@ void Sema::checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) { ExplicitSpecializationVisibilityChecker(*this, Loc).check(Spec); } -/// \brief Check whether a template partial specialization that we've discovered +/// Check whether a template partial specialization that we've discovered /// is hidden, and produce suitable diagnostics if so. void Sema::checkPartialSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec) { |