diff --git a/clang/Sema/Sema.cpp b/clang/Sema/Sema.cpp index 7bdcd0a214c7..bca3ec508bf2 100644 --- a/clang/Sema/Sema.cpp +++ b/clang/Sema/Sema.cpp @@ -152,6 +152,14 @@ bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, return true; } +bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, + const std::string &Msg2, const std::string &Msg3, + SourceRange R1) { + std::string MsgArr[] = { Msg1, Msg2, Msg3 }; + PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 3, &R1, 1); + return true; +} + bool Sema::Diag(SourceLocation Loc, unsigned DiagID, SourceRange R1, SourceRange R2) { SourceRange RangeArr[] = { R1, R2 }; diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 33fd345d00f3..8846d158134f 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -159,6 +159,8 @@ public: SourceRange R1, SourceRange R2); bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, const std::string &Msg2, SourceRange R1); + bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, + const std::string &Msg2, const std::string &Msg3, SourceRange R1); bool Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, const std::string &Msg2, SourceRange R1, SourceRange R2); diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index bab7d3d7e9b5..de642c6e65e1 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -2229,38 +2229,35 @@ bool Sema::CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs, Args[i] = argExpr; // Make sure we store the converted expression. SourceLocation l = argExpr->getLocStart(); - // decode the result (notice that AST's are still created for extensions). + // Decode the result (notice that AST's are still created for extensions). + const char *Kind = "sending"; switch (result) { case Compatible: break; case PointerFromInt: - Diag(l, diag::ext_typecheck_sending_pointer_int, - lhsType.getAsString(), rhsType.getAsString(), - argExpr->getSourceRange()); - break; case IntFromPointer: - Diag(l, diag::ext_typecheck_sending_pointer_int, - lhsType.getAsString(), rhsType.getAsString(), + Diag(l, diag::ext_typecheck_convert_pointer_int, + lhsType.getAsString(), rhsType.getAsString(), Kind, argExpr->getSourceRange()); break; case IncompatiblePointer: - Diag(l, diag::ext_typecheck_sending_incompatible_pointer, - rhsType.getAsString(), lhsType.getAsString(), + Diag(l, diag::ext_typecheck_convert_incompatible_pointer, + lhsType.getAsString(), rhsType.getAsString(), Kind, argExpr->getSourceRange()); break; case FunctionVoidPointer: - Diag(l, diag::ext_typecheck_sending_pointer_void_func, - rhsType.getAsString(), lhsType.getAsString(), + Diag(l, diag::ext_typecheck_convert_pointer_void_func, + lhsType.getAsString(), rhsType.getAsString(), Kind, argExpr->getSourceRange()); break; case CompatiblePointerDiscardsQualifiers: - Diag(l, diag::ext_typecheck_sending_discards_qualifiers, - rhsType.getAsString(), lhsType.getAsString(), + Diag(l, diag::ext_typecheck_convert_discards_qualifiers, + lhsType.getAsString(), rhsType.getAsString(), Kind, argExpr->getSourceRange()); break; case Incompatible: - Diag(l, diag::err_typecheck_sending_incompatible, - rhsType.getAsString(), lhsType.getAsString(), + Diag(l, diag::err_typecheck_convert_incompatible, + lhsType.getAsString(), rhsType.getAsString(), Kind, argExpr->getSourceRange()); anyIncompatibleArgs = true; } diff --git a/clang/include/clang/Basic/DiagnosticKinds.def b/clang/include/clang/Basic/DiagnosticKinds.def index c97e52a6b581..136f6021bb93 100644 --- a/clang/include/clang/Basic/DiagnosticKinds.def +++ b/clang/include/clang/Basic/DiagnosticKinds.def @@ -759,6 +759,18 @@ DIAG(ext_typecheck_comparison_of_distinct_pointers, WARNING, "comparison of distinct pointer types ('%0' and '%1')") DIAG(err_typecheck_assign_const, ERROR, "read-only variable is not assignable") + +DIAG(err_typecheck_convert_incompatible, ERROR, + "incompatible type %2 '%1', expected '%0'") +DIAG(ext_typecheck_convert_pointer_int, EXTENSION, + "incompatible pointer/int conversion %2 '%1', expected '%0'") +DIAG(ext_typecheck_convert_pointer_void_func, EXTENSION, + "%2 '%1' converts between void* and function pointer, expected '%0'") +DIAG(ext_typecheck_convert_incompatible_pointer, EXTENSION, + "incompatible pointer types %d '%1', expected '%0'") +DIAG(ext_typecheck_convert_discards_qualifiers, EXTENSION, + "%d '%1' discards qualifiers, expected '%0'") + DIAG(err_typecheck_return_incompatible, ERROR, @@ -796,18 +808,6 @@ DIAG(ext_typecheck_passing_pointer_void_func, EXTENSION, DIAG(ext_typecheck_passing_discards_qualifiers, WARNING, "passing '%0' to '%1' discards qualifiers") -DIAG(err_typecheck_sending_incompatible, ERROR, - "incompatible types passing '%0' to method expecting '%1'") -DIAG(ext_typecheck_sending_incompatible_pointer, WARNING, - "incompatible pointer types passing '%0' to method expecting '%1'") -DIAG(ext_typecheck_sending_pointer_int, WARNING, - "incompatible types passing '%1' to method expecting '%0'") -DIAG(ext_typecheck_sending_pointer_void_func, EXTENSION, - "sending '%1' to method expecting '%0' converts between void*" - " and function pointer") -DIAG(ext_typecheck_sending_discards_qualifiers, WARNING, - "sending '%0' to '%1' discards qualifiers") - DIAG(err_typecheck_array_not_modifiable_lvalue, ERROR, "array type '%0' is not assignable") diff --git a/clang/test/Sema/argument-checking.m b/clang/test/Sema/argument-checking.m index 851a874c9359..57ab14f1ff21 100644 --- a/clang/test/Sema/argument-checking.m +++ b/clang/test/Sema/argument-checking.m @@ -1,4 +1,4 @@ -// RUN: clang -fsyntax-only -verify %s +// RUN: clang -fsyntax-only -verify -pedantic %s struct S { int a; }; @@ -19,7 +19,7 @@ void test() { charStarFunc(1); // expected-warning {{incompatible types passing 'int' to function expecting 'char *'}} charFunc("abc"); // expected-warning {{incompatible types passing 'char *' to function expecting 'char'}} - [obj charStarMeth:1]; // expected-warning {{incompatible types passing 'int' to method expecting 'char *'}} - [obj structMeth:1]; // expected-error {{incompatible types passing 'int' to method expecting 'struct S'}} - [obj structMeth:sInst :1]; // expected-error {{incompatible types passing 'int' to method expecting 'struct S'}} + [obj charStarMeth:1]; // expected-warning {{incompatible pointer/int conversion sending 'int'}} + [obj structMeth:1]; // expected-error {{incompatible type sending 'int'}} + [obj structMeth:sInst :1]; // expected-error {{incompatible type sending 'int'}} }