aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Sema/Overload.h1
-rw-r--r--lib/Sema/SemaExprCXX.cpp9
-rw-r--r--lib/Sema/SemaOverload.cpp43
-rw-r--r--test/Sema/overloaded-func-transparent-union.c28
4 files changed, 79 insertions, 2 deletions
diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h
index 6e07d2c68a..e196e83a0e 100644
--- a/include/clang/Sema/Overload.h
+++ b/include/clang/Sema/Overload.h
@@ -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
};
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 0a8bd8fb52..36079c2ce7 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -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:
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 7a4e68d3cb..6fa78a9a46 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -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
index 0000000000..fa0314e946
--- /dev/null
+++ b/test/Sema/overloaded-func-transparent-union.c
@@ -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");
+}
+