]> granicus.if.org Git - clang/commitdiff
Support for Transparent unions used as overloadable
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 23 Mar 2011 19:50:54 +0000 (19:50 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 23 Mar 2011 19:50:54 +0000 (19:50 +0000)
function parameter. // rdar:// 9129552
and PR9406.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128159 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Overload.h
lib/Sema/SemaExprCXX.cpp
lib/Sema/SemaOverload.cpp
test/Sema/overloaded-func-transparent-union.c [new file with mode: 0644]

index 6e07d2c68a02e1f7d16b269453b7c8e59b179139..e196e83a0e26de4486ee32f0d692b9fb77ed5f8f 100644 (file)
@@ -76,6 +76,7 @@ namespace clang {
     ICK_Vector_Splat,          ///< A vector splat from an arithmetic type
     ICK_Complex_Real,          ///< Complex-real conversions (C99 6.3.1.7)
     ICK_Block_Pointer_Conversion,    ///< Block Pointer conversions 
+    ICK_TransparentUnionConversion, /// Transparent Union Conversions
     ICK_Num_Conversion_Kinds   ///< The number of conversion kinds
   };
 
index 0a8bd8fb526741397c3c447d8d4da20b6af30c2e..36079c2ce7fcec2f5f0a5075a99dbb66014053e4 100644 (file)
@@ -2277,6 +2277,15 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
       break;
     }
       
+  case ICK_TransparentUnionConversion: {
+    Sema::AssignConvertType ConvTy =
+      CheckTransparentUnionArgumentConstraints(ToType, From);
+    assert ((ConvTy == Sema::Compatible) &&
+            "Improper transparent union conversion");
+    (void)ConvTy;
+    break;
+  }
+
   case ICK_Lvalue_To_Rvalue:
   case ICK_Array_To_Pointer:
   case ICK_Function_To_Pointer:
index 7a4e68d3cbb12273322367d73aff5f4e1ab5da02..6fa78a9a462994ad2db32bbb059e103fff91201a 100644 (file)
@@ -48,6 +48,12 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
                                  bool InOverloadResolution,
                                  StandardConversionSequence &SCS,
                                  bool CStyle);
+  
+static bool IsTransparentUnionStandardConversion(Sema &S, Expr* From, 
+                                                 QualType &ToType,
+                                                 bool InOverloadResolution,
+                                                 StandardConversionSequence &SCS,
+                                                 bool CStyle);
 static OverloadingResult
 IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
                         UserDefinedConversionSequence& User,
@@ -128,7 +134,9 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) {
     ICR_Conversion,
     ICR_Conversion,
     ICR_Conversion,
-    ICR_Complex_Real_Conversion
+    ICR_Complex_Real_Conversion,
+    ICR_Conversion,
+    ICR_Conversion
   };
   return Rank[(int)Kind];
 }
@@ -157,7 +165,9 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
     "Derived-to-base conversion",
     "Vector conversion",
     "Vector splat",
-    "Complex-real conversion"
+    "Complex-real conversion",
+    "Block Pointer conversion",
+    "Transparent Union Conversion"
   };
   return Name[Kind];
 }
@@ -1203,6 +1213,11 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
   } else if (IsNoReturnConversion(S.Context, FromType, ToType, FromType)) {
     // Treat a conversion that strips "noreturn" as an identity conversion.
     SCS.Second = ICK_NoReturn_Adjustment;
+  } else if (IsTransparentUnionStandardConversion(S, From, ToType,
+                                             InOverloadResolution,
+                                             SCS, CStyle)) {
+    SCS.Second = ICK_TransparentUnionConversion;
+    FromType = ToType;
   } else {
     // No second conversion required.
     SCS.Second = ICK_Identity;
@@ -1244,6 +1259,30 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
 
   return true;
 }
+  
+static bool
+IsTransparentUnionStandardConversion(Sema &S, Expr* From, 
+                                     QualType &ToType,
+                                     bool InOverloadResolution,
+                                     StandardConversionSequence &SCS,
+                                     bool CStyle) {
+    
+  const RecordType *UT = ToType->getAsUnionType();
+  if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>())
+    return false;
+  // The field to initialize within the transparent union.
+  RecordDecl *UD = UT->getDecl();
+  // It's compatible if the expression matches any of the fields.
+  for (RecordDecl::field_iterator it = UD->field_begin(),
+       itend = UD->field_end();
+       it != itend; ++it) {
+    if (IsStandardConversion(S, From, it->getType(), InOverloadResolution, SCS, CStyle)) {
+      ToType = it->getType();
+      return true;
+    }
+  }
+  return false;
+}
 
 /// IsIntegralPromotion - Determines whether the conversion from the
 /// expression From (whose potentially-adjusted type is FromType) to
diff --git a/test/Sema/overloaded-func-transparent-union.c b/test/Sema/overloaded-func-transparent-union.c
new file mode 100644 (file)
index 0000000..fa0314e
--- /dev/null
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+// rdar:// 9129552
+// PR9406
+
+typedef struct {
+       char *str;
+       char *str2;
+} Class;
+
+typedef union {
+       Class *object;
+} Instance __attribute__((transparent_union));
+
+__attribute__((overloadable)) void Class_Init(Instance this, char *str, void *str2) {
+       this.object->str  = str;
+       this.object->str2 = str2;
+}
+
+__attribute__((overloadable)) void Class_Init(Instance this, char *str) {
+       this.object->str  = str;
+       this.object->str2 = str;
+}
+
+int main(void) {
+       Class obj;
+       Class_Init(&obj, "Hello ", " World");
+}
+