[cfe-commits] r44746 - in /cfe/trunk: Sema/SemaExpr.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/typecheck-binop.c
Chris Lattner
sabre at nondot.org
Sun Dec 9 13:53:26 PST 2007
Author: lattner
Date: Sun Dec 9 15:53:25 2007
New Revision: 44746
URL: http://llvm.org/viewvc/llvm-project?rev=44746&view=rev
Log:
Implement correct semantic analysis of subtractions, implementing
C99 6.5.6.
Added:
cfe/trunk/test/Sema/typecheck-binop.c
Modified:
cfe/trunk/Sema/SemaExpr.cpp
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=44746&r1=44745&r2=44746&view=diff
==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Sun Dec 9 15:53:25 2007
@@ -1259,14 +1259,60 @@
QualType compType = UsualArithmeticConversions(lex, rex, isCompAssign);
- // handle the common case first (both operands are arithmetic).
+ // Enforce type constraints: C99 6.5.6p3.
+
+ // Handle the common case first (both operands are arithmetic).
if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType())
return compType;
+
+ // Either ptr - int or ptr - ptr.
+ if (const PointerType *LHSPTy = lex->getType()->getAsPointerType()) {
+ // The LHS must be an object type, not incomplete, function, etc.
+ if (!LHSPTy->getPointeeType()->isObjectType()) {
+ // Handle the GNU void* extension.
+ if (LHSPTy->getPointeeType()->isVoidType()) {
+ Diag(loc, diag::ext_gnu_void_ptr,
+ lex->getSourceRange(), rex->getSourceRange());
+ } else {
+ Diag(loc, diag::err_typecheck_sub_ptr_object,
+ lex->getType().getAsString(), lex->getSourceRange());
+ return QualType();
+ }
+ }
+
+ // The result type of a pointer-int computation is the pointer type.
+ if (rex->getType()->isIntegerType())
+ return lex->getType();
- if (lex->getType()->isPointerType() && rex->getType()->isIntegerType())
- return compType;
- if (lex->getType()->isPointerType() && rex->getType()->isPointerType())
- return Context.getPointerDiffType();
+ // Handle pointer-pointer subtractions.
+ if (const PointerType *RHSPTy = rex->getType()->getAsPointerType()) {
+ // RHS must be an object type, unless void (GNU).
+ if (!RHSPTy->getPointeeType()->isObjectType()) {
+ // Handle the GNU void* extension.
+ if (RHSPTy->getPointeeType()->isVoidType()) {
+ if (!LHSPTy->getPointeeType()->isVoidType())
+ Diag(loc, diag::ext_gnu_void_ptr,
+ lex->getSourceRange(), rex->getSourceRange());
+ } else {
+ Diag(loc, diag::err_typecheck_sub_ptr_object,
+ rex->getType().getAsString(), rex->getSourceRange());
+ return QualType();
+ }
+ }
+
+ // Pointee types must be compatible.
+ if (!Context.typesAreCompatible(LHSPTy->getPointeeType(),
+ RHSPTy->getPointeeType())) {
+ Diag(loc, diag::err_typecheck_sub_ptr_compatible,
+ lex->getType().getAsString(), rex->getType().getAsString(),
+ lex->getSourceRange(), rex->getSourceRange());
+ return QualType();
+ }
+
+ return Context.getPointerDiffType();
+ }
+ }
+
InvalidOperands(loc, lex, rex);
return QualType();
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=44746&r1=44745&r2=44746&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Dec 9 15:53:25 2007
@@ -297,7 +297,9 @@
"compound literals are a C99-specific feature")
DIAG(ext_c99_enumerator_list_comma, EXTENSION,
"commas at the end of enumerator lists are a C99-specific feature")
-
+
+DIAG(ext_gnu_void_ptr, EXTENSION,
+ "use of GNU void* extension")
DIAG(ext_gnu_indirect_goto, EXTENSION,
"use of GNU indirect-goto extension")
DIAG(ext_gnu_address_of_label, EXTENSION,
@@ -733,6 +735,10 @@
"dereferencing '%0' pointer")
DIAG(err_typecheck_invalid_operands, ERROR,
"invalid operands to binary expression ('%0' and '%1')")
+DIAG(err_typecheck_sub_ptr_object, ERROR,
+ "'%0' is not a complete object type")
+DIAG(err_typecheck_sub_ptr_compatible, ERROR,
+ "'%0' and '%1' are not pointers to compatible types")
DIAG(ext_typecheck_comparison_of_pointer_integer, WARNING,
"comparison between pointer and integer ('%0' and '%1')")
DIAG(ext_typecheck_comparison_of_distinct_pointers, WARNING,
Added: cfe/trunk/test/Sema/typecheck-binop.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/typecheck-binop.c?rev=44746&view=auto
==============================================================================
--- cfe/trunk/test/Sema/typecheck-binop.c (added)
+++ cfe/trunk/test/Sema/typecheck-binop.c Sun Dec 9 15:53:25 2007
@@ -0,0 +1,20 @@
+/* RUN: clang %s -fsyntax-only -pedantic -verify
+ */
+struct incomplete;
+
+int sub1(int *a, double *b) {
+ return a - b; /* expected-error{{not pointers to compatible types}} */
+}
+
+void *sub2(struct incomplete *P) {
+ return P-4; /* expected-error{{not a complete object type}} */
+}
+
+void *sub3(void *P) {
+ return P-4; /* expected-warning{{GNU void* extension}} */
+}
+
+int sub4(void *P, void *Q) {
+ return P-Q; /* expected-warning{{GNU void* extension}} */
+}
+
More information about the cfe-commits
mailing list