erichkeane updated this revision to Diff 298666.
erichkeane marked an inline comment as done.
erichkeane added a comment.
Calc->get.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D89559/new/
https://reviews.llvm.org/D89559
Files:
clang/lib/Sema/SemaLambda.cpp
clang/test/SemaCXX/lambda-conversion-op-cc.cpp
Index: clang/test/SemaCXX/lambda-conversion-op-cc.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/lambda-conversion-op-cc.cpp
@@ -0,0 +1,79 @@
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-pc %s -verify -DBAD_CONVERSION
+// RUN: %clang_cc1 -fsyntax-only -triple i386-windows-pc %s -verify -DBAD_CONVERSION -DWIN32
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-pc %s -ast-dump | FileCheck %s --check-prefixes=CHECK,LIN64,NODEF
+// RUN: %clang_cc1 -fsyntax-only -triple i386-windows-pc %s -ast-dump -DWIN32 | FileCheck %s --check-prefixes=CHECK,WIN32,NODEF
+
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-pc -fdefault-calling-conv=vectorcall %s -verify -DBAD_VEC_CONVERS
+// RUN: %clang_cc1 -fsyntax-only -triple x86_64-linux-pc -fdefault-calling-conv=vectorcall %s -ast-dump | FileCheck %s --check-prefixes=CHECK,VECTDEF
+
+void useage() {
+ auto normal = [](int, float, double){}; // #1
+ auto vectorcall = [](int, float, double) __attribute__((vectorcall)) {}; // #2
+#ifdef WIN32
+ auto thiscall = [](int, float, double) __attribute__((thiscall)) {}; // #3
+#endif // WIN32
+ auto cdecl = [](int, float, double) __attribute__((cdecl)) {};
+
+// CHECK: VarDecl {{.*}} normal '
+// CHECK: LambdaExpr
+// WIN32: CXXMethodDecl {{.*}} operator() 'void (int, float, double) __attribute__((thiscall)) const'
+// LIN64: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const'
+// VECTDEF: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const'
+// NODEF: CXXConversionDecl {{.*}} operator void (*)(int, float, double) 'void
+// NODEF: CXXMethodDecl {{.*}} __invoke 'void (int, float, double)' static inline
+// VECTDEF: CXXConversionDecl {{.*}} operator void (*)(int, float, double) __attribute__((vectorcall)) 'void
+// VECTDEF: CXXMethodDecl {{.*}} __invoke 'void (int, float, double) __attribute__((vectorcall))' static inline
+
+// CHECK: VarDecl {{.*}} vectorcall '
+// CHECK: LambdaExpr
+// CHECK: CXXMethodDecl {{.*}} operator() 'void (int, float, double) __attribute__((vectorcall)) const'
+// CHECK: CXXConversionDecl {{.*}} operator void (*)(int, float, double) __attribute__((vectorcall)) 'void
+// CHECK: CXXMethodDecl {{.*}} __invoke 'void (int, float, double) __attribute__((vectorcall))' static inline
+
+// WIN32: VarDecl {{.*}} thiscall '
+// WIN32: LambdaExpr
+// WIN32: CXXMethodDecl {{.*}} operator() 'void (int, float, double) __attribute__((thiscall)) const'
+// WIN32: CXXConversionDecl {{.*}} operator void (*)(int, float, double) 'void
+// WIN32: CXXMethodDecl {{.*}} __invoke 'void (int, float, double)' static inline
+
+// CHECK: VarDecl {{.*}} cdecl '
+// CHECK: LambdaExpr
+// CHECK: CXXMethodDecl {{.*}} operator() 'void (int, float, double) const'
+// NODEF: CXXConversionDecl {{.*}} operator void (*)(int, float, double) 'void
+// NODEF: CXXMethodDecl {{.*}} __invoke 'void (int, float, double)' static inline
+// VECTDEF: CXXConversionDecl {{.*}} operator void (*)(int, float, double) __attribute__((vectorcall)) 'void
+// VECTDEF: CXXMethodDecl {{.*}} __invoke 'void (int, float, double) __attribute__((vectorcall))' static inline
+
+#ifdef BAD_CONVERSION
+ // expected-error-re@+2 {{no viable conversion from {{.*}} to 'void (*)(int, float, double) __attribute__((vectorcall))}}
+ // expected-note@#1 {{candidate function}}
+ void (*__attribute__((vectorcall)) normal_ptr2)(int, float, double) = normal;
+ // expected-error-re@+2 {{no viable conversion from {{.*}} to 'void (*)(int, float, double)}}
+ // expected-note@#2 {{candidate function}}
+ void (*vectorcall_ptr2)(int, float, double) = vectorcall;
+#ifdef WIN32
+ // expected-error-re@+2 {{no viable conversion from {{.*}} to 'void (*)(int, float, double) __attribute__((thiscall))}}
+ // expected-note@#3 {{candidate function}}
+ void (*__attribute__((thiscall)) thiscall_ptr2)(int, float, double) = thiscall;
+#endif // WIN32
+#endif // BAD_CONVERSION
+
+#ifdef BAD_VEC_CONVERS
+ void (*__attribute__((vectorcall)) normal_ptr2)(int, float, double) = normal;
+ void (* normal_ptr3)(int, float, double) = normal;
+ // expected-error-re@+2 {{no viable conversion from {{.*}} to 'void (*)(int, float, double) __attribute__((regcall))}}
+ // expected-note@#1 {{candidate function}}
+ void (*__attribute__((regcall)) normalptr4)(int, float, double) = normal;
+ void (*__attribute__((vectorcall)) vectorcall_ptr2)(int, float, double) = vectorcall;
+ void (* vectorcall_ptr3)(int, float, double) = vectorcall;
+#endif // BAD_VEC_CONVERS
+
+ // Required to force emission of the invoker.
+ void (*normal_ptr)(int, float, double) = normal;
+ void (*__attribute__((vectorcall)) vectorcall_ptr)(int, float, double) = vectorcall;
+#ifdef WIN32
+ void (*thiscall_ptr)(int, float, double) = thiscall;
+#endif // WIN32
+ void (*cdecl_ptr)(int, float, double) = cdecl;
+
+}
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -1263,20 +1263,36 @@
PopFunctionScopeInfo();
}
+static CallingConv
+getLambdaConversionFunctionCallConv(Sema &S,
+ const FunctionProtoType *CallOpProto) {
+ CallingConv DefaultFree = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
+ CallingConv DefaultMember = S.Context.getDefaultCallingConvention(
+ CallOpProto->isVariadic(), /*IsCXXMethod=*/true);
+ CallingConv CallOpCC = CallOpProto->getCallConv();
+
+ // If the call-operator hasn't been changed, convert the return-type to the
+ // 'free' function calling convention.
+ if (CallOpCC == DefaultMember)
+ return DefaultFree;
+ return CallOpCC;
+}
+
QualType Sema::getLambdaConversionFunctionResultType(
const FunctionProtoType *CallOpProto) {
// The function type inside the pointer type is the same as the call
- // operator with some tweaks. The calling convention is the default free
- // function convention, and the type qualifications are lost.
+ // operator with some tweaks. The calling convention should match the call
+ // operator if it has been manually altered, and match the default free
+ // function convention if not. Type qualifications are lost.
const FunctionProtoType::ExtProtoInfo CallOpExtInfo =
CallOpProto->getExtProtoInfo();
FunctionProtoType::ExtProtoInfo InvokerExtInfo = CallOpExtInfo;
- CallingConv CC = Context.getDefaultCallingConvention(
- CallOpProto->isVariadic(), /*IsCXXMethod=*/false);
+ CallingConv CC = getLambdaConversionFunctionCallConv(*this, CallOpProto);
InvokerExtInfo.ExtInfo = InvokerExtInfo.ExtInfo.withCallingConv(CC);
InvokerExtInfo.TypeQuals = Qualifiers();
assert(InvokerExtInfo.RefQualifier == RQ_None &&
- "Lambda's call operator should not have a reference qualifier");
+ "Lambda's call operator should not have a reference qualifier");
return Context.getFunctionType(CallOpProto->getReturnType(),
CallOpProto->getParamTypes(), InvokerExtInfo);
}
@@ -1296,8 +1312,10 @@
return;
// Add the conversion to function pointer.
- QualType InvokerFunctionTy = S.getLambdaConversionFunctionResultType(
- CallOperator->getType()->castAs<FunctionProtoType>());
+ const FunctionProtoType *CallOpProto =
+ CallOperator->getType()->castAs<FunctionProtoType>();
+ QualType InvokerFunctionTy =
+ S.getLambdaConversionFunctionResultType(CallOpProto);
QualType PtrToFunctionTy = S.Context.getPointerType(InvokerFunctionTy);
// Create the type of the conversion function.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits