aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaExpr.cpp28
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);
}