aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaExpr.cpp33
-rw-r--r--test/Sema/pointer-addition.c14
2 files changed, 41 insertions, 6 deletions
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}}
+}