From a64db8fa2a7b4e24d0aeef7c22046fa37d8f1f3b Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 27 Nov 2007 05:51:55 +0000 Subject: [PATCH] Report errors for invalid casts from/to vectors. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44350 91177308-0d34-0410-b5e6-96231b3b80d8 --- Sema/Sema.h | 3 +++ Sema/SemaExpr.cpp | 33 ++++++++++++++++++++++++- include/clang/Basic/DiagnosticKinds.def | 9 ++++++- test/Sema/vector-cast.c | 30 ++++++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 test/Sema/vector-cast.c 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 *'}} +} -- 2.50.1