Add */& mismatch fixit generation to the Sema::DiagnoseAssignmentResult().

llvm-svn: 136379
This commit is contained in:
Anna Zaks 2011-07-28 19:51:27 +00:00
parent e39f97c869
commit 3b402716b1
6 changed files with 86 additions and 9 deletions

View File

@ -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"

View File

@ -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);

View File

@ -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())

View File

@ -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 &}}
}

View File

@ -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 &}}
}

View File

@ -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'}}