diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-05-18 22:42:18 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-05-18 22:42:18 +0000 |
commit | fb4a5436839aae5f5599f2970997e23ee6b895b6 (patch) | |
tree | 8ae0c1e20cfd6a7a6938a58eccb0b2443ffc9c66 | |
parent | b12903e1a4b8d1b611b8c7e4f910665d628e68cd (diff) |
Implement C++ support for vector and extended vector types. This
involves extending implicit conversion sequences to model vector
conversions and vector splats, along with teaching the C++ conditional
operator-checking code about vector types.
Fixes <rdar://problem/7983501>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104081 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 57 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.h | 2 | ||||
-rw-r--r-- | test/SemaCXX/vector.cpp | 102 |
4 files changed, 181 insertions, 8 deletions
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index f337a429ca..f38bb1c96d 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -1777,10 +1777,6 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral); break; - case ICK_Complex_Real: - ImpCastExprToType(From, ToType, CastExpr::CK_Unknown); - break; - case ICK_Compatible_Conversion: ImpCastExprToType(From, ToType, CastExpr::CK_NoOp); break; @@ -1841,7 +1837,23 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; } - default: + case ICK_Vector_Conversion: + ImpCastExprToType(From, ToType, CastExpr::CK_BitCast); + break; + + case ICK_Vector_Splat: + ImpCastExprToType(From, ToType, CastExpr::CK_VectorSplat); + break; + + case ICK_Complex_Real: + ImpCastExprToType(From, ToType, CastExpr::CK_Unknown); + break; + + case ICK_Lvalue_To_Rvalue: + case ICK_Array_To_Pointer: + case ICK_Function_To_Pointer: + case ICK_Qualification: + case ICK_Num_Conversion_Kinds: assert(false && "Improper second standard conversion"); break; } @@ -1864,7 +1876,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; default: - assert(false && "Improper second standard conversion"); + assert(false && "Improper third standard conversion"); break; } @@ -2256,6 +2268,10 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, if (Context.getCanonicalType(LTy) == Context.getCanonicalType(RTy)) return LTy; + // Extension: conditional operator involving vector types. + if (LTy->isVectorType() || RTy->isVectorType()) + return CheckVectorOperands(QuestionLoc, LHS, RHS); + // -- The second and third operands have arithmetic or enumeration type; // the usual arithmetic conversions are performed to bring them to a // common type, and the result is of that type. diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 4c48e6159c..365daa6018 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -52,6 +52,8 @@ GetConversionCategory(ImplicitConversionKind Kind) { ICC_Conversion, ICC_Conversion, ICC_Conversion, + ICC_Conversion, + ICC_Conversion, ICC_Conversion }; return Category[(int)Kind]; @@ -80,6 +82,8 @@ ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind) { ICR_Conversion, ICR_Conversion, ICR_Conversion, + ICR_Conversion, + ICR_Conversion, ICR_Complex_Real_Conversion }; return Rank[(int)Kind]; @@ -102,12 +106,14 @@ const char* GetImplicitConversionName(ImplicitConversionKind Kind) { "Floating conversion", "Complex conversion", "Floating-integral conversion", - "Complex-real conversion", "Pointer conversion", "Pointer-to-member conversion", "Boolean conversion", "Compatible-types conversion", - "Derived-to-base conversion" + "Derived-to-base conversion", + "Vector conversion", + "Vector splat", + "Complex-real conversion" }; return Name[Kind]; } @@ -773,6 +779,48 @@ static bool IsNoReturnConversion(ASTContext &Context, QualType FromType, ResultTy = FromType; return true; } + +/// \brief Determine whether the conversion from FromType to ToType is a valid +/// vector conversion. +/// +/// \param ICK Will be set to the vector conversion kind, if this is a vector +/// conversion. +static bool IsVectorConversion(ASTContext &Context, QualType FromType, + QualType ToType, ImplicitConversionKind &ICK) { + // We need at least one of these types to be a vector type to have a vector + // conversion. + if (!ToType->isVectorType() && !FromType->isVectorType()) + return false; + + // Identical types require no conversions. + if (Context.hasSameUnqualifiedType(FromType, ToType)) + return false; + + // There are no conversions between extended vector types, only identity. + if (ToType->isExtVectorType()) { + // There are no conversions between extended vector types other than the + // identity conversion. + if (FromType->isExtVectorType()) + return false; + + // Vector splat from any arithmetic type to a vector. + if (!FromType->isVectorType() && FromType->isArithmeticType()) { + ICK = ICK_Vector_Splat; + return true; + } + } + + // If lax vector conversions are permitted and the vector types are of the + // same size, we can perform the conversion. + if (Context.getLangOptions().LaxVectorConversions && + FromType->isVectorType() && ToType->isVectorType() && + Context.getTypeSize(FromType) == Context.getTypeSize(ToType)) { + ICK = ICK_Vector_Conversion; + return true; + } + + return false; +} /// IsStandardConversion - Determines whether there is a standard /// conversion sequence (C++ [conv], C++ [over.ics.scs]) from the @@ -895,6 +943,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // For overloading in C, this can also be a "compatible-type" // conversion. bool IncompatibleObjC = false; + ImplicitConversionKind SecondICK = ICK_Identity; if (Context.hasSameUnqualifiedType(FromType, ToType)) { // The unqualified versions of the types are the same: there's no // conversion to do. @@ -956,10 +1005,14 @@ Sema::IsStandardConversion(Expr* From, QualType ToType, // Boolean conversions (C++ 4.12). SCS.Second = ICK_Boolean_Conversion; FromType = Context.BoolTy; + } else if (IsVectorConversion(Context, FromType, ToType, SecondICK)) { + SCS.Second = SecondICK; + FromType = ToType.getUnqualifiedType(); } else if (!getLangOptions().CPlusPlus && Context.typesAreCompatible(ToType, FromType)) { // Compatible conversions (Clang extension for C function overloading) SCS.Second = ICK_Compatible_Conversion; + FromType = ToType.getUnqualifiedType(); } else if (IsNoReturnConversion(Context, FromType, ToType, FromType)) { // Treat a conversion that strips "noreturn" as an identity conversion. SCS.Second = ICK_NoReturn_Adjustment; diff --git a/lib/Sema/SemaOverload.h b/lib/Sema/SemaOverload.h index cf16943826..8d261ddcbe 100644 --- a/lib/Sema/SemaOverload.h +++ b/lib/Sema/SemaOverload.h @@ -62,6 +62,8 @@ namespace clang { ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12) ICK_Compatible_Conversion, ///< Conversions between compatible types in C99 ICK_Derived_To_Base, ///< Derived-to-base (C++ [over.best.ics]) + ICK_Vector_Conversion, ///< Vector conversions + ICK_Vector_Splat, ///< A vector splat from an arithmetic type ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7) ICK_Num_Conversion_Kinds ///< The number of conversion kinds }; diff --git a/test/SemaCXX/vector.cpp b/test/SemaCXX/vector.cpp new file mode 100644 index 0000000000..ddbe902839 --- /dev/null +++ b/test/SemaCXX/vector.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify %s +typedef char char16 __attribute__ ((__vector_size__ (16))); +typedef long long longlong16 __attribute__ ((__vector_size__ (16))); +typedef char char16_e __attribute__ ((__ext_vector_type__ (16))); +typedef long long longlong16_e __attribute__ ((__ext_vector_type__ (2))); + +#if 1 +// Test overloading and function calls with vector types. +void f0(char16); + +void f0_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { + f0(c16); + f0(ll16); + f0(c16e); + f0(ll16e); +} + +int &f1(char16); // expected-note 2{{candidate function}} +float &f1(longlong16); // expected-note 2{{candidate function}} + +void f1_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { + int &ir1 = f1(c16); + float &fr1 = f1(ll16); + f1(c16e); // expected-error{{call to 'f1' is ambiguous}} + f1(ll16e); // expected-error{{call to 'f1' is ambiguous}} +} + +void f2(char16_e); // expected-note{{no known conversion from 'longlong16_e' to 'char16_e' for 1st argument}} + +void f2_test(char16 c16, longlong16 ll16, char16_e c16e, longlong16_e ll16e) { + f2(c16); + f2(ll16); + f2(c16e); + f2(ll16e); // expected-error{{no matching function}} + f2('a'); + f2(17); +} +#endif + +// Test the conditional operator with vector types. +void conditional(bool Cond, char16 c16, longlong16 ll16, char16_e c16e, + longlong16_e ll16e) { + // Conditional operators with the same type. + __typeof__(Cond? c16 : c16) *c16p1 = &c16; + __typeof__(Cond? ll16 : ll16) *ll16p1 = &ll16; + __typeof__(Cond? c16e : c16e) *c16ep1 = &c16e; + __typeof__(Cond? ll16e : ll16e) *ll16ep1 = &ll16e; + + // Conditional operators with similar types. + __typeof__(Cond? c16 : c16e) *c16ep2 = &c16e; + __typeof__(Cond? c16e : c16) *c16ep3 = &c16e; + __typeof__(Cond? ll16 : ll16e) *ll16ep2 = &ll16e; + __typeof__(Cond? ll16e : ll16) *ll16ep3 = &ll16e; + + // Conditional operators with incompatible types. + (void)(Cond? c16 : ll16); // expected-error{{can't convert between vector values}} + (void)(Cond? ll16e : c16e); // expected-error{{can't convert between vector values}} + (void)(Cond? ll16e : c16); // expected-error{{can't convert between vector values}} +} + +// Test C++ cast'ing of vector types. +void casts(longlong16 ll16, longlong16_e ll16e) { + // C-style casts. + (void)(char16)ll16; + (void)(char16_e)ll16; + (void)(longlong16)ll16; + (void)(longlong16_e)ll16; + (void)(char16)ll16e; + (void)(char16_e)ll16e; + (void)(longlong16)ll16e; + (void)(longlong16_e)ll16e; + + // Function-style casts. + (void)char16(ll16); + (void)char16_e(ll16); + (void)longlong16(ll16); + (void)longlong16_e(ll16); + (void)char16(ll16e); + (void)char16_e(ll16e); + (void)longlong16(ll16e); + (void)longlong16_e(ll16e); + + // static_cast + (void)static_cast<char16>(ll16); + (void)static_cast<char16_e>(ll16); + (void)static_cast<longlong16>(ll16); + (void)static_cast<longlong16_e>(ll16); + (void)static_cast<char16>(ll16e); + (void)static_cast<char16_e>(ll16e); // expected-error{{static_cast from 'longlong16_e' to 'char16_e' is not allowed}} + (void)static_cast<longlong16>(ll16e); + (void)static_cast<longlong16_e>(ll16e); + + // reinterpret_cast + (void)reinterpret_cast<char16>(ll16); + (void)reinterpret_cast<char16_e>(ll16); + (void)reinterpret_cast<longlong16>(ll16); + (void)reinterpret_cast<longlong16_e>(ll16); + (void)reinterpret_cast<char16>(ll16e); + (void)reinterpret_cast<char16_e>(ll16e); + (void)reinterpret_cast<longlong16>(ll16e); + (void)reinterpret_cast<longlong16_e>(ll16e); +} |