Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -2685,6 +2685,8 @@ "mode attribute only supported for integer and floating-point types">; def err_mode_wrong_type : Error< "type of machine mode does not match type of base type">; +def err_complex_mode_vector_type : Error< + "type of machine mode does not support base vector types">; def err_attr_wrong_decl : Error< "%0 attribute invalid on this declaration, requires typedef or value">; def warn_attribute_nonnull_no_pointers : Warning< Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp @@ -3154,16 +3154,22 @@ return; } - if (!OldTy->getAs() && !OldTy->isComplexType()) + // Base type can also be a vector type (see PR17453). + // Distinguish between base type and base element type. + QualType OldElemTy = OldTy; + if (const VectorType *VT = OldTy->getAs()) + OldElemTy = VT->getElementType(); + + if (!OldElemTy->getAs() && !OldElemTy->isComplexType()) S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); else if (IntegerMode) { - if (!OldTy->isIntegralOrEnumerationType()) + if (!OldElemTy->isIntegralOrEnumerationType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else if (ComplexMode) { - if (!OldTy->isComplexType()) + if (!OldElemTy->isComplexType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } else { - if (!OldTy->isFloatingType()) + if (!OldElemTy->isFloatingType()) S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); } @@ -3176,21 +3182,40 @@ return; } - QualType NewTy; + QualType NewElemTy; if (IntegerMode) - NewTy = S.Context.getIntTypeForBitwidth(DestWidth, - OldTy->isSignedIntegerType()); + NewElemTy = S.Context.getIntTypeForBitwidth( + DestWidth, OldElemTy->isSignedIntegerType()); else - NewTy = S.Context.getRealTypeForBitwidth(DestWidth); + NewElemTy = S.Context.getRealTypeForBitwidth(DestWidth); - if (NewTy.isNull()) { + if (NewElemTy.isNull()) { S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name; return; } if (ComplexMode) { - NewTy = S.Context.getComplexType(NewTy); + NewElemTy = S.Context.getComplexType(NewElemTy); + } + + QualType NewTy = NewElemTy; + if (const VectorType *OldVT = OldTy->getAs()) { + // Complex machine mode does not support base vector types. + if (ComplexMode) { + S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type); + return; + } + unsigned NumElements = S.Context.getTypeSize(OldElemTy) * + OldVT->getNumElements() / + S.Context.getTypeSize(NewElemTy); + NewTy = + S.Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind()); + } + + if (NewTy.isNull()) { + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + return; } // Install the new type. Index: cfe/trunk/test/CodeGen/attr-mode-vector-types.c =================================================================== --- cfe/trunk/test/CodeGen/attr-mode-vector-types.c +++ cfe/trunk/test/CodeGen/attr-mode-vector-types.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -emit-llvm -o - | FileCheck %s + +typedef int __attribute__((mode(byte))) __attribute__((vector_size(4))) vec_t1; +typedef int __attribute__((mode(QI))) __attribute__((vector_size(8))) vec_t2; +typedef int __attribute__((mode(SI))) __attribute__((vector_size(16))) vec_t3; +typedef int __attribute__((mode(DI))) __attribute__((vector_size(64)))vec_t4; +typedef float __attribute__((mode(SF))) __attribute__((vector_size(128))) vec_t5; +typedef float __attribute__((mode(DF))) __attribute__((vector_size(256))) vec_t6; + +void check() { + // CHECK: alloca <4 x i8> + vec_t1 v1; + // CHECK: alloca <8 x i8> + vec_t2 v2; + // CHECK: alloca <4 x i32> + vec_t3 v3; + // CHECK: alloca <8 x i64> + vec_t4 v4; + // CHECK: alloca <32 x float> + vec_t5 v5; + // CHECK: alloca <32 x double> + vec_t6 v6; +} + +// CHECK: ret i32 4 +int check_size1() { return sizeof(vec_t1); } + +// CHECK: ret i32 8 +int check_size2() { return sizeof(vec_t2); } + +// CHECK: ret i32 16 +int check_size3() { return sizeof(vec_t3); } + +// CHECK: ret i32 64 +int check_size4() { return sizeof(vec_t4); } + +// CHECK: ret i32 128 +int check_size5() { return sizeof(vec_t5); } + +// CHECK: ret i32 256 +int check_size6() { return sizeof(vec_t6); } Index: cfe/trunk/test/Sema/attr-mode-vector-types.c =================================================================== --- cfe/trunk/test/Sema/attr-mode-vector-types.c +++ cfe/trunk/test/Sema/attr-mode-vector-types.c @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// Correct cases. +typedef int __attribute__((mode(byte))) __attribute__((vector_size(256))) vec_t1; +typedef int __attribute__((mode(QI))) __attribute__((vector_size(256))) vec_t2; +typedef int __attribute__((mode(SI))) __attribute__((vector_size(256))) vec_t3; +typedef int __attribute__((mode(DI))) __attribute__((vector_size(256)))vec_t4; +typedef float __attribute__((mode(SF))) __attribute__((vector_size(256))) vec_t5; +typedef float __attribute__((mode(DF))) __attribute__((vector_size(256))) vec_t6; +typedef float __attribute__((mode(XF))) __attribute__((vector_size(256))) vec_t7; + +// Incorrect cases. +typedef float __attribute__((mode(QC))) __attribute__((vector_size(256))) vec_t8; +// expected-error@-1{{unsupported machine mode 'QC'}} +// expected-error@-2{{type of machine mode does not match type of base type}} +typedef _Complex float __attribute__((mode(HC))) __attribute__((vector_size(256))) vec_t9; +// expected-error@-1{{unsupported machine mode 'HC'}} +// expected-error@-2{{invalid vector element type '_Complex float'}} +typedef int __attribute__((mode(SC))) __attribute__((vector_size(256))) vec_t10; +// expected-error@-1{{type of machine mode does not match type of base type}} +// expected-error@-2{{type of machine mode does not support base vector types}} +typedef float __attribute__((mode(DC))) __attribute__((vector_size(256))) vec_t11; +// expected-error@-1{{type of machine mode does not match type of base type}} +// expected-error@-2{{type of machine mode does not support base vector types}} +typedef _Complex float __attribute__((mode(XC))) __attribute__((vector_size(256))) vec_t12; +// expected-error@-1{{invalid vector element type '_Complex float'}}