[cfe-commits] r62255 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def lib/Sema/SemaExpr.cpp test/Sema/cast-to-union.c

Seo Sanghyeon sanxiyn at gmail.com
Wed Jan 14 20:51:39 PST 2009


Author: sanxiyn
Date: Wed Jan 14 22:51:39 2009
New Revision: 62255

URL: http://llvm.org/viewvc/llvm-project?rev=62255&view=rev
Log:
PR2746: Implement GCC cast to union extension

Added:
    cfe/trunk/test/Sema/cast-to-union.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/Sema/SemaExpr.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jan 14 22:51:39 2009
@@ -1427,6 +1427,10 @@
      "C99 forbids conditional expressions with only one void side")
 DIAG(ext_typecheck_cast_nonscalar, EXTENSION,
      "C99 forbids casting nonscalar type %0 to the same type")
+DIAG(ext_typecheck_cast_to_union, EXTENSION,
+     "C99 forbids casts to union type")
+DIAG(err_typecheck_cast_to_union_no_type, ERROR,
+     "cast to union type from type %0 not present in union")
 DIAG(err_typecheck_expect_scalar_operand, ERROR,
      "operand of type %0 where arithmetic or pointer type is required")
 DIAG(err_typecheck_cond_incompatible_operands, ERROR,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jan 14 22:51:39 2009
@@ -1929,18 +1929,33 @@
   } else if (castType->isDependentType() || castExpr->isTypeDependent()) {
     // We can't check any more until template instantiation time.
   } else if (!castType->isScalarType() && !castType->isVectorType()) {
-    // GCC struct/union extension: allow cast to self.
-    if (Context.getCanonicalType(castType).getUnqualifiedType() !=
-        Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) ||
-        (!castType->isStructureType() && !castType->isUnionType())) {
+    if (Context.getCanonicalType(castType).getUnqualifiedType() ==
+        Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) &&
+        (castType->isStructureType() || castType->isUnionType())) {
+      // GCC struct/union extension: allow cast to self.
+      Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
+        << castType << castExpr->getSourceRange();
+    } else if (castType->isUnionType()) {
+      // GCC cast to union extension
+      RecordDecl *RD = castType->getAsRecordType()->getDecl();
+      RecordDecl::field_iterator Field, FieldEnd;
+      for (Field = RD->field_begin(), FieldEnd = RD->field_end();
+           Field != FieldEnd; ++Field) {
+        if (Context.getCanonicalType(Field->getType()).getUnqualifiedType() ==
+            Context.getCanonicalType(castExpr->getType()).getUnqualifiedType()) {
+          Diag(TyR.getBegin(), diag::ext_typecheck_cast_to_union)
+            << castExpr->getSourceRange();
+          break;
+        }
+      }
+      if (Field == FieldEnd)
+        return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)
+          << castExpr->getType() << castExpr->getSourceRange();
+    } else {
       // Reject any other conversions to non-scalar types.
       return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar)
         << castType << castExpr->getSourceRange();
     }
-      
-    // accept this, but emit an ext-warn.
-    Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)
-      << castType << castExpr->getSourceRange();
   } else if (!castExpr->getType()->isScalarType() && 
              !castExpr->getType()->isVectorType()) {
     return Diag(castExpr->getLocStart(),

Added: cfe/trunk/test/Sema/cast-to-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/cast-to-union.c?rev=62255&view=auto

==============================================================================
--- cfe/trunk/test/Sema/cast-to-union.c (added)
+++ cfe/trunk/test/Sema/cast-to-union.c Wed Jan 14 22:51:39 2009
@@ -0,0 +1,9 @@
+// RUN: clang -fsyntax-only -verify -pedantic %s
+
+union u { int i; };
+void f(union u);
+
+void test(int x) {
+  f((union u)x); // expected-warning {{C99 forbids casts to union type}}
+  f((union u)&x); // expected-error {{cast to union type from type 'int *' not present in union}}
+}





More information about the cfe-commits mailing list