return TDK_Success;
}
-/// \brief Given a function declaration (e.g. a generic lambda conversion \r
-/// function) that contains an 'auto' in its result type, substitute it \r
-/// with the same Deduced type that the TypeToReplaceAutoWith was deduced \r
-/// with.\r
+/// \brief Given a function declaration (e.g. a generic lambda conversion
+/// function) that contains an 'auto' in its result type, substitute it
+/// with the same Deduced type that the TypeToReplaceAutoWith was deduced
+/// with.
static inline void
ReplaceAutoWithinFunctionReturnType(FunctionDecl *F,
QualType TypeToReplaceAutoWith, Sema &S) {
TypeToReplaceAutoWith = TypeToReplaceAutoWith->
getContainedAutoType()->getDeducedType();
- QualType AutoResultType = F->getResultType();\r
- assert(AutoResultType->getContainedAutoType()); \r
- QualType DeducedResultType = S.SubstAutoType(AutoResultType, \r
+ QualType AutoResultType = F->getResultType();
+ assert(AutoResultType->getContainedAutoType());
+ QualType DeducedResultType = S.SubstAutoType(AutoResultType,
TypeToReplaceAutoWith);
S.Context.adjustDeducedFunctionResultType(F, DeducedResultType);
}
= DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
P, A, Info, Deduced, TDF))
return Result;
-\r
- // Create an Instantiation Scope for finalizing the operator.\r
- LocalInstantiationScope InstScope(*this);\r
- \r
- CXXMethodDecl *LambdaCallOpSpec = 0;\r
+
+ // Create an Instantiation Scope for finalizing the operator.
+ LocalInstantiationScope InstScope(*this);
+
+ CXXMethodDecl *LambdaCallOpSpec = 0;
bool GenericLambdaCallOperatorHasDeducedReturnType = false;
- \r
- // Having successfully deduced and matched the type of the conversion\r
- // function against the destination type, if the destination type\r
- // is a ptr-to-function and the source type is a generic lambda conversion\r
- // to ptr-to-function, we know that the parameters of the destination \r
- // ptr-to-function have matched successfully against those of our \r
- // lambda's conversion function. \r
- // For instance:\r
- // int (*fp)(int) = [](auto a) { return a; };\r
- // [template<class T> operator id<auto(*)(T)>() const]\r
- // If it is indeed the conversion operator of a generic lambda then if\r
- // not already done, create the corresponding specializations of the call \r
- // operator and the static-invoker; and if the return type is auto, \r
- // deduce the return type, and then check and see if it matches the ToType.\r
-\r
- const bool IsGenericLambdaConversionOperator = \r
- isLambdaConversionOperator(Conv);\r
- if (IsGenericLambdaConversionOperator) {\r
- const Type *FromTypePtr = P.getTypePtr();\r
- const Type *ToTypePtr = A.getTypePtr();\r
-\r
- assert(P->isPointerType()); \r
- FromTypePtr = P->getPointeeType().getTypePtr();\r
- assert(A->isPointerType());\r
- ToTypePtr = A->getPointeeType().getTypePtr();\r
- \r
- CXXRecordDecl *LambdaClass = Conv->getParent();\r
- assert(LambdaClass && LambdaClass->isGenericLambda()); \r
-\r
- const FunctionType *ToFunType = ToTypePtr->getAs<FunctionType>();\r
-\r
- // The specialization of the Generic Lambda Call Op, instantiated\r
- // using the deduced parameters from the conversion function\r
- // i.e.\r
- // auto L = [](auto a) { return f(a); };\r
- // int (*fp)(int) = L;\r
- //\r
-\r
- CXXMethodDecl *CallOp = LambdaClass->getLambdaCallOperator();\r
- QualType CallOpResultType = CallOp->getResultType(); \r
- GenericLambdaCallOperatorHasDeducedReturnType = \r
- CallOpResultType->getContainedAutoType();\r
- FunctionTemplateDecl *CallOpTemplate = \r
- CallOp->getDescribedFunctionTemplate();\r
-\r
- TemplateDeductionInfo OpInfo(Info.getLocation()); \r
- FunctionDecl *CallOpSpec = 0;\r
- // Use the deduced arguments so far, to specialize our generic\r
- // lambda's call operator.\r
- if (TemplateDeductionResult Result\r
- = FinishTemplateArgumentDeduction(CallOpTemplate, Deduced, \r
- 0, CallOpSpec, OpInfo))\r
- return Result;\r
- \r
- bool HadToDeduceReturnTypeDuringCurrentCall = false;\r
- // If we need to deduce the return type, do so (instantiates the callop).\r
- if (GenericLambdaCallOperatorHasDeducedReturnType && \r
- CallOpSpec->getResultType()->isUndeducedType()) {\r
- HadToDeduceReturnTypeDuringCurrentCall = true;\r
- DeduceReturnType(CallOpSpec, CallOpSpec->getPointOfInstantiation(),\r
- /*Diagnose*/ true);\r
- }\r
- \r
- LambdaCallOpSpec = cast<CXXMethodDecl>(CallOpSpec);\r
- \r
- // Check to see if the return type of the destination ptr-to-function\r
- // matches the return type of the call operator.\r
- if (!Context.hasSameType(LambdaCallOpSpec->getResultType(), \r
- ToFunType->getResultType()))\r
- return TDK_NonDeducedMismatch;\r
- // Since we have succeeded in matching the source and destination\r
- // ptr-to-functions (now including return type), and have successfully \r
- // specialized our corresponding call operator, we are ready to\r
- // specialize the static invoker with the deduced arguments of our\r
- // ptr-to-function.\r
- FunctionDecl *InvokerSpecialization = 0;\r
- FunctionTemplateDecl *InvokerTemplate = LambdaClass->\r
- getLambdaStaticInvoker()->getDescribedFunctionTemplate();\r
-\r
- TemplateDeductionResult Result\r
- = FinishTemplateArgumentDeduction(InvokerTemplate, Deduced, 0, \r
- InvokerSpecialization, Info);\r
- assert(Result == TDK_Success);\r
- // Set the result type to match the corresponding call operator\r
- // specialization's result type.\r
- if (GenericLambdaCallOperatorHasDeducedReturnType && \r
- InvokerSpecialization->getResultType()->isUndeducedType())\r
- ReplaceAutoWithinFunctionReturnType(InvokerSpecialization,\r
- LambdaCallOpSpec->getResultType(), *this);\r
+
+ // Having successfully deduced and matched the type of the conversion
+ // function against the destination type, if the destination type
+ // is a ptr-to-function and the source type is a generic lambda conversion
+ // to ptr-to-function, we know that the parameters of the destination
+ // ptr-to-function have matched successfully against those of our
+ // lambda's conversion function.
+ // For instance:
+ // int (*fp)(int) = [](auto a) { return a; };
+ // [template<class T> operator id<auto(*)(T)>() const]
+ // If it is indeed the conversion operator of a generic lambda then if
+ // not already done, create the corresponding specializations of the call
+ // operator and the static-invoker; and if the return type is auto,
+ // deduce the return type, and then check and see if it matches the ToType.
+
+ const bool IsGenericLambdaConversionOperator =
+ isLambdaConversionOperator(Conv);
+ if (IsGenericLambdaConversionOperator) {
+ const Type *FromTypePtr = P.getTypePtr();
+ const Type *ToTypePtr = A.getTypePtr();
+
+ assert(P->isPointerType());
+ FromTypePtr = P->getPointeeType().getTypePtr();
+ assert(A->isPointerType());
+ ToTypePtr = A->getPointeeType().getTypePtr();
+
+ CXXRecordDecl *LambdaClass = Conv->getParent();
+ assert(LambdaClass && LambdaClass->isGenericLambda());
+
+ const FunctionType *ToFunType = ToTypePtr->getAs<FunctionType>();
+
+ // The specialization of the Generic Lambda Call Op, instantiated
+ // using the deduced parameters from the conversion function
+ // i.e.
+ // auto L = [](auto a) { return f(a); };
+ // int (*fp)(int) = L;
+ //
+
+ CXXMethodDecl *CallOp = LambdaClass->getLambdaCallOperator();
+ QualType CallOpResultType = CallOp->getResultType();
+ GenericLambdaCallOperatorHasDeducedReturnType =
+ CallOpResultType->getContainedAutoType();
+ FunctionTemplateDecl *CallOpTemplate =
+ CallOp->getDescribedFunctionTemplate();
+
+ TemplateDeductionInfo OpInfo(Info.getLocation());
+ FunctionDecl *CallOpSpec = 0;
+ // Use the deduced arguments so far, to specialize our generic
+ // lambda's call operator.
+ if (TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(CallOpTemplate, Deduced,
+ 0, CallOpSpec, OpInfo))
+ return Result;
+
+ bool HadToDeduceReturnTypeDuringCurrentCall = false;
+ // If we need to deduce the return type, do so (instantiates the callop).
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ CallOpSpec->getResultType()->isUndeducedType()) {
+ HadToDeduceReturnTypeDuringCurrentCall = true;
+ DeduceReturnType(CallOpSpec, CallOpSpec->getPointOfInstantiation(),
+ /*Diagnose*/ true);
+ }
+
+ LambdaCallOpSpec = cast<CXXMethodDecl>(CallOpSpec);
+
+ // Check to see if the return type of the destination ptr-to-function
+ // matches the return type of the call operator.
+ if (!Context.hasSameType(LambdaCallOpSpec->getResultType(),
+ ToFunType->getResultType()))
+ return TDK_NonDeducedMismatch;
+ // Since we have succeeded in matching the source and destination
+ // ptr-to-functions (now including return type), and have successfully
+ // specialized our corresponding call operator, we are ready to
+ // specialize the static invoker with the deduced arguments of our
+ // ptr-to-function.
+ FunctionDecl *InvokerSpecialization = 0;
+ FunctionTemplateDecl *InvokerTemplate = LambdaClass->
+ getLambdaStaticInvoker()->getDescribedFunctionTemplate();
+
+ TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(InvokerTemplate, Deduced, 0,
+ InvokerSpecialization, Info);
+ assert(Result == TDK_Success);
+ // Set the result type to match the corresponding call operator
+ // specialization's result type.
+ if (GenericLambdaCallOperatorHasDeducedReturnType &&
+ InvokerSpecialization->getResultType()->isUndeducedType())
+ ReplaceAutoWithinFunctionReturnType(InvokerSpecialization,
+ LambdaCallOpSpec->getResultType(), *this);
// Ensure that static invoker doesn't have a const qualifier.
// FIXME: When creating the InvokerTemplate in SemaLambda.cpp
FunctionProtoType::ExtProtoInfo EPI = InvokerFPT->getExtProtoInfo();
EPI.TypeQuals = 0;
InvokerSpecialization->setType(Context.getFunctionType(
- InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI));\r
- \r
- // Since the original conversion operator's parameters are the same \r
- // entities as the lambda's call operator's, we introduce a mapping\r
- // from the generic to the specialized parameters of the call operators.\r
- // This only needs to be done in the absence of return type deduction,\r
- // since deducing the return type entails instantiation which adds\r
- // the parameter mapping to the CurrentInstantiationScope. \r
- // This is necessary when transforming nested lambdas that do not\r
- // capture.\r
- // FIXME: This will be fixed once nested lambdas and capturing\r
- // is implemented since it does require handling parameter \r
- // packs correctly which might require careful calls to\r
- // SemaTemplateInstantiate::addInstantiatedParametersToScope.\r
+ InvokerFPT->getResultType(), InvokerFPT->getArgTypes(),EPI));
+
+ // Since the original conversion operator's parameters are the same
+ // entities as the lambda's call operator's, we introduce a mapping
+ // from the generic to the specialized parameters of the call operators.
+ // This only needs to be done in the absence of return type deduction,
+ // since deducing the return type entails instantiation which adds
+ // the parameter mapping to the CurrentInstantiationScope.
+ // This is necessary when transforming nested lambdas that do not
+ // capture.
+ // FIXME: This will be fixed once nested lambdas and capturing
+ // is implemented since it does require handling parameter
+ // packs correctly which might require careful calls to
+ // SemaTemplateInstantiate::addInstantiatedParametersToScope.
// if (!HadToDeduceReturnTypeDuringCurrentCall) { ... }
}
- \r
- \r
+
+
// Finish template argument deduction.
- FunctionDecl *ConversionSpec = 0;\r
- TemplateDeductionResult Result\r
- = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0, \r
- ConversionSpec, Info);\r
- Specialization = cast_or_null<CXXConversionDecl>(ConversionSpec);\r
- if (Result == TDK_Success && GenericLambdaCallOperatorHasDeducedReturnType) {\r
- // Set the return type of the conversion specialization, since even \r
- // though we have ensured that the return types are compatible, if \r
- // there is an auto in the return type of this conversion function, \r
- // replace it permanently with the return type of the deduced lambda\r
- // so we don't try and deduce against it.\r
- assert(LambdaCallOpSpec);\r
- if (ConversionSpec->getResultType()->isUndeducedType())\r
- ReplaceAutoWithinFunctionReturnType(ConversionSpec, \r
- LambdaCallOpSpec->getResultType(),\r
- *this);\r
+ FunctionDecl *ConversionSpec = 0;
+ TemplateDeductionResult Result
+ = FinishTemplateArgumentDeduction(ConversionTemplate, Deduced, 0,
+ ConversionSpec, Info);
+ Specialization = cast_or_null<CXXConversionDecl>(ConversionSpec);
+ if (Result == TDK_Success && GenericLambdaCallOperatorHasDeducedReturnType) {
+ // Set the return type of the conversion specialization, since even
+ // though we have ensured that the return types are compatible, if
+ // there is an auto in the return type of this conversion function,
+ // replace it permanently with the return type of the deduced lambda
+ // so we don't try and deduce against it.
+ assert(LambdaCallOpSpec);
+ if (ConversionSpec->getResultType()->isUndeducedType())
+ ReplaceAutoWithinFunctionReturnType(ConversionSpec,
+ LambdaCallOpSpec->getResultType(),
+ *this);
}
return Result;
}