aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Sema/Sema.h3
-rw-r--r--Sema/SemaExpr.cpp33
-rw-r--r--include/clang/Basic/DiagnosticKinds.def9
-rw-r--r--test/Sema/vector-cast.c30
4 files changed, 73 insertions, 2 deletions
diff --git a/Sema/Sema.h b/Sema/Sema.h
index c879146760..21a7cdcbfc 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -696,6 +696,9 @@ private:
QualType ElementType, bool isStatic,
int &nInitializers, bool &hadError);
+ // returns true if the cast is invalid
+ bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty);
+
// returns true if there were any incompatible arguments.
bool CheckMessageArgumentTypes(Expr **Args, unsigned NumArgs,
ObjcMethodDecl *Method);
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index dcec7253ea..2cea607343 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -703,6 +703,28 @@ ActOnInitList(SourceLocation LBraceLoc, ExprTy **initlist, unsigned NumInit,
return e;
}
+bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty)
+{
+ assert(VectorTy->isVectorType() && "Not a vector type!");
+
+ if (Ty->isVectorType() || Ty->isIntegerType()) {
+ if (Context.getTypeSize(VectorTy, SourceLocation()) !=
+ Context.getTypeSize(Ty, SourceLocation()))
+ return Diag(R.getBegin(),
+ Ty->isVectorType() ?
+ diag::err_invalid_conversion_between_vectors :
+ diag::err_invalid_conversion_between_vector_and_integer,
+ VectorTy.getAsString().c_str(),
+ Ty.getAsString().c_str(), R);
+ } else
+ return Diag(R.getBegin(),
+ diag::err_invalid_conversion_between_vector_and_scalar,
+ VectorTy.getAsString().c_str(),
+ Ty.getAsString().c_str(), R);
+
+ return false;
+}
+
Action::ExprResult Sema::
ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
SourceLocation RParenLoc, ExprTy *Op) {
@@ -719,10 +741,19 @@ ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty,
if (!castType->isScalarType())
return Diag(LParenLoc, diag::err_typecheck_cond_expect_scalar,
castType.getAsString(), SourceRange(LParenLoc, RParenLoc));
- if (!castExpr->getType()->isScalarType()) {
+ if (!castExpr->getType()->isScalarType())
return Diag(castExpr->getLocStart(),
diag::err_typecheck_expect_scalar_operand,
castExpr->getType().getAsString(),castExpr->getSourceRange());
+
+ if (castExpr->getType()->isVectorType()) {
+ if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc),
+ castExpr->getType(), castType))
+ return true;
+ } else if (castType->isVectorType()) {
+ if (CheckVectorCast(SourceRange(LParenLoc, RParenLoc),
+ castType, castExpr->getType()))
+ return true;
}
}
return new CastExpr(castType, castExpr, LParenLoc);
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index f847453dd1..8f1945959d 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -799,7 +799,14 @@ DIAG(err_invalid_type_in_asm_input, ERROR,
"invalid type '%0' in asm input")
DIAG(err_unknown_register_name_in_asm, ERROR,
"unknown register name '%0' in asm")
-
+DIAG(err_invalid_conversion_between_vectors, ERROR,
+ "invalid conversion between vector type '%0' and '%1' of different size")
+DIAG(err_invalid_conversion_between_vector_and_integer, ERROR,
+ "invalid conversion between vector type '%0' and integer type '%1' "
+ "of different size")
+DIAG(err_invalid_conversion_between_vector_and_scalar, ERROR,
+ "invalid conversion between vector type '%0' and scalar type '%1'")
+
// CHECK: printf format string errors
DIAG(warn_printf_not_string_constant, WARNING,
"format string is not a string literal (potentially insecure)")
diff --git a/test/Sema/vector-cast.c b/test/Sema/vector-cast.c
new file mode 100644
index 0000000000..111430b1c1
--- /dev/null
+++ b/test/Sema/vector-cast.c
@@ -0,0 +1,30 @@
+// RUN: clang -fsyntax-only %s -verify
+
+typedef long long t1 __attribute__ ((vector_size (8)));
+typedef char t2 __attribute__ ((vector_size (16)));
+typedef float t3 __attribute__ ((vector_size (16)));
+
+void f()
+{
+ t1 v1;
+ t2 v2;
+ 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}}
+ v3 = (t3)v2;
+
+ v1 = (t1)(char *)10; // -expected-error {{invalid conversion between vector \
+type 't1' and scalar type 'char *'}}
+ v1 = (t1)(long long)10;
+ v1 = (t1)(short)10; // -expected-error {{invalid conversion between vector \
+type 't1' and integer type 'int' of different size}}
+
+ long long r1 = (long long)v1;
+ short r2 = (short)v1; // -expected-error {{invalid conversion between vector \
+type 't1' and integer type 'short' of different size}}
+ char *r3 = (char *)v1; // -expected-error {{invalid conversion between vector\
+ type 't1' and scalar type 'char *'}}
+}