summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2018-01-02 23:52:42 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2018-01-02 23:52:42 +0000
commit50e291eaf28383e8b9c061dedc3aa0acb9d0c9e6 (patch)
tree227ed404063ea5ef3ba4a45a8610ebdf8053c03e /clang/lib/Sema/SemaDeclCXX.cpp
parent96625fdc6bff9f9bbf96239860a501778623b680 (diff)
downloadbcm5719-llvm-50e291eaf28383e8b9c061dedc3aa0acb9d0c9e6.tar.gz
bcm5719-llvm-50e291eaf28383e8b9c061dedc3aa0acb9d0c9e6.zip
Fix and simplify handling of return type for (generic) lambda conversion function to function pointer.
Previously, we would: * compute the type of the conversion function and static invoker as a side-effect of template argument deduction for a conversion * re-compute the type as part of deduced return type deduction when building the conversion function itself Neither of these turns out to be quite correct. There are other ways to reach a declaration of the conversion function than in a conversion (such as an explicit call or friend declaration), and performing auto deduction causes the function type to be rebuilt in the context of the lambda closure type (which is different from the context in which it originally appeared, resulting in spurious substitution failures for constructs that are valid in one context but not the other, such as the use of an enclosing class's "this" pointer). This patch switches us to use a different strategy: as before, we use the declared type of the operator() to form the type of the conversion function and invoker, but we now populate that type as part of return type deduction for the conversion function. And the invoker is now treated as simply being an implementation detail of building the conversion function, and isn't given special treatment by template argument deduction for the conversion function any more. llvm-svn: 321683
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp70
1 files changed, 26 insertions, 44 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index ceded02e394..5e24649c71b 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -12215,30 +12215,27 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
SourceLocation CurrentLocation,
CXXConversionDecl *Conv) {
SynthesizedFunctionScope Scope(*this, Conv);
+ assert(!Conv->getReturnType()->isUndeducedType());
CXXRecordDecl *Lambda = Conv->getParent();
- CXXMethodDecl *CallOp = Lambda->getLambdaCallOperator();
- // If we are defining a specialization of a conversion to function-ptr
- // cache the deduced template arguments for this specialization
- // so that we can use them to retrieve the corresponding call-operator
- // and static-invoker.
- const TemplateArgumentList *DeducedTemplateArgs = nullptr;
-
- // Retrieve the corresponding call-operator specialization.
- if (Lambda->isGenericLambda()) {
- assert(Conv->isFunctionTemplateSpecialization());
- FunctionTemplateDecl *CallOpTemplate =
- CallOp->getDescribedFunctionTemplate();
- DeducedTemplateArgs = Conv->getTemplateSpecializationArgs();
- void *InsertPos = nullptr;
- FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(CallOpSpec &&
- "Conversion operator must have a corresponding call operator");
- CallOp = cast<CXXMethodDecl>(CallOpSpec);
+ FunctionDecl *CallOp = Lambda->getLambdaCallOperator();
+ FunctionDecl *Invoker = Lambda->getLambdaStaticInvoker();
+
+ if (auto *TemplateArgs = Conv->getTemplateSpecializationArgs()) {
+ CallOp = InstantiateFunctionDeclaration(
+ CallOp->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!CallOp)
+ return;
+
+ Invoker = InstantiateFunctionDeclaration(
+ Invoker->getDescribedFunctionTemplate(), TemplateArgs, CurrentLocation);
+ if (!Invoker)
+ return;
}
+ if (CallOp->isInvalidDecl())
+ return;
+
// Mark the call operator referenced (and add to pending instantiations
// if necessary).
// For both the conversion and static-invoker template specializations
@@ -12246,39 +12243,24 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion(
// to the PendingInstantiations.
MarkFunctionReferenced(CurrentLocation, CallOp);
- // Retrieve the static invoker...
- CXXMethodDecl *Invoker = Lambda->getLambdaStaticInvoker();
- // ... and get the corresponding specialization for a generic lambda.
- if (Lambda->isGenericLambda()) {
- assert(DeducedTemplateArgs &&
- "Must have deduced template arguments from Conversion Operator");
- FunctionTemplateDecl *InvokeTemplate =
- Invoker->getDescribedFunctionTemplate();
- void *InsertPos = nullptr;
- FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization(
- DeducedTemplateArgs->asArray(),
- InsertPos);
- assert(InvokeSpec &&
- "Must have a corresponding static invoker specialization");
- Invoker = cast<CXXMethodDecl>(InvokeSpec);
- }
+ // Fill in the __invoke function with a dummy implementation. IR generation
+ // will fill in the actual details. Update its type in case it contained
+ // an 'auto'.
+ Invoker->markUsed(Context);
+ Invoker->setReferenced();
+ Invoker->setType(Conv->getReturnType()->getPointeeType());
+ Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
+
// Construct the body of the conversion function { return __invoke; }.
Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(),
- VK_LValue, Conv->getLocation()).get();
+ VK_LValue, Conv->getLocation()).get();
assert(FunctionRef && "Can't refer to __invoke function?");
Stmt *Return = BuildReturnStmt(Conv->getLocation(), FunctionRef).get();
Conv->setBody(CompoundStmt::Create(Context, Return, Conv->getLocation(),
Conv->getLocation()));
-
Conv->markUsed(Context);
Conv->setReferenced();
- // Fill in the __invoke function with a dummy implementation. IR generation
- // will fill in the actual details.
- Invoker->markUsed(Context);
- Invoker->setReferenced();
- Invoker->setBody(new (Context) CompoundStmt(Conv->getLocation()));
-
if (ASTMutationListener *L = getASTMutationListener()) {
L->CompletedImplicitDefinition(Conv);
L->CompletedImplicitDefinition(Invoker);
OpenPOWER on IntegriCloud