On Jan 12, 2008 11:14 PM, Eli Friedman <[EMAIL PROTECTED]> wrote:
> Take the following two testcases:
>
> 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;
> }
>
> Currently, clang rejects both of these.
> Here is another test:
> void foo3 (void)
> {
>   void* x = 0;
>   void* y = &*x;
> }

Attached is a patch which makes all of these testcases work correctly
(as far as I can tell).  Essentially, this just removes the error for
a completely legal construct and fixes up the void* case to work per
C99.

-Eli
Index: Sema/SemaExpr.cpp
===================================================================
--- Sema/SemaExpr.cpp   (revision 45920)
+++ Sema/SemaExpr.cpp   (working copy)
@@ -1618,6 +1626,18 @@
 /// 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();
   
@@ -1652,17 +1672,11 @@
   
   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();
-      }
-    }
+    // 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 ptype;
   }
   Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer, 
_______________________________________________
cfe-dev mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

Reply via email to