diff options
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 111 |
1 files changed, 73 insertions, 38 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 6e1751aebd9..4aa53e0a8e8 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10351,57 +10351,92 @@ bool Sema::isImplicitlyDeleted(FunctionDecl *FD) { return FD->isDeleted() && FD->isDefaulted() && isa<CXXMethodDecl>(FD); } -/// \brief Mark the call operator of the given lambda closure type as "used". -static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { - CXXMethodDecl *CallOperator - = cast<CXXMethodDecl>( - Lambda->lookup( - S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); - CallOperator->setReferenced(); - CallOperator->markUsed(S.Context); -} - void Sema::DefineImplicitLambdaToFunctionPointerConversion( - SourceLocation CurrentLocation, - CXXConversionDecl *Conv) -{ - CXXRecordDecl *LambdaClass = Conv->getParent(); - - // Make sure that the lambda call operator is marked used. - markLambdaCallOperatorUsed(*this, LambdaClass); - - Conv->markUsed(Context); + SourceLocation CurrentLocation, + CXXConversionDecl *Conv) { + 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 = 0; + + // Retrieve the corresponding call-operator specialization. + if (Lambda->isGenericLambda()) { + assert(Conv->isFunctionTemplateSpecialization()); + FunctionTemplateDecl *CallOpTemplate = + CallOp->getDescribedFunctionTemplate(); + DeducedTemplateArgs = Conv->getTemplateSpecializationArgs(); + void *InsertPos = 0; + FunctionDecl *CallOpSpec = CallOpTemplate->findSpecialization( + DeducedTemplateArgs->data(), + DeducedTemplateArgs->size(), + InsertPos); + assert(CallOpSpec && + "Conversion operator must have a corresponding call operator"); + CallOp = cast<CXXMethodDecl>(CallOpSpec); + } + // Mark the call operator referenced (and add to pending instantiations + // if necessary). + // For both the conversion and static-invoker template specializations + // we construct their body's in this function, so no need to add them + // to the PendingInstantiations. + MarkFunctionReferenced(CurrentLocation, CallOp); + SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); + + // Retreive 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 = 0; + FunctionDecl *InvokeSpec = InvokeTemplate->findSpecialization( + DeducedTemplateArgs->data(), + DeducedTemplateArgs->size(), + InsertPos); + assert(InvokeSpec && + "Must have a corresponding static invoker specialization"); + Invoker = cast<CXXMethodDecl>(InvokeSpec); + } + // Construct the body of the conversion function { return __invoke; }. + Expr *FunctionRef = BuildDeclRefExpr(Invoker, Invoker->getType(), + VK_LValue, Conv->getLocation()).take(); + assert(FunctionRef && "Can't refer to __invoke function?"); + Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); + Conv->setBody(new (Context) CompoundStmt(Context, Return, + Conv->getLocation(), + Conv->getLocation())); + + Conv->markUsed(Context); + Conv->setReferenced(); - // Return the address of the __invoke function. - - CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker(); - Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(), - VK_LValue, Conv->getLocation()).take(); - assert(FunctionRef && "Can't refer to lambda static invoker function?"); - Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take(); - Conv->setBody(new (Context) CompoundStmt(Context, Return, - Conv->getLocation(), - Conv->getLocation())); - - // Fill in the static invoker function with a dummy implementation. - // IR generation will fill in the actual details. - Invoke->markUsed(Context); - Invoke->setReferenced(); - Invoke->setBody(new (Context) CompoundStmt(Conv->getLocation())); - + // 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(Invoke); - } + L->CompletedImplicitDefinition(Invoker); + } } + + void Sema::DefineImplicitLambdaToBlockPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { + assert(!Conv->getParent()->isGenericLambda());
+ Conv->markUsed(Context); SynthesizedFunctionScope Scope(*this, Conv); |