Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -230,6 +230,8 @@ void threadSafetyCleanup(BeforeSet* Cache); } + + // FIXME: No way to easily map from TemplateTypeParmTypes to // TemplateTypeParmDecls, so we have this horrible PointerUnion. typedef std::pair, @@ -12138,6 +12140,8 @@ MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK, sema::TemplateDeductionInfo &Info); + + /// Contains a late templated function. /// Will be parsed at the end of the translation unit, used by Sema & Parser. struct LateParsedTemplate { @@ -12147,6 +12151,9 @@ }; } // end namespace clang +clang::Sema::AssignConvertType checkPointerTypesForAssignment(clang::Sema &S, clang::QualType LHSType, + clang::QualType RHSType); + namespace llvm { // Hash a FunctionDeclAndLoc by looking at both its FunctionDecl and its // SourceLocation. Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -8018,7 +8018,7 @@ // routine is it effectively iqnores the qualifiers on the top level pointee. // This circumvents the usual type rules specified in 6.2.7p1 & 6.7.5.[1-3]. // FIXME: add a couple examples in this comment. -static Sema::AssignConvertType +Sema::AssignConvertType checkPointerTypesForAssignment(Sema &S, QualType LHSType, QualType RHSType) { assert(LHSType.isCanonical() && "LHS not canonicalized!"); assert(RHSType.isCanonical() && "RHS not canonicalized!"); Index: clang/lib/Sema/SemaExprCXX.cpp =================================================================== --- clang/lib/Sema/SemaExprCXX.cpp +++ clang/lib/Sema/SemaExprCXX.cpp @@ -3872,10 +3872,17 @@ llvm_unreachable("Cannot perform an ellipsis conversion"); case ImplicitConversionSequence::BadConversion: + Sema::AssignConvertType ConvTy = Compatible; + if (ToType.getCanonicalType()->isPointerType() && + From->getType()->isPointerType()) + ConvTy = checkPointerTypesForAssignment(*this, ToType.getCanonicalType(), + From->getType().getCanonicalType()); bool Diagnosed = - DiagnoseAssignmentResult(Incompatible, From->getExprLoc(), ToType, + DiagnoseAssignmentResult(ConvTy == Compatible ? Incompatible : ConvTy, + From->getExprLoc(), ToType, From->getType(), From, Action); - assert(Diagnosed && "failed to diagnose bad conversion"); (void)Diagnosed; + //assert(Diagnosed && "failed to diagnose bad conversion"); + (void)Diagnosed; return ExprError(); } Index: clang/test/SemaCXX/addr-of-overloaded-function.cpp =================================================================== --- clang/test/SemaCXX/addr-of-overloaded-function.cpp +++ clang/test/SemaCXX/addr-of-overloaded-function.cpp @@ -182,19 +182,19 @@ void parameter_number() { void (*ptr1)(int, int) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(int, int)' with an rvalue of type 'void (*)(int)': different number of parameters (2 vs 1)}} void (*ptr2)(int, int); - ptr2 = &fun; // expected-error {{assigning to 'void (*)(int, int)' from incompatible type 'void (*)(int)': different number of parameters (2 vs 1)}} + ptr2 = &fun; // expected-warning {{incompatible function pointer types assigning to 'void (*)(int, int)' from 'void (*)(int)'}} } void parameter_mismatch() { void (*ptr1)(double) = &fun; // expected-error {{cannot initialize a variable of type 'void (*)(double)' with an rvalue of type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} void (*ptr2)(double); - ptr2 = &fun; // expected-error {{assigning to 'void (*)(double)' from incompatible type 'void (*)(int)': type mismatch at 1st parameter ('double' vs 'int')}} + ptr2 = &fun; // expected-warning {{incompatible function pointer types assigning to 'void (*)(int, int)' from 'void (*)(int)'}} } void return_type_test() { int (*ptr1)(int) = &fun; // expected-error {{cannot initialize a variable of type 'int (*)(int)' with an rvalue of type 'void (*)(int)': different return type ('int' vs 'void')}} int (*ptr2)(int); - ptr2 = &fun; // expected-error {{assigning to 'int (*)(int)' from incompatible type 'void (*)(int)': different return type ('int' vs 'void')}} + ptr2 = &fun; // expected-warning {{incompatible function pointer types assigning to 'int (*)(int)' from 'void (*)(int)'}} } int foo(double x, double y) {return 0;} // expected-note {{candidate function has different number of parameters (expected 1 but has 2)}}