diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 28 |
1 files changed, 19 insertions, 9 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 371a4e39eb..050386e299 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9404,7 +9404,11 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { Func->setReferenced(); - if (Func->isUsed(false)) + // Don't mark this function as used multiple times, unless it's a constexpr + // function which we need to instantiate. + if (Func->isUsed(false) && + !(Func->isConstexpr() && !Func->getBody() && + Func->isImplicitlyInstantiable())) return; if (!IsPotentiallyEvaluatedContext(*this)) @@ -9455,34 +9459,40 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { // class templates. if (Func->isImplicitlyInstantiable()) { bool AlreadyInstantiated = false; + SourceLocation PointOfInstantiation = Loc; if (FunctionTemplateSpecializationInfo *SpecInfo = Func->getTemplateSpecializationInfo()) { if (SpecInfo->getPointOfInstantiation().isInvalid()) SpecInfo->setPointOfInstantiation(Loc); else if (SpecInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) + == TSK_ImplicitInstantiation) { AlreadyInstantiated = true; + PointOfInstantiation = SpecInfo->getPointOfInstantiation(); + } } else if (MemberSpecializationInfo *MSInfo = Func->getMemberSpecializationInfo()) { if (MSInfo->getPointOfInstantiation().isInvalid()) MSInfo->setPointOfInstantiation(Loc); else if (MSInfo->getTemplateSpecializationKind() - == TSK_ImplicitInstantiation) + == TSK_ImplicitInstantiation) { AlreadyInstantiated = true; + PointOfInstantiation = MSInfo->getPointOfInstantiation(); + } } - if (!AlreadyInstantiated) { + if (!AlreadyInstantiated || Func->isConstexpr()) { if (isa<CXXRecordDecl>(Func->getDeclContext()) && cast<CXXRecordDecl>(Func->getDeclContext())->isLocalClass()) - PendingLocalImplicitInstantiations.push_back(std::make_pair(Func, - Loc)); - else if (Func->getTemplateInstantiationPattern()->isConstexpr()) + PendingLocalImplicitInstantiations.push_back( + std::make_pair(Func, PointOfInstantiation)); + else if (Func->isConstexpr()) // Do not defer instantiations of constexpr functions, to avoid the // expression evaluator needing to call back into Sema if it sees a // call to such a function. - InstantiateFunctionDefinition(Loc, Func); + InstantiateFunctionDefinition(PointOfInstantiation, Func); else { - PendingInstantiations.push_back(std::make_pair(Func, Loc)); + PendingInstantiations.push_back(std::make_pair(Func, + PointOfInstantiation)); // Notify the consumer that a function was implicitly instantiated. Consumer.HandleCXXImplicitFunctionInstantiation(Func); } |