diff options
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiateDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 432 |
1 files changed, 347 insertions, 85 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index d1ad304e62e4..64500d0a26d5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -385,12 +385,13 @@ static void instantiateOMPDeclareVariantAttr( }; ExprResult VariantFuncRef; - if (Expr *E = Attr.getVariantFuncRef()) + if (Expr *E = Attr.getVariantFuncRef()) { + // Do not mark function as is used to prevent its emission if this is the + // only place where it is used. + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); VariantFuncRef = Subst(E); - - ExprResult Score; - if (Expr *E = Attr.getScore()) - Score = Subst(E); + } // Check function/variant ref. Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData = @@ -398,12 +399,41 @@ static void instantiateOMPDeclareVariantAttr( S.ConvertDeclToDeclGroup(New), VariantFuncRef.get(), Attr.getRange()); if (!DeclVarData) return; - // Instantiate the attribute. - Sema::OpenMPDeclareVariantCtsSelectorData Data( - Attr.getCtxSelectorSet(), Attr.getCtxSelector(), - llvm::makeMutableArrayRef(Attr.implVendors_begin(), - Attr.implVendors_size()), - Score); + SmallVector<Sema::OMPCtxSelectorData, 4> Data; + for (unsigned I = 0, E = Attr.scores_size(); I < E; ++I) { + ExprResult Score; + if (Expr *E = *std::next(Attr.scores_begin(), I)) + Score = Subst(E); + // Instantiate the attribute. + auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( + *std::next(Attr.ctxSelectorSets_begin(), I)); + auto Ctx = static_cast<OpenMPContextSelectorKind>( + *std::next(Attr.ctxSelectors_begin(), I)); + switch (CtxSet) { + case OMP_CTX_SET_implementation: + switch (Ctx) { + case OMP_CTX_vendor: + Data.emplace_back(CtxSet, Ctx, Score, Attr.implVendors()); + break; + case OMP_CTX_kind: + case OMP_CTX_unknown: + llvm_unreachable("Unexpected context selector kind."); + } + break; + case OMP_CTX_SET_device: + switch (Ctx) { + case OMP_CTX_kind: + Data.emplace_back(CtxSet, Ctx, Score, Attr.deviceKinds()); + break; + case OMP_CTX_vendor: + case OMP_CTX_unknown: + llvm_unreachable("Unexpected context selector kind."); + } + break; + case OMP_CTX_SET_unknown: + llvm_unreachable("Unexpected context selector set kind."); + } + } S.ActOnOpenMPDeclareVariantDirective(DeclVarData.getValue().first, DeclVarData.getValue().second, Attr.getRange(), Data); @@ -625,11 +655,10 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, LateAttrs->push_back(LateInstantiatedAttribute(TmplAttr, Saved, New)); } else { // Allow 'this' within late-parsed attributes. - NamedDecl *ND = dyn_cast<NamedDecl>(New); - CXXRecordDecl *ThisContext = - dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); + auto *ND = cast<NamedDecl>(New); + auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(ND->getDeclContext()); CXXThisScopeRAII ThisScope(*this, ThisContext, Qualifiers(), - ND && ND->isCXXInstanceMember()); + ND->isCXXInstanceMember()); Attr *NewAttr = sema::instantiateTemplateAttribute(TmplAttr, Context, *this, TemplateArgs); @@ -905,6 +934,9 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D, SemaRef.inferObjCARCLifetime(Var)) Var->setInvalidDecl(); + if (SemaRef.getLangOpts().OpenCL) + SemaRef.deduceOpenCLAddressSpace(Var); + // Substitute the nested name specifier, if any. if (SubstQualifier(D, Var)) return nullptr; @@ -1761,8 +1793,9 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context, /// 1) instantiating function templates /// 2) substituting friend declarations /// 3) substituting deduction guide declarations for nested class templates -Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, - TemplateParameterList *TemplateParams) { +Decl *TemplateDeclInstantiator::VisitFunctionDecl( + FunctionDecl *D, TemplateParameterList *TemplateParams, + RewriteKind FunctionRewriteKind) { // Check whether there is already a function template specialization for // this declaration. FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); @@ -1812,6 +1845,18 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, return nullptr; } + // FIXME: Concepts: Do not substitute into constraint expressions + Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); + if (TrailingRequiresClause) { + ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, + TemplateArgs); + if (SubstRC.isInvalid()) + return nullptr; + TrailingRequiresClause = SubstRC.get(); + if (!SemaRef.CheckConstraintExpression(TrailingRequiresClause)) + return nullptr; + } + // If we're instantiating a local function declaration, put the result // in the enclosing namespace; otherwise we need to find the instantiated // context. @@ -1832,6 +1877,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + if (FunctionRewriteKind != RewriteKind::None) + adjustForRewrite(FunctionRewriteKind, D, T, TInfo, NameInfo); + FunctionDecl *Function; if (auto *DGuide = dyn_cast<CXXDeductionGuideDecl>(D)) { Function = CXXDeductionGuideDecl::Create( @@ -1845,7 +1893,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Function = FunctionDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo, D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->getConstexprKind()); + D->hasWrittenPrototype(), D->getConstexprKind(), + TrailingRequiresClause); Function->setRangeEnd(D->getSourceRange().getEnd()); } @@ -1872,6 +1921,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Params[P]->setOwningFunction(Function); Function->setParams(Params); + if (TrailingRequiresClause) + Function->setTrailingRequiresClause(TrailingRequiresClause); + if (TemplateParams) { // Our resulting instantiation is actually a function template, since we // are substituting only the outer template parameters. For example, given @@ -2049,6 +2101,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, } } + if (D->isExplicitlyDefaulted()) { + if (SubstDefaultedFunction(Function, D)) + return nullptr; + } + if (D->isDeleted()) + SemaRef.SetDeclDeleted(Function, D->getLocation()); + if (Function->isLocalExternDecl() && !Function->getPreviousDecl()) DC->makeDeclVisibleInContext(PrincipalDecl); @@ -2056,14 +2115,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, PrincipalDecl->isInIdentifierNamespace(Decl::IDNS_Ordinary)) PrincipalDecl->setNonMemberOperator(); - assert(!D->isDefaulted() && "only methods should be defaulted"); return Function; } Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( CXXMethodDecl *D, TemplateParameterList *TemplateParams, - Optional<const ASTTemplateArgumentListInfo *> - ClassScopeSpecializationArgs) { + Optional<const ASTTemplateArgumentListInfo *> ClassScopeSpecializationArgs, + RewriteKind FunctionRewriteKind) { FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); if (FunctionTemplate && !TemplateParams) { // We are creating a function template specialization from a function @@ -2125,6 +2183,18 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( return nullptr; } + // FIXME: Concepts: Do not substitute into constraint expressions + Expr *TrailingRequiresClause = D->getTrailingRequiresClause(); + if (TrailingRequiresClause) { + ExprResult SubstRC = SemaRef.SubstExpr(TrailingRequiresClause, + TemplateArgs); + if (SubstRC.isInvalid()) + return nullptr; + TrailingRequiresClause = SubstRC.get(); + if (!SemaRef.CheckConstraintExpression(TrailingRequiresClause)) + return nullptr; + } + DeclContext *DC = Owner; if (isFriend) { if (QualifierLoc) { @@ -2142,34 +2212,42 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( if (!DC) return nullptr; } + DeclarationNameInfo NameInfo + = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); + + if (FunctionRewriteKind != RewriteKind::None) + adjustForRewrite(FunctionRewriteKind, D, T, TInfo, NameInfo); + // Build the instantiated method declaration. CXXRecordDecl *Record = cast<CXXRecordDecl>(DC); CXXMethodDecl *Method = nullptr; SourceLocation StartLoc = D->getInnerLocStart(); - DeclarationNameInfo NameInfo - = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) { Method = CXXConstructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, - Constructor->getConstexprKind()); + Constructor->getConstexprKind(), InheritedConstructor(), + TrailingRequiresClause); Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, - Destructor->isInlineSpecified(), false, Destructor->getConstexprKind()); + Destructor->isInlineSpecified(), false, Destructor->getConstexprKind(), + TrailingRequiresClause); Method->setRangeEnd(Destructor->getEndLoc()); } else if (CXXConversionDecl *Conversion = dyn_cast<CXXConversionDecl>(D)) { Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, - Conversion->getConstexprKind(), Conversion->getEndLoc()); + Conversion->getConstexprKind(), Conversion->getEndLoc(), + TrailingRequiresClause); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, SC, D->isInlineSpecified(), - D->getConstexprKind(), D->getEndLoc()); + D->getConstexprKind(), D->getEndLoc(), + TrailingRequiresClause); } if (D->isInlined()) @@ -2325,8 +2403,10 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( SemaRef.CheckOverrideControl(Method); // If a function is defined as defaulted or deleted, mark it as such now. - if (D->isExplicitlyDefaulted()) - SemaRef.SetDeclDefaulted(Method, Method->getLocation()); + if (D->isExplicitlyDefaulted()) { + if (SubstDefaultedFunction(Method, D)) + return nullptr; + } if (D->isDeletedAsWritten()) SemaRef.SetDeclDeleted(Method, Method->getLocation()); @@ -2399,13 +2479,68 @@ Decl *TemplateDeclInstantiator::VisitTemplateTypeParmDecl( // TODO: don't always clone when decls are refcounted. assert(D->getTypeForDecl()->isTemplateTypeParmType()); + Optional<unsigned> NumExpanded; + + if (const TypeConstraint *TC = D->getTypeConstraint()) { + if (D->isPackExpansion() && !D->isExpandedParameterPack()) { + assert(TC->getTemplateArgsAsWritten() && + "type parameter can only be an expansion when explicit arguments " + "are specified"); + // The template type parameter pack's type is a pack expansion of types. + // Determine whether we need to expand this parameter pack into separate + // types. + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + for (auto &ArgLoc : TC->getTemplateArgsAsWritten()->arguments()) + SemaRef.collectUnexpandedParameterPacks(ArgLoc, Unexpanded); + + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + if (SemaRef.CheckParameterPacksForExpansion( + cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) + ->getEllipsisLoc(), + SourceRange(TC->getConceptNameLoc(), + TC->hasExplicitTemplateArgs() ? + TC->getTemplateArgsAsWritten()->getRAngleLoc() : + TC->getConceptNameInfo().getEndLoc()), + Unexpanded, TemplateArgs, Expand, RetainExpansion, NumExpanded)) + return nullptr; + } + } + TemplateTypeParmDecl *Inst = TemplateTypeParmDecl::Create( SemaRef.Context, Owner, D->getBeginLoc(), D->getLocation(), D->getDepth() - TemplateArgs.getNumSubstitutedLevels(), D->getIndex(), - D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack()); + D->getIdentifier(), D->wasDeclaredWithTypename(), D->isParameterPack(), + D->hasTypeConstraint(), NumExpanded); + Inst->setAccess(AS_public); Inst->setImplicit(D->isImplicit()); - + if (auto *TC = D->getTypeConstraint()) { + // TODO: Concepts: do not instantiate the constraint (delayed constraint + // substitution) + const ASTTemplateArgumentListInfo *TemplArgInfo + = TC->getTemplateArgsAsWritten(); + TemplateArgumentListInfo InstArgs; + + if (TemplArgInfo) { + InstArgs.setLAngleLoc(TemplArgInfo->LAngleLoc); + InstArgs.setRAngleLoc(TemplArgInfo->RAngleLoc); + if (SemaRef.Subst(TemplArgInfo->getTemplateArgs(), + TemplArgInfo->NumTemplateArgs, + InstArgs, TemplateArgs)) + return nullptr; + } + if (SemaRef.AttachTypeConstraint( + TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), + TC->getNamedConcept(), &InstArgs, Inst, + D->isParameterPack() + ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) + ->getEllipsisLoc() + : SourceLocation())) + return nullptr; + } if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) { TypeSourceInfo *InstantiatedDefaultArg = SemaRef.SubstType(D->getDefaultArgumentInfo(), TemplateArgs, @@ -3040,7 +3175,9 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( } if (SubstReductionType.isNull()) return nullptr; - bool IsCorrect = !SubstReductionType.isNull(); + Expr *Combiner = D->getCombiner(); + Expr *Init = D->getInitializer(); + bool IsCorrect = true; // Create instantiated copy. std::pair<QualType, SourceLocation> ReductionTypes[] = { std::make_pair(SubstReductionType, D->getLocation())}; @@ -3055,23 +3192,10 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( PrevDeclInScope); auto *NewDRD = cast<OMPDeclareReductionDecl>(DRD.get().getSingleDecl()); SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewDRD); - if (!RequiresInstantiation) { - if (Expr *Combiner = D->getCombiner()) { - NewDRD->setCombinerData(D->getCombinerIn(), D->getCombinerOut()); - NewDRD->setCombiner(Combiner); - if (Expr *Init = D->getInitializer()) { - NewDRD->setInitializerData(D->getInitOrig(), D->getInitPriv()); - NewDRD->setInitializer(Init, D->getInitializerKind()); - } - } - (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd( - /*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl()); - return NewDRD; - } Expr *SubstCombiner = nullptr; Expr *SubstInitializer = nullptr; // Combiners instantiation sequence. - if (D->getCombiner()) { + if (Combiner) { SemaRef.ActOnOpenMPDeclareReductionCombinerStart( /*S=*/nullptr, NewDRD); SemaRef.CurrentInstantiationScope->InstantiatedLocal( @@ -3083,41 +3207,41 @@ Decl *TemplateDeclInstantiator::VisitOMPDeclareReductionDecl( auto *ThisContext = dyn_cast_or_null<CXXRecordDecl>(Owner); Sema::CXXThisScopeRAII ThisScope(SemaRef, ThisContext, Qualifiers(), ThisContext); - SubstCombiner = SemaRef.SubstExpr(D->getCombiner(), TemplateArgs).get(); + SubstCombiner = SemaRef.SubstExpr(Combiner, TemplateArgs).get(); SemaRef.ActOnOpenMPDeclareReductionCombinerEnd(NewDRD, SubstCombiner); - // Initializers instantiation sequence. - if (D->getInitializer()) { - VarDecl *OmpPrivParm = - SemaRef.ActOnOpenMPDeclareReductionInitializerStart( - /*S=*/nullptr, NewDRD); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getInitOrig())->getDecl(), - cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl()); - SemaRef.CurrentInstantiationScope->InstantiatedLocal( - cast<DeclRefExpr>(D->getInitPriv())->getDecl(), - cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl()); - if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { - SubstInitializer = - SemaRef.SubstExpr(D->getInitializer(), TemplateArgs).get(); - } else { - IsCorrect = IsCorrect && OmpPrivParm->hasInit(); - } - SemaRef.ActOnOpenMPDeclareReductionInitializerEnd( - NewDRD, SubstInitializer, OmpPrivParm); + } + // Initializers instantiation sequence. + if (Init) { + VarDecl *OmpPrivParm = SemaRef.ActOnOpenMPDeclareReductionInitializerStart( + /*S=*/nullptr, NewDRD); + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getInitOrig())->getDecl(), + cast<DeclRefExpr>(NewDRD->getInitOrig())->getDecl()); + SemaRef.CurrentInstantiationScope->InstantiatedLocal( + cast<DeclRefExpr>(D->getInitPriv())->getDecl(), + cast<DeclRefExpr>(NewDRD->getInitPriv())->getDecl()); + if (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit) { + SubstInitializer = SemaRef.SubstExpr(Init, TemplateArgs).get(); + } else { + auto *OldPrivParm = + cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()); + IsCorrect = IsCorrect && OldPrivParm->hasInit(); + if (IsCorrect) + SemaRef.InstantiateVariableInitializer(OmpPrivParm, OldPrivParm, + TemplateArgs); } - IsCorrect = - IsCorrect && SubstCombiner && - (!D->getInitializer() || - (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit && - SubstInitializer) || - (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && - !SubstInitializer && !SubstInitializer)); - } else { - IsCorrect = false; + SemaRef.ActOnOpenMPDeclareReductionInitializerEnd(NewDRD, SubstInitializer, + OmpPrivParm); } + IsCorrect = IsCorrect && SubstCombiner && + (!Init || + (D->getInitializerKind() == OMPDeclareReductionDecl::CallInit && + SubstInitializer) || + (D->getInitializerKind() != OMPDeclareReductionDecl::CallInit && + !SubstInitializer)); - (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd(/*S=*/nullptr, DRD, - IsCorrect); + (void)SemaRef.ActOnOpenMPDeclareReductionDirectiveEnd( + /*S=*/nullptr, DRD, IsCorrect && !D->isInvalidDecl()); return NewDRD; } @@ -3163,7 +3287,8 @@ TemplateDeclInstantiator::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { } else { // Instantiate the mapper variable. DeclarationNameInfo DirName; - SemaRef.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, /*S=*/nullptr, + SemaRef.StartOpenMPDSABlock(llvm::omp::OMPD_declare_mapper, DirName, + /*S=*/nullptr, (*D->clauselist_begin())->getBeginLoc()); SemaRef.ActOnOpenMPDeclareMapperDirectiveVarDecl( NewDMD, /*S=*/nullptr, SubstMapperTy, D->getLocation(), VN); @@ -3275,7 +3400,8 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl( D->getLocation(), InstTemplateArgs, false, - Converted)) + Converted, + /*UpdateArgsWithConversion=*/true)) return nullptr; // Figure out where to insert this class template explicit specialization @@ -3396,7 +3522,8 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl( // Check that the template argument list is well-formed for this template. SmallVector<TemplateArgument, 4> Converted; if (SemaRef.CheckTemplateArgumentList(InstVarTemplate, D->getLocation(), - VarTemplateArgsInfo, false, Converted)) + VarTemplateArgsInfo, false, Converted, + /*UpdateArgsWithConversion=*/true)) return nullptr; // Check whether we've already seen a declaration of this specialization. @@ -3490,6 +3617,73 @@ Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, return SubstD; } +void TemplateDeclInstantiator::adjustForRewrite(RewriteKind RK, + FunctionDecl *Orig, QualType &T, + TypeSourceInfo *&TInfo, + DeclarationNameInfo &NameInfo) { + assert(RK == RewriteKind::RewriteSpaceshipAsEqualEqual); + + // C++2a [class.compare.default]p3: + // the return type is replaced with bool + auto *FPT = T->castAs<FunctionProtoType>(); + T = SemaRef.Context.getFunctionType( + SemaRef.Context.BoolTy, FPT->getParamTypes(), FPT->getExtProtoInfo()); + + // Update the return type in the source info too. The most straightforward + // way is to create new TypeSourceInfo for the new type. Use the location of + // the '= default' as the location of the new type. + // + // FIXME: Set the correct return type when we initially transform the type, + // rather than delaying it to now. + TypeSourceInfo *NewTInfo = + SemaRef.Context.getTrivialTypeSourceInfo(T, Orig->getEndLoc()); + auto OldLoc = TInfo->getTypeLoc().getAsAdjusted<FunctionProtoTypeLoc>(); + assert(OldLoc && "type of function is not a function type?"); + auto NewLoc = NewTInfo->getTypeLoc().castAs<FunctionProtoTypeLoc>(); + for (unsigned I = 0, N = OldLoc.getNumParams(); I != N; ++I) + NewLoc.setParam(I, OldLoc.getParam(I)); + TInfo = NewTInfo; + + // and the declarator-id is replaced with operator== + NameInfo.setName( + SemaRef.Context.DeclarationNames.getCXXOperatorName(OO_EqualEqual)); +} + +FunctionDecl *Sema::SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD, + FunctionDecl *Spaceship) { + if (Spaceship->isInvalidDecl()) + return nullptr; + + // C++2a [class.compare.default]p3: + // an == operator function is declared implicitly [...] with the same + // access and function-definition and in the same class scope as the + // three-way comparison operator function + MultiLevelTemplateArgumentList NoTemplateArgs; + TemplateDeclInstantiator Instantiator(*this, RD, NoTemplateArgs); + Decl *R; + if (auto *MD = dyn_cast<CXXMethodDecl>(Spaceship)) { + R = Instantiator.VisitCXXMethodDecl( + MD, nullptr, None, + TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual); + } else { + assert(Spaceship->getFriendObjectKind() && + "defaulted spaceship is neither a member nor a friend"); + + R = Instantiator.VisitFunctionDecl( + Spaceship, nullptr, + TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual); + if (!R) + return nullptr; + + FriendDecl *FD = + FriendDecl::Create(Context, RD, Spaceship->getLocation(), + cast<NamedDecl>(R), Spaceship->getBeginLoc()); + FD->setAccess(AS_public); + RD->addDecl(FD); + } + return cast_or_null<FunctionDecl>(R); +} + /// Instantiates a nested template parameter list in the current /// instantiation context. /// @@ -3598,7 +3792,8 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // in the member template's set of class template partial specializations. void *InsertPos = nullptr; ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->findPartialSpecialization(Converted, InsertPos); + = ClassTemplate->findPartialSpecialization(Converted, InstParams, + InsertPos); // Build the canonical type that describes the converted template // arguments of the class template partial specialization. @@ -3722,7 +3917,7 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization( // in the member template's set of variable template partial specializations. void *InsertPos = nullptr; VarTemplateSpecializationDecl *PrevDecl = - VarTemplate->findPartialSpecialization(Converted, InsertPos); + VarTemplate->findPartialSpecialization(Converted, InstParams, InsertPos); // Build the canonical type that describes the converted template // arguments of the variable template partial specialization. @@ -4009,6 +4204,48 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, TemplateArgs); } +bool Sema::CheckInstantiatedFunctionTemplateConstraints( + SourceLocation PointOfInstantiation, FunctionDecl *Decl, + ArrayRef<TemplateArgument> TemplateArgs, + ConstraintSatisfaction &Satisfaction) { + // In most cases we're not going to have constraints, so check for that first. + FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); + // Note - code synthesis context for the constraints check is created + // inside CheckConstraintsSatisfaction. + SmallVector<const Expr *, 3> TemplateAC; + Template->getAssociatedConstraints(TemplateAC); + if (TemplateAC.empty()) { + Satisfaction.IsSatisfied = true; + return false; + } + + // Enter the scope of this instantiation. We don't use + // PushDeclContext because we don't have a scope. + Sema::ContextRAII savedContext(*this, Decl); + LocalInstantiationScope Scope(*this); + + MultiLevelTemplateArgumentList MLTAL = + getTemplateInstantiationArgs(Decl, nullptr, /*RelativeToPrimary*/true); + + // If this is not an explicit specialization - we need to get the instantiated + // version of the template arguments and add them to scope for the + // substitution. + if (Decl->isTemplateInstantiation()) { + InstantiatingTemplate Inst(*this, Decl->getPointOfInstantiation(), + InstantiatingTemplate::ConstraintsCheck{}, Decl->getPrimaryTemplate(), + MLTAL.getInnermost(), SourceRange()); + if (Inst.isInvalid()) + return true; + if (addInstantiatedParametersToScope(*this, Decl, + Decl->getTemplateInstantiationPattern(), + Scope, MLTAL)) + return true; + } + + return CheckConstraintSatisfaction(Template, TemplateAC, TemplateArgs, + PointOfInstantiation, Satisfaction); +} + /// Initializes the common fields of an instantiation function /// declaration (New) from the corresponding fields of its template (Tmpl). /// @@ -4016,9 +4253,6 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, bool TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl) { - if (Tmpl->isDeleted()) - New->setDeletedAsWritten(); - New->setImplicit(Tmpl->isImplicit()); // Forward the mangling number from the template to the instantiated decl. @@ -4119,6 +4353,34 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, return false; } +bool TemplateDeclInstantiator::SubstDefaultedFunction(FunctionDecl *New, + FunctionDecl *Tmpl) { + // Transfer across any unqualified lookups. + if (auto *DFI = Tmpl->getDefaultedFunctionInfo()) { + SmallVector<DeclAccessPair, 32> Lookups; + Lookups.reserve(DFI->getUnqualifiedLookups().size()); + bool AnyChanged = false; + for (DeclAccessPair DA : DFI->getUnqualifiedLookups()) { + NamedDecl *D = SemaRef.FindInstantiatedDecl(New->getLocation(), + DA.getDecl(), TemplateArgs); + if (!D) + return true; + AnyChanged |= (D != DA.getDecl()); + Lookups.push_back(DeclAccessPair::make(D, DA.getAccess())); + } + + // It's unlikely that substitution will change any declarations. Don't + // store an unnecessary copy in that case. + New->setDefaultedFunctionInfo( + AnyChanged ? FunctionDecl::DefaultedFunctionInfo::Create( + SemaRef.Context, Lookups) + : DFI); + } + + SemaRef.SetDeclDefaulted(New, Tmpl->getLocation()); + return false; +} + /// Instantiate (or find existing instantiation of) a function template with a /// given set of template arguments. /// |