Index: cfe/trunk/include/clang/Basic/AttrDocs.td =================================================================== --- cfe/trunk/include/clang/Basic/AttrDocs.td +++ cfe/trunk/include/clang/Basic/AttrDocs.td @@ -470,6 +470,11 @@ * 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 Index: cfe/trunk/include/clang/Sema/Overload.h =================================================================== --- cfe/trunk/include/clang/Sema/Overload.h +++ cfe/trunk/include/clang/Sema/Overload.h @@ -84,6 +84,8 @@ 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 }; @@ -97,8 +99,10 @@ 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); Index: cfe/trunk/lib/Sema/SemaExprCXX.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp @@ -3705,6 +3705,7 @@ case ICK_Qualification: case ICK_Num_Conversion_Kinds: case ICK_C_Only_Conversion: + case ICK_Incompatible_Pointer_Conversion: llvm_unreachable("Improper second standard conversion"); } Index: cfe/trunk/lib/Sema/SemaOverload.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaOverload.cpp +++ cfe/trunk/lib/Sema/SemaOverload.cpp @@ -136,7 +136,8 @@ 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]; } @@ -170,7 +171,8 @@ "Transparent Union Conversion", "Writeback conversion", "OpenCL Zero Event Conversion", - "C specific type conversion" + "C specific type conversion", + "Incompatible pointer conversion" }; return Name[Kind]; } @@ -1783,22 +1785,37 @@ 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, @@ -5105,6 +5122,7 @@ 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: @@ -5906,10 +5924,15 @@ /*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()) { Index: cfe/trunk/test/CodeGen/builtins-systemz-zvector-error.c =================================================================== --- cfe/trunk/test/CodeGen/builtins-systemz-zvector-error.c +++ cfe/trunk/test/CodeGen/builtins-systemz-zvector-error.c @@ -233,38 +233,27 @@ // 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}} Index: cfe/trunk/test/CodeGen/overloadable.c =================================================================== --- cfe/trunk/test/CodeGen/overloadable.c +++ cfe/trunk/test/CodeGen/overloadable.c @@ -59,3 +59,18 @@ // 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); +} Index: cfe/trunk/test/Sema/overloadable.c =================================================================== --- cfe/trunk/test/Sema/overloadable.c +++ cfe/trunk/test/Sema/overloadable.c @@ -23,7 +23,7 @@ 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; }; @@ -122,3 +122,32 @@ 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}} +} Index: cfe/trunk/test/Sema/pass-object-size.c =================================================================== --- cfe/trunk/test/Sema/pass-object-size.c +++ cfe/trunk/test/Sema/pass-object-size.c @@ -52,5 +52,5 @@ 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}} } Index: cfe/trunk/test/SemaOpenCL/event_t_overload.cl =================================================================== --- cfe/trunk/test/SemaOpenCL/event_t_overload.cl +++ cfe/trunk/test/SemaOpenCL/event_t_overload.cl @@ -1,11 +1,11 @@ // 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}} }