From: Eli Friedman Date: Sun, 18 May 2008 18:08:51 +0000 (+0000) Subject: Add proper type-checking for pointer additiion; before, we were accepting X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d72d16e6f105deb6fe890225a6251dd0e9001ce7;p=clang Add proper type-checking for pointer additiion; before, we were accepting 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 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6132dfddba..e5ac14e092 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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 index 0000000000..f2fb973d1b --- /dev/null +++ b/test/Sema/pointer-addition.c @@ -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}} +}