diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index c2880a0ad138..08611c32c692 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2541,23 +2541,27 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef) const { case CXXFunctionalCastExprClass: case CXXStaticCastExprClass: case ImplicitCastExprClass: - case CStyleCastExprClass: + case CStyleCastExprClass: { + const CastExpr *CE = cast(this); + + // Handle bitcasts of vector constants. + if (getType()->isVectorType() && CE->getCastKind() == CK_BitCast) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + // Handle casts with a destination that's a struct or union; this // deals with both the gcc no-op struct cast extension and the // cast-to-union extension. if (getType()->isRecordType()) - return cast(this)->getSubExpr() - ->isConstantInitializer(Ctx, false); - + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + // Integer->integer casts can be handled here, which is important for // things like (int)(&&x-&&y). Scary but true. if (getType()->isIntegerType() && - cast(this)->getSubExpr()->getType()->isIntegerType()) - return cast(this)->getSubExpr() - ->isConstantInitializer(Ctx, false); - + CE->getSubExpr()->getType()->isIntegerType()) + return CE->getSubExpr()->isConstantInitializer(Ctx, false); + break; - + } case MaterializeTemporaryExprClass: return cast(this)->GetTemporaryExpr() ->isConstantInitializer(Ctx, false); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 438bef5de876..6a290a6c8340 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2502,11 +2502,9 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { const VectorType *VTy = E->getType()->castAs(); - QualType EltTy = VTy->getElementType(); unsigned NElts = VTy->getNumElements(); - unsigned EltWidth = Info.Ctx.getTypeSize(EltTy); - const Expr* SE = E->getSubExpr(); + const Expr *SE = E->getSubExpr(); QualType SETy = SE->getType(); switch (E->getCastKind()) { @@ -2530,34 +2528,6 @@ bool VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { SmallVector Elts(NElts, Val); return Success(Elts, E); } - case CK_BitCast: { - // FIXME: this is wrong for any cast other than a no-op cast. - if (SETy->isVectorType()) - return Visit(SE); - - if (!SETy->isIntegerType()) - return Error(E); - - APSInt Init; - if (!EvaluateInteger(SE, Init, Info)) - return Error(E); - - assert((EltTy->isIntegerType() || EltTy->isRealFloatingType()) && - "Vectors must be composed of ints or floats"); - - SmallVector Elts; - for (unsigned i = 0; i != NElts; ++i) { - APSInt Tmp = Init.extOrTrunc(EltWidth); - - if (EltTy->isIntegerType()) - Elts.push_back(APValue(Tmp)); - else - Elts.push_back(APValue(APFloat(Tmp))); - - Init >>= EltWidth; - } - return Success(Elts, E); - } default: return ExprEvaluatorBaseTy::VisitCastExpr(E); } diff --git a/clang/test/CodeGen/altivec.c b/clang/test/CodeGen/altivec.c index c3b1f42e06d8..bd694a6a56de 100644 --- a/clang/test/CodeGen/altivec.c +++ b/clang/test/CodeGen/altivec.c @@ -5,6 +5,15 @@ vector int test0 = (vector int)(1); // CHECK: @test0 = global <4 x i32> vector float test1 = (vector float)(1.0); // CHECK: @test1 = global <4 x float> +// CHECK: @v1 = global <16 x i8> bitcast (<4 x i32> to <16 x i8>) +vector char v1 = (vector char)((vector int)(1, 2, 3, 4)); +// CHECK: @v2 = global <16 x i8> bitcast (<4 x float> to <16 x i8>) +vector char v2 = (vector char)((vector float)(1.0f, 2.0f, 3.0f, 4.0f)); +// CHECK: @v3 = global <16 x i8> bitcast (<4 x i32> to <16 x i8>) +vector char v3 = (vector char)((vector int)('a', 'b', 'c', 'd')); +// CHECK: @v4 = global <4 x i32> bitcast (<16 x i8> to <4 x i32>) +vector int v4 = (vector char){1, 2, 3, 4}; + void test2() { vector int vi;