]> granicus.if.org Git - clang/commitdiff
Add proper type-checking for pointer additiion; before, we were accepting
authorEli Friedman <eli.friedman@gmail.com>
Sun, 18 May 2008 18:08:51 +0000 (18:08 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sun, 18 May 2008 18:08:51 +0000 (18:08 +0000)
addition with a pointer and an integer even when it didn't make sense.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51228 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
test/Sema/pointer-addition.c [new file with mode: 0644]

index 6132dfddbaca84e465d02f7cc3033c005f7a332e..e5ac14e092c568291ff7654aa77bfda2ea6502cb 100644 (file)
@@ -1405,15 +1405,33 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6
     return CheckVectorOperands(loc, lex, rex);
 
   QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
-  
+
   // handle the common case first (both operands are arithmetic).
   if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
     return compType;
 
-  if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
-    return lex->getType();
-  if (lex->getType()->isIntegerType() && rex->getType()->isPointerType())
-    return rex->getType();
+  // Put any potential pointer into PExp
+  Expr* PExp = lex, *IExp = rex;
+  if (IExp->getType()->isPointerType())
+    std::swap(PExp, IExp);
+
+  if (const PointerType* PTy = PExp->getType()->getAsPointerType()) {
+    if (IExp->getType()->isIntegerType()) {
+      // Check for arithmetic on pointers to incomplete types
+      if (!PTy->getPointeeType()->isObjectType()) {
+        if (PTy->getPointeeType()->isVoidType()) {
+          Diag(loc, diag::ext_gnu_void_ptr, 
+               lex->getSourceRange(), rex->getSourceRange());
+        } else {
+          Diag(loc, diag::err_typecheck_arithmetic_incomplete_type,
+               lex->getType().getAsString(), lex->getSourceRange());
+          return QualType();
+        }
+      }
+      return PExp->getType();
+    }
+  }
+
   return InvalidOperands(loc, lex, rex);
 }
 
@@ -1681,7 +1699,10 @@ QualType Sema::CheckIncrementDecrementOperand(Expr *op, SourceLocation OpLoc) {
 
   // C99 6.5.2.4p1: We allow complex as a GCC extension.
   if (const PointerType *pt = resType->getAsPointerType()) {
-    if (!pt->getPointeeType()->isObjectType()) { // C99 6.5.2.4p2, 6.5.6p2
+    if (pt->getPointeeType()->isVoidType()) {
+      Diag(OpLoc, diag::ext_gnu_void_ptr, op->getSourceRange());
+    } else if (!pt->getPointeeType()->isObjectType()) {
+      // C99 6.5.2.4p2, 6.5.6p2
       Diag(OpLoc, diag::err_typecheck_arithmetic_incomplete_type,
            resType.getAsString(), op->getSourceRange());
       return QualType();
diff --git a/test/Sema/pointer-addition.c b/test/Sema/pointer-addition.c
new file mode 100644 (file)
index 0000000..f2fb973
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: clang %s -fsyntax-only -verify -pedantic
+
+typedef struct S S;
+void a(S* b, void* c) {
+  b++;       // expected-error {{arithmetic on pointer to incomplete type}}
+  b += 1;    // expected-error {{arithmetic on pointer to incomplete type}}
+  c++;       // expected-warning {{use of GNU void* extension}}
+  c += 1;    // expected-warning {{use of GNU void* extension}}
+  b = 1+b;   // expected-error {{arithmetic on pointer to incomplete type}}
+  /* The next couple tests are only pedantic warnings in gcc */
+  void (*d)(S*,void*) = a;
+  d += 1;    // expected-error {{pointer to incomplete type}}
+  d++;       // expected-error {{pointer to incomplete type}}
+}