diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 24 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 32 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 4 | ||||
-rw-r--r-- | test/FixIt/dereference-addressof.c | 22 | ||||
-rw-r--r-- | test/FixIt/fixit.cpp | 11 | ||||
-rw-r--r-- | test/SemaObjC/comptypes-7.m | 2 |
6 files changed, 86 insertions, 9 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 98f758332f..1bb24a46fc 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -3547,7 +3547,11 @@ def err_typecheck_convert_incompatible : Error< "%select{from incompatible type|to parameter of incompatible type|" "from a function with incompatible result type|to incompatible type|" "with an expression of incompatible type|to parameter of incompatible type|" - "to incompatible type}2 %1">; + "to incompatible type}2 %1; " + "%select{|dereference with *|" + "take the address with &|" + "remove *|" + "remove &}3">; def warn_incompatible_qualified_id : Warning< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " @@ -3560,13 +3564,21 @@ def ext_typecheck_convert_pointer_int : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1">; + "with an expression of type|to parameter of type|to type}2 %1; " + "%select{|dereference with *|" + "take the address with &|" + "remove *|" + "remove &}3">; def ext_typecheck_convert_int_pointer : ExtWarn< "incompatible integer to pointer conversion " "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1">; + "with an expression of type|to parameter of type|to type}2 %1; " + "%select{|dereference with *|" + "take the address with &|" + "remove *|" + "remove &}3">; def ext_typecheck_convert_pointer_void_func : Extension< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " @@ -3585,7 +3597,11 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" " %0 " "%select{from|to parameter of type|from a function with result type|to type|" - "with an expression of type|to parameter of type|to type}2 %1">, + "with an expression of type|to parameter of type|to type}2 %1" + "%select{|dereference with *|" + "take the address with &|" + "remove *|" + "remove &}3">, InGroup<DiagGroup<"incompatible-pointer-types">>; def ext_typecheck_convert_discards_qualifiers : ExtWarn< "%select{assigning to|passing|returning|converting|initializing|sending|casting}2" diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index dedf7b0d77..9019e95747 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -36,6 +36,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/ParsedTemplate.h" +#include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/Template.h" using namespace clang; using namespace sema; @@ -8668,21 +8669,31 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, bool isInvalid = false; unsigned DiagKind; FixItHint Hint; + ConversionFixItGenerator ConvHints; + bool MayHaveConvFixit = false; switch (ConvTy) { default: assert(0 && "Unknown conversion type"); case Compatible: return false; case PointerToInt: DiagKind = diag::ext_typecheck_convert_pointer_int; + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; break; case IntToPointer: DiagKind = diag::ext_typecheck_convert_int_pointer; + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; break; case IncompatiblePointer: MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint); DiagKind = diag::ext_typecheck_convert_incompatible_pointer; CheckInferredResultType = DstType->isObjCObjectPointerType() && SrcType->isObjCObjectPointerType(); + if (Hint.isNull() && !CheckInferredResultType) { + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + } + MayHaveConvFixit = true; break; case IncompatiblePointerSign: DiagKind = diag::ext_typecheck_convert_incompatible_pointer_sign; @@ -8746,6 +8757,8 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, break; case Incompatible: DiagKind = diag::err_typecheck_convert_incompatible; + ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); + MayHaveConvFixit = true; isInvalid = true; break; } @@ -8770,8 +8783,23 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, break; } - Diag(Loc, DiagKind) << FirstType << SecondType << Action - << SrcExpr->getSourceRange() << Hint; + PartialDiagnostic FDiag = PDiag(DiagKind); + FDiag << FirstType << SecondType << Action << SrcExpr->getSourceRange(); + + // If we can fix the conversion, suggest the FixIts. + assert(ConvHints.isNull() || Hint.isNull()); + if (!ConvHints.isNull()) { + for (llvm::SmallVector<FixItHint, 1>::iterator + HI = ConvHints.Hints.begin(), HE = ConvHints.Hints.end(); + HI != HE; ++HI) + FDiag << *HI; + } else { + FDiag << Hint; + } + if (MayHaveConvFixit) { FDiag << (unsigned) (ConvHints.Kind); } + + Diag(Loc, FDiag); + if (CheckInferredResultType) EmitRelatedResultTypeNote(SrcExpr); diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 1812510942..0061db9730 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -2363,12 +2363,12 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, Diag(From->getSourceRange().getBegin(), diag::ext_typecheck_convert_incompatible_pointer) << ToType << From->getType() << Action - << From->getSourceRange(); + << From->getSourceRange() << 0; else Diag(From->getSourceRange().getBegin(), diag::ext_typecheck_convert_incompatible_pointer) << From->getType() << ToType << Action - << From->getSourceRange(); + << From->getSourceRange() << 0; if (From->getType()->isObjCObjectPointerType() && ToType->isObjCObjectPointerType()) diff --git a/test/FixIt/dereference-addressof.c b/test/FixIt/dereference-addressof.c new file mode 100644 index 0000000000..950fadc830 --- /dev/null +++ b/test/FixIt/dereference-addressof.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: cp %s %t +// RUN: not %clang_cc1 -fsyntax-only -fixit -x c %t +// RUN: %clang_cc1 -fsyntax-only -pedantic -x c %t + +void ip(int *aPtr) {} // expected-note{{passing argument to parameter 'aPtr' here}} +void i(int a) {} // expected-note{{passing argument to parameter 'a' here}} +void ii(int a) {} // expected-note{{passing argument to parameter 'a' here}} +void fp(float *aPtr) {} // expected-note{{passing argument to parameter 'aPtr' here}} +void f(float a) {} // expected-note{{passing argument to parameter 'a' here}} + +void f2(int *aPtr, int a, float *bPtr, char c) { + float fl = 0; + ip(a); // expected-warning{{incompatible integer to pointer conversion passing 'int' to parameter of type 'int *'; take the address with &}} + i(aPtr); // expected-warning{{incompatible pointer to integer conversion passing 'int *' to parameter of type 'int'; dereference with *}} + ii(&a); // expected-warning{{incompatible pointer to integer conversion passing 'int *' to parameter of type 'int'; remove &}} + fp(*bPtr); // expected-error{{passing 'float' to parameter of incompatible type 'float *'; remove *}} + f(bPtr); // expected-error{{passing 'float *' to parameter of incompatible type 'float'; dereference with *}} + a = aPtr; // expected-warning{{incompatible pointer to integer conversion assigning to 'int' from 'int *'; dereference with *}} + fl = bPtr + a; // expected-error{{assigning to 'float' from incompatible type 'float *'; dereference with *}} + bPtr = bPtr[a]; // expected-error{{assigning to 'float *' from incompatible type 'float'; take the address with &}} +} diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp index ac749859ea..109c14d91a 100644 --- a/test/FixIt/fixit.cpp +++ b/test/FixIt/fixit.cpp @@ -96,4 +96,15 @@ void f(){ typename F1<T>:: /*template*/ Iterator<0> Mypos; // expected-error {{use 'template' keyword to treat 'Iterator' as a dependent template name}} } +// Tests for &/* fixits radar 7113438. +class AD {}; +class BD: public AD {}; + +void test (BD &br) { + AD* aPtr; + BD b; + aPtr = b; // expected-error {{assigning to 'AD *' from incompatible type 'BD'; take the address with &}} + aPtr = br; // expected-error {{assigning to 'A *' from incompatible type 'B'; take the address with &}} +} + diff --git a/test/SemaObjC/comptypes-7.m b/test/SemaObjC/comptypes-7.m index df627e5300..ef0f158c49 100644 --- a/test/SemaObjC/comptypes-7.m +++ b/test/SemaObjC/comptypes-7.m @@ -30,7 +30,7 @@ int main() obj_p = i; // expected-warning {{incompatible integer to pointer conversion assigning to 'id<MyProtocol>' from 'int'}} obj_p = j; // expected-warning {{ incompatible pointer types assigning to 'id<MyProtocol>' from 'int *'}} - obj_c = i; // expected-warning {{ incompatible integer to pointer conversion assigning to 'MyClass *' from 'int'}} + obj_c = i; // expected-warning {{incompatible integer to pointer conversion assigning to 'MyClass *' from 'int'}} obj_c = j; // expected-warning {{incompatible pointer types assigning to 'MyClass *' from 'int *'}} obj_C = i; // expected-warning {{incompatible integer to pointer conversion assigning to 'Class' from 'int'}} |