OpenCL 1.0 support: explicit casts to ext-vector types
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74247 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 5343ceb..62e0eb3 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1860,6 +1860,9 @@
def err_collection_expr_type : Error<
"collection expression type %0 is not a valid object">;
+def err_invalid_conversion_between_ext_vectors : Error<
+ "invalid conversion between ext-vector type %0 and %1">;
+
// Type
def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
def warn_receiver_forward_class : Warning<
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 36f3ff9..48e6772 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3063,6 +3063,13 @@
// returns true if the cast is invalid
bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+ // CheckExtVectorCast - check type constraints for extended vectors.
+ // Since vectors are an extension, there are no C standard reference for this.
+ // We allow casting between vectors and integer datatypes of the same size,
+ // or vectors and the element type of that vector.
+ // returns true if the cast is invalid
+ bool CheckExtVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+
/// CheckMessageArgumentTypes - Check types in an Obj-C message send.
/// \param Method - May be null.
/// \param [out] ReturnType - The return type of the send.
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a01fbb1..3d22321 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2876,12 +2876,15 @@
return Diag(castExpr->getLocStart(),
diag::err_typecheck_expect_scalar_operand)
<< castExpr->getType() << castExpr->getSourceRange();
- } else if (castExpr->getType()->isVectorType()) {
- if (CheckVectorCast(TyR, castExpr->getType(), castType))
+ } else if (castType->isExtVectorType()) {
+ if (CheckExtVectorCast(TyR, castType, castExpr->getType()))
return true;
} else if (castType->isVectorType()) {
if (CheckVectorCast(TyR, castType, castExpr->getType()))
return true;
+ } else if (castExpr->getType()->isVectorType()) {
+ if (CheckVectorCast(TyR, castExpr->getType(), castType))
+ return true;
} else if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr)) {
return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR;
} else if (!castType->isArithmeticType()) {
@@ -2919,6 +2922,35 @@
return false;
}
+bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) {
+ assert(DestTy->isExtVectorType() && "Not an extended vector type!");
+
+ // If SrcTy is also an ExtVectorType, the types must be identical unless
+ // lax vector conversions is enabled.
+ if (SrcTy->isExtVectorType()) {
+ if (getLangOptions().LaxVectorConversions &&
+ Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy))
+ return false;
+ if (DestTy != SrcTy)
+ return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ << DestTy << SrcTy << R;
+ return false;
+ }
+
+ // If SrcTy is a VectorType, then only the total size must match.
+ if (SrcTy->isVectorType()) {
+ if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))
+ return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)
+ << DestTy << SrcTy << R;
+ return false;
+ }
+
+ // All scalar -> ext vector "c-style" casts are legal; the appropriate
+ // conversion will take place first from scalar to elt type, and then
+ // splat from elt type to vector.
+ return false;
+}
+
Action::OwningExprResult
Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprArg Op) {
diff --git a/test/Sema/ext_vector_casts.c b/test/Sema/ext_vector_casts.c
new file mode 100644
index 0000000..8aa762e
--- /dev/null
+++ b/test/Sema/ext_vector_casts.c
@@ -0,0 +1,23 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+typedef __attribute__(( ext_vector_type(2) )) float float2;
+typedef __attribute__(( ext_vector_type(4) )) int int4;
+typedef __attribute__(( ext_vector_type(4) )) float float4;
+typedef float t3 __attribute__ ((vector_size (16)));
+
+static void test() {
+ float2 vec2;
+ float4 vec4, vec4_2;
+ int4 ivec4;
+ t3 vec4_3;
+
+ vec4 = (float4)5.0f;
+ vec4 = (float4)5;
+ vec4 = (float4)vec4_3;
+
+ ivec4 = (int4)5.0f;
+ ivec4 = (int4)5;
+ ivec4 = (int4)vec4_3;
+
+ vec4 = (float4)vec2; // expected-error {{invalid conversion between ext-vector type 'float4' and 'float2'}}
+}
diff --git a/test/Sema/vector-cast.c b/test/Sema/vector-cast.c
index bd09e69..9460cac 100644
--- a/test/Sema/vector-cast.c
+++ b/test/Sema/vector-cast.c
@@ -11,9 +11,9 @@
t3 v3;
v2 = (t2)v1; // -expected-error {{invalid conversion between vector type \
-'t1' and 't2' of different size}}
- v1 = (t1)v2; // -expected-error {{invalid conversion between vector type \
't2' and 't1' of different size}}
+ v1 = (t1)v2; // -expected-error {{invalid conversion between vector type \
+'t1' and 't2' of different size}}
v3 = (t3)v2;
v1 = (t1)(char *)10; // -expected-error {{invalid conversion between vector \