forked from OSchip/llvm-project
Fixed Sema::CheckEqualityOperands() and Sema::CheckRelationalOperands() to deal more
thoughtfully with incompatible pointers. This includes: - Emit a diagnostic when two pointers aren't compatible! - Promote one of the pointers/integers so we maintain the invariant expected by the code generator (i.e. that the left/right types match). - Upgrade the pointer/integer comparison diagnostic to include the types. llvm-svn: 41127
This commit is contained in:
parent
5f208bea91
commit
cdee44c12a
|
@ -1047,22 +1047,34 @@ inline QualType Sema::CheckRelationalOperands( // C99 6.5.8
|
|||
if (lType->isRealType() && rType->isRealType())
|
||||
return Context.IntTy;
|
||||
|
||||
if (lType->isPointerType()) {
|
||||
if (rType->isPointerType())
|
||||
return Context.IntTy;
|
||||
if (rType->isIntegerType()) {
|
||||
if (!rex->isNullPointerConstant(Context))
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
return Context.IntTy; // the previous diagnostic is a GCC extension.
|
||||
// All of the following pointer related warnings are GCC extensions. One
|
||||
// day, we can consider making them errors (when -pedantic-errors is enabled).
|
||||
if (lType->isPointerType() && rType->isPointerType()) {
|
||||
if (!Type::pointerTypesAreCompatible(lType, rType)) {
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
promoteExprToType(rex, lType); // promote the pointer to pointer
|
||||
}
|
||||
} else if (rType->isPointerType()) {
|
||||
if (lType->isIntegerType()) {
|
||||
if (!lex->isNullPointerConstant(Context))
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
return Context.IntTy; // the previous diagnostic is a GCC extension.
|
||||
return Context.IntTy;
|
||||
}
|
||||
if (lType->isPointerType() && rType->isIntegerType()) {
|
||||
if (!rex->isNullPointerConstant(Context)) {
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
promoteExprToType(rex, lType); // promote the integer to pointer
|
||||
}
|
||||
return Context.IntTy;
|
||||
}
|
||||
if (lType->isIntegerType() && rType->isPointerType()) {
|
||||
if (!lex->isNullPointerConstant(Context)) {
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
promoteExprToType(lex, rType); // promote the integer to pointer
|
||||
}
|
||||
return Context.IntTy;
|
||||
}
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
|
@ -1084,22 +1096,34 @@ inline QualType Sema::CheckEqualityOperands( // C99 6.5.9
|
|||
if (lType->isArithmeticType() && rType->isArithmeticType())
|
||||
return Context.IntTy;
|
||||
|
||||
if (lType->isPointerType()) {
|
||||
if (rType->isPointerType())
|
||||
return Context.IntTy;
|
||||
if (rType->isIntegerType()) {
|
||||
if (!rex->isNullPointerConstant(Context))
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
return Context.IntTy; // the previous diagnostic is a GCC extension.
|
||||
// All of the following pointer related warnings are GCC extensions. One
|
||||
// day, we can consider making them errors (when -pedantic-errors is enabled).
|
||||
if (lType->isPointerType() && rType->isPointerType()) {
|
||||
if (!Type::pointerTypesAreCompatible(lType, rType)) {
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_distinct_pointers,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
promoteExprToType(rex, lType); // promote the pointer to pointer
|
||||
}
|
||||
} else if (rType->isPointerType()) {
|
||||
if (lType->isIntegerType()) {
|
||||
if (!lex->isNullPointerConstant(Context))
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
return Context.IntTy; // the previous diagnostic is a GCC extension.
|
||||
return Context.IntTy;
|
||||
}
|
||||
if (lType->isPointerType() && rType->isIntegerType()) {
|
||||
if (!rex->isNullPointerConstant(Context)) {
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
promoteExprToType(rex, lType); // promote the integer to pointer
|
||||
}
|
||||
return Context.IntTy;
|
||||
}
|
||||
if (lType->isIntegerType() && rType->isPointerType()) {
|
||||
if (!lex->isNullPointerConstant(Context)) {
|
||||
Diag(loc, diag::ext_typecheck_comparison_of_pointer_integer,
|
||||
lType.getAsString(), rType.getAsString(),
|
||||
lex->getSourceRange(), rex->getSourceRange());
|
||||
promoteExprToType(lex, rType); // promote the integer to pointer
|
||||
}
|
||||
return Context.IntTy;
|
||||
}
|
||||
InvalidOperands(loc, lex, rex);
|
||||
return QualType();
|
||||
|
|
|
@ -611,7 +611,9 @@ DIAG(ext_typecheck_deref_ptr_to_void, WARNING,
|
|||
DIAG(err_typecheck_invalid_operands, ERROR,
|
||||
"invalid operands to binary expression ('%0' and '%1')")
|
||||
DIAG(ext_typecheck_comparison_of_pointer_integer, WARNING,
|
||||
"comparison between pointer and integer")
|
||||
"comparison between pointer and integer ('%0' and '%1')")
|
||||
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_assign_incompatible, ERROR,
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// RUN: clang -parse-ast-check %s
|
||||
|
||||
int test() {
|
||||
void *vp;
|
||||
int *ip;
|
||||
char *cp;
|
||||
struct foo *fp;
|
||||
struct bar *bp;
|
||||
short sint = 7;
|
||||
|
||||
if (ip < cp) ; // expected-warning {{comparison of distinct pointer types ('int *' and 'char *')}}
|
||||
if (cp < fp) ; // expected-warning {{comparison of distinct pointer types ('char *' and 'struct foo *')}}
|
||||
if (fp < bp) ; // expected-warning {{comparison of distinct pointer types ('struct foo *' and 'struct bar *')}}
|
||||
if (ip < 7) ; // expected-warning {{comparison between pointer and integer ('int *' and 'int')}}
|
||||
if (sint < ip) ; // expected-warning {{comparison between pointer and integer ('int' and 'int *')}}
|
||||
if (ip == cp) ; // expected-warning {{comparison of distinct pointer types ('int *' and 'char *')}}
|
||||
}
|
||||
|
Loading…
Reference in New Issue