Add */& mismatch fixit generation to the Sema::DiagnoseAssignmentResult().
llvm-svn: 136379
This commit is contained in:
parent
e39f97c869
commit
3b402716b1
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 &}}
|
||||
}
|
|
@ -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 &}}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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'}}
|
||||
|
|
Loading…
Reference in New Issue