[cfe-commits] r45933 - in /cfe/trunk: Sema/SemaExpr.cpp include/clang/Basic/DiagnosticKinds.def test/Sema/conditional-expr.c test/Sema/deref.c

Steve Naroff snaroff at apple.com
Sun Jan 13 09:10:09 PST 2008


Author: snaroff
Date: Sun Jan 13 11:10:08 2008
New Revision: 45933

URL: http://llvm.org/viewvc/llvm-project?rev=45933&view=rev
Log:
Change Sema::CheckAddressOfOperation() to respect C99-only addressof rules.
Remove diagnostics from Sema::CheckIndirectionOperand(). C89/C99 allow dereferencing an incomplete type. clang appears to be emulating some incorrect gcc behavior (see below).

void
foo (void)
{
 struct b;
 struct b* x = 0;
 struct b* y = &*x; // gcc produces an error ("dereferencing pointer to incomplete type")
}

With this patch, the above is now allowed.

Bug/Patch by Eli Friedman!


Added:
    cfe/trunk/test/Sema/deref.c
Modified:
    cfe/trunk/Sema/SemaExpr.cpp
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/test/Sema/conditional-expr.c

Modified: cfe/trunk/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaExpr.cpp?rev=45933&r1=45932&r2=45933&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/Sema/SemaExpr.cpp Sun Jan 13 11:10:08 2008
@@ -1618,6 +1618,17 @@
 /// Note: The usual conversions are *not* applied to the operand of the & 
 /// operator (C99 6.3.2.1p[2-4]), and its result is never an lvalue.
 QualType Sema::CheckAddressOfOperand(Expr *op, SourceLocation OpLoc) {
+  if (getLangOptions().C99) {
+    // Implement C99-only parts of addressof rules.
+    if (UnaryOperator* uOp = dyn_cast<UnaryOperator>(op)) {
+      if (uOp->getOpcode() == UnaryOperator::Deref)
+        // Per C99 6.5.3.2, the address of a deref always returns a valid result
+        // (assuming the deref expression is valid).
+        return uOp->getSubExpr()->getType();
+    }
+    // Technically, there should be a check for array subscript
+    // expressions here, but the result of one is always an lvalue anyway.
+  }
   Decl *dcl = getPrimaryDeclaration(op);
   Expr::isLvalueResult lval = op->isLvalue();
   
@@ -1651,19 +1662,12 @@
   QualType qType = op->getType();
   
   if (const PointerType *PT = qType->getAsPointerType()) {
-    QualType ptype = PT->getPointeeType();
-    // C99 6.5.3.2p4. "if it points to an object,...".
-    if (ptype->isIncompleteType()) { // An incomplete type is not an object
-      // GCC compat: special case 'void *' (treat as extension, not error).
-      if (ptype->isVoidType()) {
-        Diag(OpLoc, diag::ext_typecheck_deref_ptr_to_void,op->getSourceRange());
-      } else {
-        Diag(OpLoc, diag::err_typecheck_deref_incomplete_type, 
-             ptype.getAsString(), op->getSourceRange());
-        return QualType();
-      }
-    }
-    return ptype;
+    // Note that per both C89 and C99, this is always legal, even
+    // if ptype is an incomplete type or void.
+    // It would be possible to warn about dereferencing a
+    // void pointer, but it's completely well-defined,
+    // and such a warning is unlikely to catch any mistakes.
+    return PT->getPointeeType();
   }
   Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer, 
        qType.getAsString(), op->getSourceRange());

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=45933&r1=45932&r2=45933&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Jan 13 11:10:08 2008
@@ -756,10 +756,6 @@
      "invalid argument type to unary expression '%0'")
 DIAG(err_typecheck_indirection_requires_pointer, ERROR,
      "indirection requires pointer operand ('%0' invalid)")
-DIAG(err_typecheck_deref_incomplete_type, ERROR,
-     "dereferencing pointer to incomplete type '%0'")
-DIAG(ext_typecheck_deref_ptr_to_void, WARNING,
-     "dereferencing void pointer")
 DIAG(err_typecheck_invalid_operands, ERROR,
      "invalid operands to binary expression ('%0' and '%1')")
 DIAG(err_typecheck_sub_ptr_object, ERROR,

Modified: cfe/trunk/test/Sema/conditional-expr.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/conditional-expr.c?rev=45933&r1=45932&r2=45933&view=diff

==============================================================================
--- cfe/trunk/test/Sema/conditional-expr.c (original)
+++ cfe/trunk/test/Sema/conditional-expr.c Sun Jan 13 11:10:08 2008
@@ -1,7 +1,7 @@
 // RUN: clang -fsyntax-only -verify -pedantic %s
 void foo() {
   *(0 ? (double *)0 : (void *)0) = 0;
-  *((void *) 0) = 0; // -expected-warning {{dereferencing void pointer}} -expected-error {{incomplete type 'void' is not assignable}}
+  *((void *) 0) = 0; // -expected-error {{incomplete type 'void' is not assignable}}
   double *dp;
   int *ip;
   void *vp;

Added: cfe/trunk/test/Sema/deref.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/deref.c?rev=45933&view=auto

==============================================================================
--- cfe/trunk/test/Sema/deref.c (added)
+++ cfe/trunk/test/Sema/deref.c Sun Jan 13 11:10:08 2008
@@ -0,0 +1,22 @@
+// RUN: clang -fsyntax-only -verify -std=c90 %s
+void
+foo (void)
+{
+ struct b;
+ struct b* x = 0;
+ struct b* y = &*x;
+}
+
+void foo2 (void)
+{
+ typedef int (*arrayptr)[];
+ arrayptr x = 0;
+ arrayptr y = &*x;
+}
+
+void foo3 (void)
+{
+ void* x = 0;
+ void* y = &*x; // expected-error {{invalid lvalue in address expression}}
+}
+





More information about the cfe-commits mailing list