From 8e12298192a5221e2819b0fb78b4962a035f2188 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sun, 18 May 2008 18:08:51 +0000 Subject: [PATCH] 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. llvm-svn: 51228 --- clang/lib/Sema/SemaExpr.cpp | 33 ++++++++++++++++++++++++------ clang/test/Sema/pointer-addition.c | 14 +++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 clang/test/Sema/pointer-addition.c diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 6132dfddbaca..e5ac14e092c5 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/test/Sema/pointer-addition.c b/clang/test/Sema/pointer-addition.c new file mode 100644 index 000000000000..f2fb973d1be0 --- /dev/null +++ b/clang/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}} +}