diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 302 |
1 files changed, 138 insertions, 164 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4937cce4621f..f930bd8651d5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -726,44 +726,22 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { - DeclContext *DC = getFunctionLevelDeclContext(); - - // C++11 [expr.prim.general]p12: - // An id-expression that denotes a non-static data member or non-static - // member function of a class can only be used: - // (...) - // - if that id-expression denotes a non-static data member and it - // appears in an unevaluated operand. - // - // If this might be the case, form a DependentScopeDeclRefExpr instead of a - // CXXDependentScopeMemberExpr. The former can instantiate to either - // DeclRefExpr or MemberExpr depending on lookup results, while the latter is - // always a MemberExpr. - bool MightBeCxx11UnevalField = - getLangOpts().CPlusPlus11 && isUnevaluatedContext(); - - // Check if the nested name specifier is an enum type. - bool IsEnum = false; - if (NestedNameSpecifier *NNS = SS.getScopeRep()) - IsEnum = isa_and_nonnull<EnumType>(NNS->getAsType()); - - if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && - isa<CXXMethodDecl>(DC) && - cast<CXXMethodDecl>(DC)->isImplicitObjectMemberFunction()) { - QualType ThisType = - cast<CXXMethodDecl>(DC)->getThisType().getNonReferenceType(); - - // Since the 'this' expression is synthesized, we don't need to - // perform the double-lookup check. - NamedDecl *FirstQualifierInScope = nullptr; + if (SS.isEmpty()) { + // FIXME: This codepath is only used by dependent unqualified names + // (e.g. a dependent conversion-function-id, or operator= once we support + // it). It doesn't quite do the right thing, and it will silently fail if + // getCurrentThisType() returns null. + QualType ThisType = getCurrentThisType(); + if (ThisType.isNull()) + return ExprError(); return CXXDependentScopeMemberExpr::Create( - Context, /*This=*/nullptr, ThisType, + Context, /*Base=*/nullptr, ThisType, /*IsArrow=*/!Context.getLangOpts().HLSL, - /*Op=*/SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc, - FirstQualifierInScope, NameInfo, TemplateArgs); + /*OperatorLoc=*/SourceLocation(), + /*QualifierLoc=*/NestedNameSpecifierLoc(), TemplateKWLoc, + /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs); } - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); } @@ -772,13 +750,15 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { - // DependentScopeDeclRefExpr::Create requires a valid QualifierLoc - NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!QualifierLoc) - return ExprError(); + // DependentScopeDeclRefExpr::Create requires a valid NestedNameSpecifierLoc + if (!SS.isValid()) + return CreateRecoveryExpr( + SS.getBeginLoc(), + TemplateArgs ? TemplateArgs->getRAngleLoc() : NameInfo.getEndLoc(), {}); return DependentScopeDeclRefExpr::Create( - Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs); + Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo, + TemplateArgs); } @@ -1091,7 +1071,8 @@ NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename, return Param; } - Param->setDefaultArgument(DefaultTInfo); + Param->setDefaultArgument( + Context, TemplateArgumentLoc(DefaultTInfo->getType(), DefaultTInfo)); } return Param; @@ -1859,7 +1840,8 @@ DeclResult Sema::CheckClassTemplate( TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); - assert(TUK != TUK_Reference && "Can only declare or define class templates"); + assert(TUK != TagUseKind::Reference && + "Can only declare or define class templates"); bool Invalid = false; // Check that we can declare a template here. @@ -1881,8 +1863,9 @@ DeclResult Sema::CheckClassTemplate( // C++11 [basic.lookup.elab]p2). DeclContext *SemanticContext; LookupResult Previous(*this, Name, NameLoc, - (SS.isEmpty() && TUK == TUK_Friend) - ? LookupTagName : LookupOrdinaryName, + (SS.isEmpty() && TUK == TagUseKind::Friend) + ? LookupTagName + : LookupOrdinaryName, forRedeclarationInCurContext()); if (SS.isNotEmpty() && !SS.isInvalid()) { SemanticContext = computeDeclContext(SS, true); @@ -1890,11 +1873,11 @@ DeclResult Sema::CheckClassTemplate( // FIXME: Horrible, horrible hack! We can't currently represent this // in the AST, and historically we have just ignored such friend // class templates, so don't complain here. - Diag(NameLoc, TUK == TUK_Friend + Diag(NameLoc, TUK == TagUseKind::Friend ? diag::warn_template_qualified_friend_ignored : diag::err_template_qualified_declarator_no_match) << SS.getScopeRep() << SS.getRange(); - return TUK != TUK_Friend; + return TUK != TagUseKind::Friend; } if (RequireCompleteDeclContext(SS, SemanticContext)) @@ -1909,7 +1892,7 @@ DeclResult Sema::CheckClassTemplate( Invalid = true; } - if (TUK != TUK_Friend && TUK != TUK_Reference) + if (TUK != TagUseKind::Friend && TUK != TagUseKind::Reference) diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, /*TemplateId-*/ nullptr, /*IsMemberSpecialization*/ false); @@ -1922,7 +1905,7 @@ DeclResult Sema::CheckClassTemplate( // If T is the name of a class, then each of the following shall have a // name different from T: // -- every member template of class T - if (TUK != TUK_Friend && + if (TUK != TagUseKind::Friend && DiagnoseClassNameShadow(SemanticContext, DeclarationNameInfo(Name, NameLoc))) return true; @@ -1964,7 +1947,7 @@ DeclResult Sema::CheckClassTemplate( } } - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { // C++ [namespace.memdef]p3: // [...] When looking for a prior declaration of a class or a function // declared as a friend, and when the name of the friend class or @@ -2001,9 +1984,8 @@ DeclResult Sema::CheckClassTemplate( PrevDecl = (*Previous.begin())->getUnderlyingDecl(); } } - } else if (PrevDecl && - !isDeclInScope(Previous.getRepresentativeDecl(), SemanticContext, - S, SS.isValid())) + } else if (PrevDecl && !isDeclInScope(Previous.getRepresentativeDecl(), + SemanticContext, S, SS.isValid())) PrevDecl = PrevClassTemplate = nullptr; if (auto *Shadow = dyn_cast_or_null<UsingShadowDecl>( @@ -2025,7 +2007,7 @@ DeclResult Sema::CheckClassTemplate( // Ensure that the template parameter lists are compatible. Skip this check // for a friend in a dependent context: the template parameter list itself // could be dependent. - if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && + if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && !TemplateParameterListsAreEqual( TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext : CurContext, @@ -2041,8 +2023,8 @@ DeclResult Sema::CheckClassTemplate( // the class-key shall agree in kind with the original class // template declaration (7.1.5.3). RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl(); - if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, - TUK == TUK_Definition, KWLoc, Name)) { + if (!isAcceptableTagRedeclaration( + PrevRecordDecl, Kind, TUK == TagUseKind::Definition, KWLoc, Name)) { Diag(KWLoc, diag::err_use_with_wrong_tag) << Name << FixItHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName()); @@ -2051,7 +2033,7 @@ DeclResult Sema::CheckClassTemplate( } // Check for redefinition of this class template. - if (TUK == TUK_Definition) { + if (TUK == TagUseKind::Definition) { if (TagDecl *Def = PrevRecordDecl->getDefinition()) { // If we have a prior definition that is not visible, treat this as // simply making that previous definition visible. @@ -2088,7 +2070,7 @@ DeclResult Sema::CheckClassTemplate( // merging in the template parameter list from the previous class // template declaration. Skip this check for a friend in a dependent // context, because the template parameter list might be dependent. - if (!(TUK == TUK_Friend && CurContext->isDependentContext()) && + if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && CheckTemplateParameterList( TemplateParams, PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) @@ -2096,8 +2078,8 @@ DeclResult Sema::CheckClassTemplate( (SS.isSet() && SemanticContext && SemanticContext->isRecord() && SemanticContext->isDependentContext()) ? TPC_ClassTemplateMember - : TUK == TUK_Friend ? TPC_FriendClassTemplate - : TPC_ClassTemplate, + : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate + : TPC_ClassTemplate, SkipBody)) Invalid = true; @@ -2105,9 +2087,10 @@ DeclResult Sema::CheckClassTemplate( // If the name of the template was qualified, we must be defining the // template out-of-line. if (!SS.isInvalid() && !Invalid && !PrevClassTemplate) { - Diag(NameLoc, TUK == TUK_Friend ? diag::err_friend_decl_does_not_match - : diag::err_member_decl_does_not_match) - << Name << SemanticContext << /*IsDefinition*/true << SS.getRange(); + Diag(NameLoc, TUK == TagUseKind::Friend + ? diag::err_friend_decl_does_not_match + : diag::err_member_decl_does_not_match) + << Name << SemanticContext << /*IsDefinition*/ true << SS.getRange(); Invalid = true; } } @@ -2117,8 +2100,8 @@ DeclResult Sema::CheckClassTemplate( // recent declaration tricking the template instantiator to make substitutions // there. // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious - bool ShouldAddRedecl - = !(TUK == TUK_Friend && CurContext->isDependentContext()); + bool ShouldAddRedecl = + !(TUK == TagUseKind::Friend && CurContext->isDependentContext()); CXXRecordDecl *NewClass = CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, @@ -2133,7 +2116,7 @@ DeclResult Sema::CheckClassTemplate( // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(NewClass); AddMsStructLayoutForRecord(NewClass); } @@ -2164,14 +2147,15 @@ DeclResult Sema::CheckClassTemplate( PrevClassTemplate->setMemberSpecialization(); // Set the access specifier. - if (!Invalid && TUK != TUK_Friend && NewTemplate->getDeclContext()->isRecord()) + if (!Invalid && TUK != TagUseKind::Friend && + NewTemplate->getDeclContext()->isRecord()) SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); // Set the lexical context of these templates NewClass->setLexicalDeclContext(CurContext); NewTemplate->setLexicalDeclContext(CurContext); - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) NewClass->startDefinition(); ProcessDeclAttributeList(S, NewClass, Attr); @@ -2184,7 +2168,7 @@ DeclResult Sema::CheckClassTemplate( inferGslOwnerPointerAttribute(NewClass); inferNullableClassAttribute(NewClass); - if (TUK != TUK_Friend) { + if (TUK != TagUseKind::Friend) { // Per C++ [basic.scope.temp]p2, skip the template parameter scopes. Scope *Outer = S; while ((Outer->getFlags() & Scope::TemplateParamScope) != 0) @@ -2338,11 +2322,11 @@ transformTemplateTypeParam(Sema &SemaRef, DeclContext *DC, SemaRef.SubstTypeConstraint(NewTTP, TC, Args, /*EvaluateConstraint=*/true); if (TTP->hasDefaultArgument()) { - TypeSourceInfo *InstantiatedDefaultArg = - SemaRef.SubstType(TTP->getDefaultArgumentInfo(), Args, - TTP->getDefaultArgumentLoc(), TTP->getDeclName()); - if (InstantiatedDefaultArg) - NewTTP->setDefaultArgument(InstantiatedDefaultArg); + TemplateArgumentLoc InstantiatedDefaultArg; + if (!SemaRef.SubstTemplateArgument( + TTP->getDefaultArgument(), Args, InstantiatedDefaultArg, + TTP->getDefaultArgumentLoc(), TTP->getDeclName())) + NewTTP->setDefaultArgument(SemaRef.Context, InstantiatedDefaultArg); } SemaRef.CurrentInstantiationScope->InstantiatedLocal(TTP, NewTTP); return NewTTP; @@ -3595,10 +3579,9 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, = dyn_cast<TemplateTypeParmDecl>(*NewParam)) { // Check the presence of a default argument here. if (NewTypeParm->hasDefaultArgument() && - DiagnoseDefaultTemplateArgument(*this, TPC, - NewTypeParm->getLocation(), - NewTypeParm->getDefaultArgumentInfo()->getTypeLoc() - .getSourceRange())) + DiagnoseDefaultTemplateArgument( + *this, TPC, NewTypeParm->getLocation(), + NewTypeParm->getDefaultArgument().getSourceRange())) NewTypeParm->removeDefaultArgument(); // Merge default arguments for template type parameters. @@ -5035,7 +5018,7 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, IdentifierInfo *Id = D->getIdentifier(); assert(Id && "templated class must have an identifier"); - if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TUK_Definition, + if (!isAcceptableTagRedeclaration(D, TagKind, TUK == TagUseKind::Definition, TagLoc, Id)) { Diag(TagLoc, diag::err_use_with_wrong_tag) << Result @@ -5747,50 +5730,36 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, } // We actually only call this from template instantiation. -ExprResult -Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs) { - +ExprResult Sema::BuildQualifiedTemplateIdExpr( + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, bool IsAddressOfOperand) { assert(TemplateArgs || TemplateKWLoc.isValid()); - DeclContext *DC; - if (!(DC = computeDeclContext(SS, false)) || - DC->isDependentContext() || - RequireCompleteDeclContext(SS, DC)) - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); LookupResult R(*this, NameInfo, LookupOrdinaryName); - if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(), - /*Entering*/ false, TemplateKWLoc)) + if (LookupTemplateName(R, /*S=*/nullptr, SS, /*ObjectType=*/QualType(), + /*EnteringContext=*/false, TemplateKWLoc)) return ExprError(); if (R.isAmbiguous()) return ExprError(); + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); + if (R.empty()) { + DeclContext *DC = computeDeclContext(SS); Diag(NameInfo.getLoc(), diag::err_no_member) << NameInfo.getName() << DC << SS.getRange(); return ExprError(); } - auto DiagnoseTypeTemplateDecl = [&](TemplateDecl *Temp, - bool isTypeAliasTemplateDecl) { - Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template) - << SS.getScopeRep() << NameInfo.getName().getAsString() << SS.getRange() - << isTypeAliasTemplateDecl; - Diag(Temp->getLocation(), diag::note_referenced_type_template) - << isTypeAliasTemplateDecl; - return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); - }; - - if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) - return DiagnoseTypeTemplateDecl(Temp, false); - - if (TypeAliasTemplateDecl *Temp = R.getAsSingle<TypeAliasTemplateDecl>()) - return DiagnoseTypeTemplateDecl(Temp, true); + // If necessary, build an implicit class member access. + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + /*S=*/nullptr); - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL=*/false, TemplateArgs); } /// Form a template name from a name that is syntactically required to name a @@ -5982,8 +5951,7 @@ bool Sema::CheckTemplateTypeArgument( LookupParsedName(Result, CurScope, &SS, /*ObjectType=*/QualType()); if (Result.getAsSingle<TypeDecl>() || - Result.getResultKind() == - LookupResult::NotFoundInCurrentInstantiation) { + Result.wasNotFoundInCurrentInstantiation()) { assert(SS.getScopeRep() && "dependent scope expr must has a scope!"); // Suggest that the user add 'typename' before the NNS. SourceLocation Loc = AL.getSourceRange().getBegin(); @@ -6075,22 +6043,26 @@ bool Sema::CheckTemplateTypeArgument( /// /// \param Converted the list of template arguments provided for template /// parameters that precede \p Param in the template parameter list. -/// \returns the substituted template argument, or NULL if an error occurred. -static TypeSourceInfo *SubstDefaultTemplateArgument( +/// +/// \param Output the resulting substituted template argument. +/// +/// \returns true if an error occurred. +static bool SubstDefaultTemplateArgument( Sema &SemaRef, TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTypeParmDecl *Param, ArrayRef<TemplateArgument> SugaredConverted, - ArrayRef<TemplateArgument> CanonicalConverted) { - TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo(); + ArrayRef<TemplateArgument> CanonicalConverted, + TemplateArgumentLoc &Output) { + Output = Param->getDefaultArgument(); // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. - if (ArgType->getType()->isInstantiationDependentType()) { + if (Output.getArgument().isInstantiationDependent()) { Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc, Param, Template, SugaredConverted, SourceRange(TemplateLoc, RAngleLoc)); if (Inst.isInvalid()) - return nullptr; + return true; // Only substitute for the innermost template argument list. MultiLevelTemplateArgumentList TemplateArgLists(Template, SugaredConverted, @@ -6103,12 +6075,14 @@ static TypeSourceInfo *SubstDefaultTemplateArgument( ForLambdaCallOperator = Rec->isLambda(); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext(), !ForLambdaCallOperator); - ArgType = - SemaRef.SubstType(ArgType, TemplateArgLists, - Param->getDefaultArgumentLoc(), Param->getDeclName()); + + if (SemaRef.SubstTemplateArgument(Output, TemplateArgLists, Output, + Param->getDefaultArgumentLoc(), + Param->getDeclName())) + return true; } - return ArgType; + return false; } /// Substitute template arguments into the default template argument for @@ -6231,13 +6205,12 @@ TemplateArgumentLoc Sema::SubstDefaultTemplateArgumentIfAvailable( return TemplateArgumentLoc(); HasDefaultArg = true; - TypeSourceInfo *DI = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, TypeParm, SugaredConverted, - CanonicalConverted); - if (DI) - return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); - - return TemplateArgumentLoc(); + TemplateArgumentLoc Output; + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + TypeParm, SugaredConverted, + CanonicalConverted, Output)) + return TemplateArgumentLoc(); + return Output; } if (NonTypeTemplateParmDecl *NonTypeParm @@ -6820,14 +6793,10 @@ bool Sema::CheckTemplateArgumentList( return diagnoseMissingArgument(*this, TemplateLoc, Template, TTP, NewArgs); - TypeSourceInfo *ArgType = SubstDefaultTemplateArgument( - *this, Template, TemplateLoc, RAngleLoc, TTP, SugaredConverted, - CanonicalConverted); - if (!ArgType) + if (SubstDefaultTemplateArgument(*this, Template, TemplateLoc, RAngleLoc, + TTP, SugaredConverted, + CanonicalConverted, Arg)) return true; - - Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), - ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { if (!hasReachableDefaultArgument(NTTP)) @@ -9486,7 +9455,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( SourceLocation ModulePrivateLoc, CXXScopeSpec &SS, TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr, MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { - assert(TUK != TUK_Reference && "References are not specializations"); + assert(TUK != TagUseKind::Reference && "References are not specializations"); SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc; SourceLocation LAngleLoc = TemplateId.LAngleLoc; @@ -9508,7 +9477,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( bool isPartialSpecialization = false; if (SS.isSet()) { - if (TUK != TUK_Reference && TUK != TUK_Friend && + if (TUK != TagUseKind::Reference && TUK != TagUseKind::Friend && diagnoseQualifiedDeclaration(SS, ClassTemplate->getDeclContext(), ClassTemplate->getDeclName(), TemplateNameLoc, &TemplateId, @@ -9523,9 +9492,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( bool Invalid = false; TemplateParameterList *TemplateParams = MatchTemplateParametersToScopeSpecifier( - KWLoc, TemplateNameLoc, SS, &TemplateId, - TemplateParameterLists, TUK == TUK_Friend, isMemberSpecialization, - Invalid); + KWLoc, TemplateNameLoc, SS, &TemplateId, TemplateParameterLists, + TUK == TagUseKind::Friend, isMemberSpecialization, Invalid); if (Invalid) return true; @@ -9536,7 +9504,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( if (TemplateParams && TemplateParams->size() > 0) { isPartialSpecialization = true; - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { Diag(KWLoc, diag::err_partial_specialization_friend) << SourceRange(LAngleLoc, RAngleLoc); return true; @@ -9572,14 +9540,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } } } else if (TemplateParams) { - if (TUK == TUK_Friend) + if (TUK == TagUseKind::Friend) Diag(KWLoc, diag::err_template_spec_friend) << FixItHint::CreateRemoval( SourceRange(TemplateParams->getTemplateLoc(), TemplateParams->getRAngleLoc())) << SourceRange(LAngleLoc, RAngleLoc); } else { - assert(TUK == TUK_Friend && "should have a 'template<>' for this decl"); + assert(TUK == TagUseKind::Friend && + "should have a 'template<>' for this decl"); } // Check that the specialization uses the same tag kind as the @@ -9587,8 +9556,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); assert(Kind != TagTypeKind::Enum && "Invalid enum tag in class template spec!"); - if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), - Kind, TUK == TUK_Definition, KWLoc, + if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), Kind, + TUK == TagUseKind::Definition, KWLoc, ClassTemplate->getIdentifier())) { Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate @@ -9652,7 +9621,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Check whether we can declare a class template specialization in // the current scope. - if (TUK != TUK_Friend && + if (TUK != TagUseKind::Friend && CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl, TemplateNameLoc, isPartialSpecialization)) @@ -9679,8 +9648,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // This rule has since been removed, because it's redundant given DR1495, // but we keep it because it produces better diagnostics and recovery. Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) - << /*class template*/0 << (TUK == TUK_Definition) - << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); + << /*class template*/ 0 << (TUK == TagUseKind::Definition) + << FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(), TemplateNameLoc, @@ -9772,11 +9741,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization( } // If this is not a friend, note that this is an explicit specialization. - if (TUK != TUK_Friend) + if (TUK != TagUseKind::Friend) Specialization->setSpecializationKind(TSK_ExplicitSpecialization); // Check that this isn't a redefinition of this specialization. - if (TUK == TUK_Definition) { + if (TUK == TagUseKind::Definition) { RecordDecl *Def = Specialization->getDefinition(); NamedDecl *Hidden = nullptr; if (Def && SkipBody && !hasVisibleDefinition(Def, &Hidden)) { @@ -9797,7 +9766,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) { + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) { AddAlignmentAttributesForRecord(Specialization); AddMsStructLayoutForRecord(Specialization); } @@ -9818,10 +9787,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization( Specialization->setLexicalDeclContext(CurContext); // We may be starting the definition of this specialization. - if (TUK == TUK_Definition && (!SkipBody || !SkipBody->ShouldSkip)) + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) Specialization->startDefinition(); - if (TUK == TUK_Friend) { + if (TUK == TagUseKind::Friend) { // Build the fully-sugared type for this class template // specialization as the user wrote in the specialization // itself. This means that we'll pretty-print the type retrieved @@ -10290,15 +10259,20 @@ bool Sema::CheckFunctionTemplateSpecialization( Ovl->getDeclContext()->getRedeclContext())) continue; + QualType FT = FD->getType(); + // C++11 [dcl.constexpr]p8: + // A constexpr specifier for a non-static member function that is not + // a constructor declares that member function to be const. + // // When matching a constexpr member function template specialization // against the primary template, we don't yet know whether the // specialization has an implicit 'const' (because we don't know whether // it will be a static member function until we know which template it - // specializes), so adjust it now assuming it specializes this template. - QualType FT = FD->getType(); - if (FD->isConstexpr()) { - CXXMethodDecl *OldMD = - dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + // specializes). This rule was removed in C++14. + if (auto *NewMD = dyn_cast<CXXMethodDecl>(FD); + !getLangOpts().CPlusPlus14 && NewMD && NewMD->isConstexpr() && + !isa<CXXConstructorDecl, CXXDestructorDecl>(NewMD)) { + auto *OldMD = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); if (OldMD && OldMD->isConst()) { const FunctionProtoType *FPT = FT->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); @@ -11124,8 +11098,7 @@ DeclResult Sema::ActOnExplicitInstantiation( Def->setTemplateSpecializationKind(TSK); if (!getDLLAttr(Def) && getDLLAttr(Specialization) && - (Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !Context.getTargetInfo().getTriple().isPS())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // An explicit instantiation definition can add a dll attribute to a // template with a previous instantiation declaration. MinGW doesn't // allow this. @@ -11142,8 +11115,7 @@ DeclResult Sema::ActOnExplicitInstantiation( bool NewlyDLLExported = !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>(); if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && - (Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !Context.getTargetInfo().getTriple().isPS())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // An explicit instantiation definition can add a dll attribute to a // template with a previous implicit instantiation. MinGW doesn't allow // this. We limit clang to only adding dllexport, to avoid potentially @@ -11192,11 +11164,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, bool Owned = false; bool IsDependent = false; - Decl *TagD = ActOnTag(S, TagSpec, Sema::TUK_Reference, KWLoc, SS, Name, - NameLoc, Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), + Decl *TagD = + ActOnTag(S, TagSpec, TagUseKind::Reference, KWLoc, SS, Name, NameLoc, + Attr, AS_none, /*ModulePrivateLoc=*/SourceLocation(), MultiTemplateParamsArg(), Owned, IsDependent, SourceLocation(), false, TypeResult(), /*IsTypeSpecifier*/ false, - /*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside).get(); + /*IsTemplateParamOrArg*/ false, /*OOK=*/OOK_Outside) + .get(); assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); if (!TagD) @@ -11727,9 +11701,9 @@ TypeResult Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); - if (TUK == TUK_Declaration || TUK == TUK_Definition) { + if (TUK == TagUseKind::Declaration || TUK == TagUseKind::Definition) { Diag(NameLoc, diag::err_dependent_tag_decl) - << (TUK == TUK_Definition) << llvm::to_underlying(Kind) + << (TUK == TagUseKind::Definition) << llvm::to_underlying(Kind) << SS.getRange(); return true; } |
