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(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,