Index: cfe/trunk/include/clang/Basic/DiagnosticGroups.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticGroups.td +++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td @@ -83,6 +83,7 @@ def CXX11CompatDeprecatedWritableStr : DiagGroup<"c++11-compat-deprecated-writable-strings">; +def DeprecatedAttributes : DiagGroup<"deprecated-attributes">; def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">; def UnavailableDeclarations : DiagGroup<"unavailable-declarations">; def PartialAvailability : DiagGroup<"partial-availability">; @@ -92,7 +93,8 @@ def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings", [CXX11CompatDeprecatedWritableStr]>; // FIXME: Why is DeprecatedImplementations not in this group? -def Deprecated : DiagGroup<"deprecated", [DeprecatedDeclarations, +def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes, + DeprecatedDeclarations, DeprecatedIncrementBool, DeprecatedRegister, DeprecatedWritableStr]>, Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td @@ -2823,6 +2823,10 @@ "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 warn_vector_mode_deprecated : Warning< + "specifying vector types with the 'mode' attribute is deprecated; " + "use the 'vector_size' attribute instead">, + InGroup; def err_complex_mode_vector_type : Error< "type of machine mode does not support base vector types">; def err_attr_wrong_decl : Error< Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp =================================================================== --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp @@ -3234,38 +3234,31 @@ return true; } -/// handleModeAttr - This attribute modifies the width of a decl with primitive -/// type. -/// -/// Despite what would be logical, the mode attribute is a decl attribute, not a -/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be -/// HImode, not an intermediate pointer. -static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // This attribute isn't documented, but glibc uses it. It changes - // the width of an int or unsigned int to the specified size. - if (!Attr.isArgIdent(0)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() - << AANT_ArgumentIdentifier; - return; - } - - IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - StringRef Str = Name->getName(); - - normalizeName(Str); - - unsigned DestWidth = 0; - bool IntegerMode = true; - bool ComplexMode = false; +/// parseModeAttrArg - Parses attribute mode string and returns parsed type +/// attribute. +static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, + bool &IntegerMode, bool &ComplexMode) { switch (Str.size()) { case 2: switch (Str[0]) { - case 'Q': DestWidth = 8; break; - case 'H': DestWidth = 16; break; - case 'S': DestWidth = 32; break; - case 'D': DestWidth = 64; break; - case 'X': DestWidth = 96; break; - case 'T': DestWidth = 128; break; + case 'Q': + DestWidth = 8; + break; + case 'H': + DestWidth = 16; + break; + case 'S': + DestWidth = 32; + break; + case 'D': + DestWidth = 64; + break; + case 'X': + DestWidth = 96; + break; + case 'T': + DestWidth = 128; + break; } if (Str[1] == 'F') { IntegerMode = false; @@ -3293,6 +3286,52 @@ DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); break; } +} + +/// handleModeAttr - This attribute modifies the width of a decl with primitive +/// type. +/// +/// Despite what would be logical, the mode attribute is a decl attribute, not a +/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be +/// HImode, not an intermediate pointer. +static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // This attribute isn't documented, but glibc uses it. It changes + // the width of an int or unsigned int to the specified size. + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() + << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; + StringRef Str = Name->getName(); + + normalizeName(Str); + + unsigned DestWidth = 0; + bool IntegerMode = true; + bool ComplexMode = false; + llvm::APInt VectorSize(64, 0); + if (Str.size() >= 4 && Str[0] == 'V') { + // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). + size_t StrSize = Str.size(); + size_t VectorStringLength = 0; + while ((VectorStringLength + 1) < StrSize && + isdigit(Str[VectorStringLength + 1])) + ++VectorStringLength; + if (VectorStringLength && + !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && + VectorSize.isPowerOf2()) { + parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, + IntegerMode, ComplexMode); + S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); + } else { + VectorSize = 0; + } + } + + if (!VectorSize) + parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); QualType OldTy; if (TypedefNameDecl *TD = dyn_cast(D)) @@ -3351,7 +3390,10 @@ } QualType NewTy = NewElemTy; - if (const VectorType *OldVT = OldTy->getAs()) { + if (VectorSize.getBoolValue()) { + NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(), + VectorType::GenericVector); + } else 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); 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 @@ -9,6 +9,14 @@ typedef float __attribute__((mode(DF))) __attribute__((vector_size(256))) vec_t6; typedef float __attribute__((mode(XF))) __attribute__((vector_size(256))) vec_t7; +typedef int v8qi __attribute__ ((mode(QI))) __attribute__ ((vector_size(8))); +typedef int v8qi __attribute__ ((mode(V8QI))); +// expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated; use the 'vector_size' attribute instead}} + +typedef float v4sf __attribute__((mode(V4SF))); +// expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated; use the 'vector_size' attribute instead}} +typedef float v4sf __attribute__((mode(SF))) __attribute__ ((vector_size(16))); + // Incorrect cases. typedef float __attribute__((mode(QC))) __attribute__((vector_size(256))) vec_t8; // expected-error@-1{{unsupported machine mode 'QC'}} @@ -24,3 +32,5 @@ // 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'}} +typedef int __attribute__((mode(V3QI))) v3qi; +// expected-error@-1{{unknown machine mode 'V3QI'}}