* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T``
and ``U`` are compatible types. This conversion is given "conversion" rank.
+* A conversion from a pointer of type ``T*`` to a pointer of type ``U*``, where
+ ``T`` and ``U`` are incompatible, is allowed, but is ranked below all other
+ types of conversions. Please note: ``U`` lacking qualifiers that are present
+ on ``T`` is sufficient for ``T`` and ``U`` to be incompatible.
+
The declaration of ``overloadable`` functions is restricted to function
declarations and definitions. Most importantly, if any function with a given
name is given the ``overloadable`` attribute, then all function declarations
ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion
ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10)
ICK_C_Only_Conversion, ///< Conversions allowed in C, but not C++
+ ICK_Incompatible_Pointer_Conversion, ///< C-only conversion between pointers
+ /// with incompatible types
ICK_Num_Conversion_Kinds, ///< The number of conversion kinds
};
ICR_Conversion, ///< Conversion
ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion
ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion
- ICR_C_Conversion ///< Conversion only allowed in the C standard.
+ ICR_C_Conversion, ///< Conversion only allowed in the C standard.
/// (e.g. void* to char*)
+ ICR_C_Conversion_Extension ///< Conversion not allowed by the C standard,
+ /// but that we accept as an extension anyway.
};
ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind);
case ICK_Qualification:
case ICK_Num_Conversion_Kinds:
case ICK_C_Only_Conversion:
+ case ICK_Incompatible_Pointer_Conversion:
llvm_unreachable("Improper second standard conversion");
}
ICR_Exact_Match, // NOTE(gbiv): This may not be completely right --
// it was omitted by the patch that added
// ICK_Zero_Event_Conversion
- ICR_C_Conversion
+ ICR_C_Conversion,
+ ICR_C_Conversion_Extension
};
return Rank[(int)Kind];
}
"Transparent Union Conversion",
"Writeback conversion",
"OpenCL Zero Event Conversion",
- "C specific type conversion"
+ "C specific type conversion",
+ "Incompatible pointer conversion"
};
return Name[Kind];
}
return false;
ExprResult ER = ExprResult{From};
- auto Conv = S.CheckSingleAssignmentConstraints(ToType, ER,
- /*Diagnose=*/false,
- /*DiagnoseCFAudited=*/false,
- /*ConvertRHS=*/false);
- if (Conv != Sema::Compatible)
+ Sema::AssignConvertType Conv =
+ S.CheckSingleAssignmentConstraints(ToType, ER,
+ /*Diagnose=*/false,
+ /*DiagnoseCFAudited=*/false,
+ /*ConvertRHS=*/false);
+ ImplicitConversionKind ImplicitConv;
+ switch (Conv) {
+ case Sema::Compatible:
+ ImplicitConv = ICK_C_Only_Conversion;
+ break;
+ // For our purposes, discarding qualifiers is just as bad as using an
+ // incompatible pointer. Note that an IncompatiblePointer conversion can drop
+ // qualifiers, as well.
+ case Sema::CompatiblePointerDiscardsQualifiers:
+ case Sema::IncompatiblePointer:
+ case Sema::IncompatiblePointerSign:
+ ImplicitConv = ICK_Incompatible_Pointer_Conversion;
+ break;
+ default:
return false;
+ }
SCS.setAllToTypes(ToType);
// We need to set all three because we want this conversion to rank terribly,
// and we don't know what conversions it may overlap with.
- SCS.First = ICK_C_Only_Conversion;
- SCS.Second = ICK_C_Only_Conversion;
- SCS.Third = ICK_C_Only_Conversion;
+ SCS.First = ImplicitConv;
+ SCS.Second = ImplicitConv;
+ SCS.Third = ImplicitConv;
return true;
}
-
+
static bool
IsTransparentUnionStandardConversion(Sema &S, Expr* From,
QualType &ToType,
case ICK_Writeback_Conversion:
case ICK_Zero_Event_Conversion:
case ICK_C_Only_Conversion:
+ case ICK_Incompatible_Pointer_Conversion:
return false;
case ICK_Lvalue_To_Rvalue:
/*AllowObjCWritebackConversion=*/
getLangOpts().ObjCAutoRefCount,
/*AllowExplicit*/false);
- if (ConversionState.isBad()) {
- Match = false;
- break;
- }
+ // This function looks for a reasonably-exact match, so we consider
+ // incompatible pointer conversions to be a failure here.
+ if (ConversionState.isBad() ||
+ (ConversionState.isStandard() &&
+ ConversionState.Standard.Second ==
+ ICK_Incompatible_Pointer_Conversion)) {
+ Match = false;
+ break;
+ }
}
// Promote additional arguments to variadic methods.
if (Match && Method->isVariadic()) {
// expected-note@vecintrin.h:* 1 {{must be a constant integer from 0 to 1}}
vsc = vec_load_bndry(cptrsc, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsc = vec_load_bndry(cptrsc, 200); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsc = vec_load_bndry(cptrsc, 32); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsc = vec_load_bndry(cptrsc, 8192); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vuc = vec_load_bndry(cptruc, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vss = vec_load_bndry(cptrss, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vus = vec_load_bndry(cptrus, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsi = vec_load_bndry(cptrsi, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vui = vec_load_bndry(cptrui, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vsl = vec_load_bndry(cptrsl, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vul = vec_load_bndry(cptrul, idx); // expected-error {{no matching function}}
- // expected-note@vecintrin.h:* 8 {{candidate function not viable}}
- // expected-note@vecintrin.h:* 1 {{must be a constant power of 2 from 64 to 4096}}
+ // expected-note@vecintrin.h:* 9 {{must be a constant power of 2 from 64 to 4096}}
vuc = vec_genmask(idx); // expected-error {{no matching function}}
// expected-note@vecintrin.h:* {{must be a constant integer}}
// CHECK: @_Z13addrof_singlePc
void *vp3 = &addrof_single;
}
+
+
+void ovl_bar(char *) __attribute__((overloadable));
+void ovl_bar(int) __attribute__((overloadable));
+
+// CHECK-LABEL: define void @bar
+void bar() {
+ char charbuf[1];
+ unsigned char ucharbuf[1];
+
+ // CHECK: call void @_Z7ovl_barPc
+ ovl_bar(charbuf);
+ // CHECK: call void @_Z7ovl_barPc
+ ovl_bar(ucharbuf);
+}
void test_funcptr(int (*f1)(int, double),
int (*f2)(int, float)) {
float *fp = accept_funcptr(f1);
- accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'}}
+ accept_funcptr(f2); // expected-error{{call to 'accept_funcptr' is ambiguous}}
}
struct X { int x; float y; };
void *specific_disabled = &disabled;
}
+
+void incompatible_pointer_type_conversions() {
+ char charbuf[1];
+ unsigned char ucharbuf[1];
+ int intbuf[1];
+
+ void foo(char *c) __attribute__((overloadable));
+ void foo(short *c) __attribute__((overloadable));
+ foo(charbuf);
+ foo(ucharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@131{{candidate function}} expected-note@132{{candidate function}}
+ foo(intbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@131{{candidate function}} expected-note@132{{candidate function}}
+
+ void bar(unsigned char *c) __attribute__((overloadable));
+ void bar(signed char *c) __attribute__((overloadable));
+ bar(charbuf); // expected-error{{call to 'bar' is ambiguous}} expected-note@137{{candidate function}} expected-note@138{{candidate function}}
+ bar(ucharbuf);
+ bar(intbuf); // expected-error{{call to 'bar' is ambiguous}} expected-note@137{{candidate function}} expected-note@138{{candidate function}}
+}
+
+void dropping_qualifiers_is_incompatible() {
+ const char ccharbuf[1];
+ volatile char vcharbuf[1];
+
+ void foo(char *c) __attribute__((overloadable));
+ void foo(const volatile unsigned char *c) __attribute__((overloadable));
+
+ foo(ccharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}}
+ foo(vcharbuf); // expected-error{{call to 'foo' is ambiguous}} expected-note@148{{candidate function}} expected-note@149{{candidate function}}
+}
int P;
(&NotOverloaded)(&P); //expected-error{{cannot take address of function 'NotOverloaded' because parameter 1 has pass_object_size attribute}}
- (&IsOverloaded)(&P); //expected-error{{no matching function}} expected-note@35{{candidate address cannot be taken because parameter 1 has pass_object_size attribute}} expected-note@36{{candidate function not viable: no known conversion from 'int *' to 'char *' for 1st argument}}
+ (&IsOverloaded)(&P); //expected-warning{{incompatible pointer types passing 'int *' to parameter of type 'char *'}} expected-note@36{{passing argument to parameter 'p' here}}
}
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
-void __attribute__((overloadable)) foo(event_t, __local char *); // expected-note {{candidate function not viable: no known conversion from '__global int *' to '__local char *' for 2nd argument}}
-void __attribute__((overloadable)) foo(event_t, __local float *); // expected-note {{candidate function not viable: no known conversion from '__global int *' to '__local float *' for 2nd argument}}
+void __attribute__((overloadable)) foo(event_t, __local char *); // expected-note {{candidate function}}
+void __attribute__((overloadable)) foo(event_t, __local float *); // expected-note {{candidate function}}
void kernel ker(__local char *src1, __local float *src2, __global int *src3) {
event_t evt;
foo(evt, src1);
foo(0, src2);
- foo(evt, src3); // expected-error {{no matching function for call to 'foo'}}
+ foo(evt, src3); // expected-error {{call to 'foo' is ambiguous}}
}