[cfe-commits] r117243 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp test/CodeGen/transparent-union.c test/Sema/transparent-union.c

Peter Collingbourne peter at pcc.me.uk
Sun Oct 24 11:30:18 PDT 2010


Author: pcc
Date: Sun Oct 24 13:30:18 2010
New Revision: 117243

URL: http://llvm.org/viewvc/llvm-project?rev=117243&view=rev
Log:
Implement GNU C extension: two types are compatible if they appear
as a function argument, one of the types is a transparent union type
and the other type is compatible with a union member

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/test/CodeGen/transparent-union.c
    cfe/trunk/test/Sema/transparent-union.c

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=117243&r1=117242&r2=117243&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sun Oct 24 13:30:18 2010
@@ -1290,6 +1290,12 @@
                       bool Unqualified = false);
   QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false,
                               bool Unqualified = false);
+  QualType mergeFunctionArgumentTypes(QualType, QualType,
+                                      bool OfBlockPointer=false,
+                                      bool Unqualified = false);
+  QualType mergeTransparentUnionType(QualType, QualType,
+                                     bool OfBlockPointer=false,
+                                     bool Unqualified = false);
   
   QualType mergeObjCGCQualifiers(QualType, QualType);
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=117243&r1=117242&r2=117243&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sun Oct 24 13:30:18 2010
@@ -4674,6 +4674,49 @@
   return !mergeTypes(LHS, RHS, true).isNull();
 }
 
+/// mergeTransparentUnionType - if T is a transparent union type and a member
+/// of T is compatible with SubType, return the merged type, else return
+/// QualType()
+QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType,
+                                               bool OfBlockPointer,
+                                               bool Unqualified) {
+  if (const RecordType *UT = T->getAsUnionType()) {
+    RecordDecl *UD = UT->getDecl();
+    if (UD->hasAttr<TransparentUnionAttr>()) {
+      for (RecordDecl::field_iterator it = UD->field_begin(),
+           itend = UD->field_end(); it != itend; ++it) {
+        QualType ET = it->getType();
+        QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified);
+        if (!MT.isNull())
+          return MT;
+      }
+    }
+  }
+
+  return QualType();
+}
+
+/// mergeFunctionArgumentTypes - merge two types which appear as function
+/// argument types
+QualType ASTContext::mergeFunctionArgumentTypes(QualType lhs, QualType rhs, 
+                                                bool OfBlockPointer,
+                                                bool Unqualified) {
+  // GNU extension: two types are compatible if they appear as a function
+  // argument, one of the types is a transparent union type and the other
+  // type is compatible with a union member
+  QualType lmerge = mergeTransparentUnionType(lhs, rhs, OfBlockPointer,
+                                              Unqualified);
+  if (!lmerge.isNull())
+    return lmerge;
+
+  QualType rmerge = mergeTransparentUnionType(rhs, lhs, OfBlockPointer,
+                                              Unqualified);
+  if (!rmerge.isNull())
+    return rmerge;
+
+  return mergeTypes(lhs, rhs, OfBlockPointer, Unqualified);
+}
+
 QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, 
                                         bool OfBlockPointer,
                                         bool Unqualified) {
@@ -4751,8 +4794,9 @@
     for (unsigned i = 0; i < lproto_nargs; i++) {
       QualType largtype = lproto->getArgType(i).getUnqualifiedType();
       QualType rargtype = rproto->getArgType(i).getUnqualifiedType();
-      QualType argtype = mergeTypes(largtype, rargtype, OfBlockPointer,
-                                    Unqualified);
+      QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype,
+                                                    OfBlockPointer,
+                                                    Unqualified);
       if (argtype.isNull()) return QualType();
       
       if (Unqualified)

Modified: cfe/trunk/test/CodeGen/transparent-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/transparent-union.c?rev=117243&r1=117242&r2=117243&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/transparent-union.c (original)
+++ cfe/trunk/test/CodeGen/transparent-union.c Sun Oct 24 13:30:18 2010
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o %t %s
+// RUN: %clang_cc1 -Werror -triple i386-unknown-unknown -emit-llvm -o %t %s
 // RUN: FileCheck < %t %s
 //
 // FIXME: Note that we don't currently get the ABI right here. f0() should be
@@ -12,9 +12,12 @@
 
 // CHECK: define void @f1_0(i32* %a0) 
 // CHECK:  call void @f0(%union.anon* byval %{{.*}})
+// CHECK:  call void %{{.*}}(i8* %{{[a-z0-9]*}})
 // CHECK: }
 void f1_0(int *a0) {
+  void (*f0p)(void *) = f0;
   f0(a0);
+  f0p(a0);
 }
 
 void f1_1(int *a0) {

Modified: cfe/trunk/test/Sema/transparent-union.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/transparent-union.c?rev=117243&r1=117242&r2=117243&view=diff
==============================================================================
--- cfe/trunk/test/Sema/transparent-union.c (original)
+++ cfe/trunk/test/Sema/transparent-union.c Sun Oct 24 13:30:18 2010
@@ -17,6 +17,24 @@
   tu.ip = ip;
 }
 
+/* Test ability to redeclare a function taking a transparent_union arg
+   with various compatible and incompatible argument types. */
+
+void fip(TU);
+void fip(int *i) {}
+
+void ffp(TU);
+void ffp(float *f) {}
+
+void fvp(TU); // expected-note{{previous declaration is here}}
+void fvp(void *p) {} // expected-error{{conflicting types}}
+
+void fsp(TU); // expected-note{{previous declaration is here}}
+void fsp(short *s) {} // expected-error{{conflicting types}}
+
+void fi(TU); // expected-note{{previous declaration is here}}
+void fi(int i) {} // expected-error{{conflicting types}}
+
 /* FIXME: we'd like to just use an "int" here and align it differently
    from the normal "int", but if we do so we lose the alignment
    information from the typedef within the compiler. */





More information about the cfe-commits mailing list