diff options
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 294 |
1 files changed, 251 insertions, 43 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index dfe37d8..58fe59e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -28,11 +28,20 @@ using namespace clang; /// \brief Retrieve the template argument list(s) that should be used to /// instantiate the definition of the given declaration. +/// +/// \param D the declaration for which we are computing template instantiation +/// arguments. +/// +/// \param Innermost if non-NULL, the innermost template argument list. MultiLevelTemplateArgumentList -Sema::getTemplateInstantiationArgs(NamedDecl *D) { +Sema::getTemplateInstantiationArgs(NamedDecl *D, + const TemplateArgumentList *Innermost) { // Accumulate the set of template argument lists in this structure. MultiLevelTemplateArgumentList Result; + if (Innermost) + Result.addOuterTemplateArguments(Innermost); + DeclContext *Ctx = dyn_cast<DeclContext>(D); if (!Ctx) Ctx = D->getDeclContext(); @@ -87,6 +96,23 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) { return Result; } +bool Sema::ActiveTemplateInstantiation::isInstantiationRecord() const { + switch (Kind) { + case TemplateInstantiation: + case DefaultTemplateArgumentInstantiation: + case DefaultFunctionArgumentInstantiation: + return true; + + case ExplicitTemplateArgumentSubstitution: + case DeducedTemplateArgumentSubstitution: + case PriorTemplateArgumentSubstitution: + case DefaultTemplateArgumentChecking: + return false; + } + + return true; +} + Sema::InstantiatingTemplate:: InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Decl *Entity, @@ -104,7 +130,6 @@ InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, Inst.NumTemplateArgs = 0; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; } } @@ -128,7 +153,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; } } @@ -152,7 +176,9 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; + + if (!Inst.isInstantiationRecord()) + ++SemaRef.NonInstantiationEntries; } } @@ -164,48 +190,119 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, SourceRange InstantiationRange) : SemaRef(SemaRef) { - Invalid = CheckInstantiationDepth(PointOfInstantiation, - InstantiationRange); - if (!Invalid) { - ActiveTemplateInstantiation Inst; - Inst.Kind - = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; - Inst.PointOfInstantiation = PointOfInstantiation; - Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); - Inst.TemplateArgs = TemplateArgs; - Inst.NumTemplateArgs = NumTemplateArgs; - Inst.InstantiationRange = InstantiationRange; - SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; - } + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; } Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, - SourceLocation PointOfInstantation, + SourceLocation PointOfInstantiation, ParmVarDecl *Param, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceRange InstantiationRange) : SemaRef(SemaRef) { - Invalid = CheckInstantiationDepth(PointOfInstantation, InstantiationRange); + Invalid = CheckInstantiationDepth(PointOfInstantiation, InstantiationRange); if (!Invalid) { ActiveTemplateInstantiation Inst; Inst.Kind = ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation; - Inst.PointOfInstantiation = PointOfInstantation; + Inst.PointOfInstantiation = PointOfInstantiation; Inst.Entity = reinterpret_cast<uintptr_t>(Param); Inst.TemplateArgs = TemplateArgs; Inst.NumTemplateArgs = NumTemplateArgs; Inst.InstantiationRange = InstantiationRange; SemaRef.ActiveTemplateInstantiations.push_back(Inst); - Invalid = false; } } +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NonTypeTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) : SemaRef(SemaRef) { + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + TemplateTemplateParmDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) : SemaRef(SemaRef) { + Invalid = false; + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + +Sema::InstantiatingTemplate:: +InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + TemplateDecl *Template, + NamedDecl *Param, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceRange InstantiationRange) : SemaRef(SemaRef) { + Invalid = false; + + ActiveTemplateInstantiation Inst; + Inst.Kind = ActiveTemplateInstantiation::DefaultTemplateArgumentChecking; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Template = Template; + Inst.Entity = reinterpret_cast<uintptr_t>(Param); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + + assert(!Inst.isInstantiationRecord()); + ++SemaRef.NonInstantiationEntries; +} + void Sema::InstantiatingTemplate::Clear() { if (!Invalid) { + if (!SemaRef.ActiveTemplateInstantiations.back().isInstantiationRecord()) { + assert(SemaRef.NonInstantiationEntries > 0); + --SemaRef.NonInstantiationEntries; + } + SemaRef.ActiveTemplateInstantiations.pop_back(); Invalid = true; } @@ -214,8 +311,11 @@ void Sema::InstantiatingTemplate::Clear() { bool Sema::InstantiatingTemplate::CheckInstantiationDepth( SourceLocation PointOfInstantiation, SourceRange InstantiationRange) { - if (SemaRef.ActiveTemplateInstantiations.size() - <= SemaRef.getLangOptions().InstantiationDepth) + assert(SemaRef.NonInstantiationEntries <= + SemaRef.ActiveTemplateInstantiations.size()); + if ((SemaRef.ActiveTemplateInstantiations.size() - + SemaRef.NonInstantiationEntries) + <= SemaRef.getLangOptions().InstantiationDepth) return false; SemaRef.Diag(PointOfInstantiation, @@ -322,6 +422,34 @@ void Sema::PrintInstantiationStack() { break; } + case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: { + NamedDecl *Parm = cast<NamedDecl>((Decl *)Active->Entity); + std::string Name; + if (!Parm->getName().empty()) + Name = std::string(" '") + Parm->getName().str() + "'"; + + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_prior_template_arg_substitution) + << isa<TemplateTemplateParmDecl>(Parm) + << Name + << getTemplateArgumentBindingsText( + Active->Template->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } + + case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: { + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_template_default_arg_checking) + << getTemplateArgumentBindingsText( + Active->Template->getTemplateParameters(), + Active->TemplateArgs, + Active->NumTemplateArgs) + << Active->InstantiationRange; + break; + } } } } @@ -332,18 +460,20 @@ bool Sema::isSFINAEContext() const { Active = ActiveTemplateInstantiations.rbegin(), ActiveEnd = ActiveTemplateInstantiations.rend(); Active != ActiveEnd; - ++Active) { - + ++Active) + { switch(Active->Kind) { case ActiveTemplateInstantiation::TemplateInstantiation: case ActiveTemplateInstantiation::DefaultFunctionArgumentInstantiation: - // This is a template instantiation, so there is no SFINAE. return false; case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: - // A default template argument instantiation may or may not be a - // SFINAE context; look further up the stack. + case ActiveTemplateInstantiation::PriorTemplateArgumentSubstitution: + case ActiveTemplateInstantiation::DefaultTemplateArgumentChecking: + // A default template argument instantiation and substitution into + // template parameters with arguments for prior parameters may or may + // not be a SFINAE context; look further up the stack. break; case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: @@ -427,6 +557,9 @@ namespace { Sema::OwningExprResult TransformDeclRefExpr(DeclRefExpr *E, bool isAddressOfOperand); + Sema::OwningExprResult TransformCXXDefaultArgExpr(CXXDefaultArgExpr *E, + bool isAddressOfOperand); + /// \brief Transforms a template type parameter type by performing /// substitution of the corresponding template type argument. QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, @@ -440,10 +573,11 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) { if (TTP->getDepth() < TemplateArgs.getNumLevels()) { - assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() && + TemplateName Template + = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate(); + assert(!Template.isNull() && Template.getAsTemplateDecl() && "Wrong kind of template template argument"); - return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(), - TTP->getPosition()).getAsDecl()); + return Template.getAsTemplateDecl(); } // If the corresponding template argument is NULL or non-existent, it's @@ -454,9 +588,8 @@ Decl *TemplateInstantiator::TransformDecl(Decl *D) { TTP->getPosition())) return D; - // FIXME: Implement depth reduction of template template parameters - assert(false && - "Reducing depth of template template parameters is not yet implemented"); + // Fall through to find the instantiated declaration for this template + // template parameter. } return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs); @@ -567,7 +700,6 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { if (NTTP->getDepth() < TemplateArgs.getNumLevels()) { - // If the corresponding template argument is NULL or non-existent, it's // because we are performing instantiation from explicitly-specified // template arguments in a function template, but there were some @@ -592,7 +724,38 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!VD) return SemaRef.ExprError(); - return SemaRef.BuildDeclRefExpr(VD, VD->getType(), E->getLocation(), + if (VD->getDeclContext()->isRecord()) { + // If the value is a class member, we might have a pointer-to-member. + // Determine whether the non-type template template parameter is of + // pointer-to-member type. If so, we need to build an appropriate + // expression for a pointer-to-member, since a "normal" DeclRefExpr + // would refer to the member itself. + if (NTTP->getType()->isMemberPointerType()) { + QualType ClassType + = SemaRef.Context.getTypeDeclType( + cast<RecordDecl>(VD->getDeclContext())); + NestedNameSpecifier *Qualifier + = NestedNameSpecifier::Create(SemaRef.Context, 0, false, + ClassType.getTypePtr()); + CXXScopeSpec SS; + SS.setScopeRep(Qualifier); + OwningExprResult RefExpr + = SemaRef.BuildDeclRefExpr(VD, + VD->getType().getNonReferenceType(), + E->getLocation(), + /*FIXME:*/false, /*FIXME:*/false, + &SS); + if (RefExpr.isInvalid()) + return SemaRef.ExprError(); + + return SemaRef.CreateBuiltinUnaryOp(E->getLocation(), + UnaryOperator::AddrOf, + move(RefExpr)); + } + } + + return SemaRef.BuildDeclRefExpr(VD, VD->getType().getNonReferenceType(), + E->getLocation(), /*FIXME:*/false, /*FIXME:*/false); } @@ -625,10 +788,46 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!InstD) return SemaRef.ExprError(); - // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl, - // we need to get the underlying decl. - // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this? - InstD = InstD->getUnderlyingDecl(); + // Flatten using declarations into their shadow declarations. + if (isa<UsingDecl>(InstD)) { + UsingDecl *UD = cast<UsingDecl>(InstD); + + bool HasNonFunction = false; + + llvm::SmallVector<NamedDecl*, 8> Decls; + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) { + NamedDecl *TD = (*I)->getTargetDecl(); + if (!TD->isFunctionOrFunctionTemplate()) + HasNonFunction = true; + + Decls.push_back(TD); + } + + if (Decls.empty()) + return SemaRef.ExprError(); + + if (Decls.size() == 1) + InstD = Decls[0]; + else if (!HasNonFunction) { + OverloadedFunctionDecl *OFD + = OverloadedFunctionDecl::Create(SemaRef.Context, + UD->getDeclContext(), + UD->getDeclName()); + for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(), + E = Decls.end(); I != E; ++I) + if (isa<FunctionDecl>(*I)) + OFD->addOverload(cast<FunctionDecl>(*I)); + else + OFD->addOverload(cast<FunctionTemplateDecl>(*I)); + + InstD = OFD; + } else { + // FIXME + assert(false && "using declaration resolved to mixed set"); + return SemaRef.ExprError(); + } + } CXXScopeSpec SS; NestedNameSpecifier *Qualifier = 0; @@ -648,6 +847,15 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, isAddressOfOperand); } +Sema::OwningExprResult TemplateInstantiator::TransformCXXDefaultArgExpr( + CXXDefaultArgExpr *E, bool isAddressOfOperand) { + assert(!cast<FunctionDecl>(E->getParam()->getDeclContext())-> + getDescribedFunctionTemplate() && + "Default arg expressions are never formed in dependent cases."); + return SemaRef.Owned(E->Retain()); +} + + QualType TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, TemplateTypeParmTypeLoc TL) { @@ -889,9 +1097,9 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Member != MemberEnd; ++Member) { Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs); if (NewMember) { - if (NewMember->isInvalidDecl()) + if (NewMember->isInvalidDecl()) { Invalid = true; - else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) + } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember)) Fields.push_back(DeclPtrTy::make(Field)); else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember)) Instantiation->addDecl(UD); |