diff options
-rw-r--r-- | include/clang/Sema/Overload.h | 1 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 43 | ||||
-rw-r--r-- | test/Sema/overloaded-func-transparent-union.c | 28 |
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"); +} + |