]> granicus.if.org Git - clang/commitdiff
Fixed Sema::CheckEqualityOperands() and Sema::CheckRelationalOperands() to deal more
authorSteve Naroff <snaroff@apple.com>
Thu, 16 Aug 2007 21:48:38 +0000 (21:48 +0000)
committerSteve Naroff <snaroff@apple.com>
Thu, 16 Aug 2007 21:48:38 +0000 (21:48 +0000)
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

Sema/SemaExpr.cpp
include/clang/Basic/DiagnosticKinds.def
test/Parser/pointer_promotion.c [new file with mode: 0644]

index f69867fdf16b88344496521d142e246554581e5b..43e06867c60d521d68fff797de1727ed67d0c7a8 100644 (file)
@@ -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();
index 9137a8419fea3746bf8f3d58a14ae28658f77d49..e13a95bac00fa4b9a603a05e84b0b91835c8ff1b 100644 (file)
@@ -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 (file)
index 0000000..18cd968
--- /dev/null
@@ -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 *')}}
+}
+