aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Naroff <snaroff@apple.com>2007-08-16 21:48:38 +0000
committerSteve Naroff <snaroff@apple.com>2007-08-16 21:48:38 +0000
commite77fd3c15c8c4a2f1225e75d5742b6ad07578913 (patch)
treef8c543ab445d196603a2b75bf4f0829a4989765a
parentfc4a1601a84d280d7e5c424b77843fdd743beec8 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41127 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Sema/SemaExpr.cpp80
-rw-r--r--include/clang/Basic/DiagnosticKinds.def4
-rw-r--r--test/Parser/pointer_promotion.c18
3 files changed, 73 insertions, 29 deletions
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index f69867fdf1..43e06867c6 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -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();
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 9137a8419f..e13a95bac0 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -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,
diff --git a/test/Parser/pointer_promotion.c b/test/Parser/pointer_promotion.c
new file mode 100644
index 0000000000..18cd9687b7
--- /dev/null
+++ b/test/Parser/pointer_promotion.c
@@ -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 *')}}
+}
+