Introduce _Complex conversions into the function overloading
system. Since C99 doesn't have overloading and C++ doesn't have
_Complex, there is no specification for this. Here's what I think
makes sense.
Complex conversions come in several flavors:
- Complex promotions: a complex -> complex conversion where the
underlying real-type conversion is a floating-point promotion. GCC
seems to call this a promotion, EDG does something else. This is
given "promotion" rank for determining the best viable function.
- Complex conversions: a complex -> complex conversion that is
not a complex promotion. This is given "conversion" rank for
determining the best viable function.
- Complex-real conversions: a real -> complex or complex -> real
conversion. This is given "conversion" rank for determining the
best viable function.
These rules are the same for C99 (when using the "overloadable"
attribute) and C++. However, there is one difference in the handling
of floating-point promotions: in C99, float -> long double and double
-> long double are considered promotions (so we give them "promotion"
rank), while C++ considers these conversions ("conversion" rank).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64343 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/SemaCXX/complex-overload.cpp b/test/SemaCXX/complex-overload.cpp
new file mode 100644
index 0000000..4d27a20
--- /dev/null
+++ b/test/SemaCXX/complex-overload.cpp
@@ -0,0 +1,43 @@
+// RUN: clang -fsyntax-only -verify %s
+char *foo(float); // expected-note 3 {{candidate function}}
+
+void test_foo_1(float fv, double dv, float _Complex fc, double _Complex dc) {
+ char *cp1 = foo(fv);
+ char *cp2 = foo(dv);
+ // Note: GCC and EDG reject these two, but they are valid C99 conversions
+ char *cp3 = foo(fc);
+ char *cp4 = foo(dc);
+}
+
+int *foo(float _Complex); // expected-note 3 {{candidate function}}
+
+void test_foo_2(float fv, double dv, float _Complex fc, double _Complex dc) {
+ char *cp1 = foo(fv);
+ char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}}
+ int *ip = foo(fc);
+ int *lp = foo(dc); // expected-error{{call to 'foo' is ambiguous; candidates are:}}
+}
+
+long *foo(double _Complex); // expected-note {{candidate function}}
+
+void test_foo_3(float fv, double dv, float _Complex fc, double _Complex dc) {
+ char *cp1 = foo(fv);
+ char *cp2 = foo(dv); // expected-error{{call to 'foo' is ambiguous; candidates are:}}
+ int *ip = foo(fc);
+ long *lp = foo(dc);
+}
+
+char *promote_or_convert(double _Complex); // expected-note{{candidate function}}
+int *promote_or_convert(long double _Complex); // expected-note{{candidate function}}
+
+void test_promote_or_convert(float f, float _Complex fc) {
+ char *cp = promote_or_convert(fc);
+ int *ip2 = promote_or_convert(f); // expected-error{{call to 'promote_or_convert' is ambiguous; candidates are:}}
+}
+
+char *promote_or_convert2(float);
+int *promote_or_convert2(double _Complex);
+
+void test_promote_or_convert(float _Complex fc) {
+ int *cp = promote_or_convert2(fc);
+}