Fix for PR8901: attribute "mode" rejected for enums and dependent types.

Allow "mode" attribute for enum types, except for vector modes, for compatibility with GCC.
Support "mode" attribute with dependent types.

Differential Revision: http://reviews.llvm.org/D16219

llvm-svn: 259497
This commit is contained in:
Denis Zobnin 2016-02-02 13:50:39 +00:00
parent 96fe4ef5f7
commit d9e2dcdb42
11 changed files with 403 additions and 41 deletions

View File

@ -879,8 +879,8 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr<TargetMips> {
def Mode : Attr {
let Spellings = [GCC<"mode">];
let Subjects = SubjectList<[Var, TypedefName, Field], ErrorDiag,
"ExpectedVariableFieldOrTypedef">;
let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag,
"ExpectedVariableEnumFieldOrTypedef">;
let Args = [IdentifierArgument<"Mode">];
let Documentation = [Undocumented];
}

View File

@ -2448,7 +2448,7 @@ def warn_attribute_wrong_decl_type : Warning<
"variables, functions and classes|Objective-C protocols|"
"functions and global variables|structs, unions, and typedefs|structs and typedefs|"
"interface or protocol declarations|kernel functions|non-K&R-style functions|"
"variables, fields and typedefs}1">,
"variables, enums, fields and typedefs}1">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>;
def warn_type_attribute_wrong_type : Warning<
@ -2858,6 +2858,8 @@ def warn_vector_mode_deprecated : Warning<
InGroup<DeprecatedAttributes>;
def err_complex_mode_vector_type : Error<
"type of machine mode does not support base vector types">;
def err_enum_mode_vector_type : Error<
"mode %0 is not supported for enumeration types">;
def warn_attribute_nonnull_no_pointers : Warning<
"'nonnull' attribute applied to function with no pointer arguments">,
InGroup<IgnoredAttributes>;

View File

@ -856,7 +856,7 @@ enum AttributeDeclKind {
ExpectedObjectiveCInterfaceOrProtocol,
ExpectedKernelFunction,
ExpectedFunctionWithProtoType,
ExpectedVariableFieldOrTypedef
ExpectedVariableEnumFieldOrTypedef
};
} // end namespace clang

View File

@ -7750,6 +7750,10 @@ public:
void AddLaunchBoundsAttr(SourceRange AttrRange, Decl *D, Expr *MaxThreads,
Expr *MinBlocks, unsigned SpellingListIndex);
/// AddModeAttr - Adds a mode attribute to a particular declaration.
void AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
unsigned SpellingListIndex, bool InInstantiation = false);
//===--------------------------------------------------------------------===//
// C++ Coroutines TS
//

View File

@ -3297,6 +3297,8 @@ bool Sema::checkMSInheritanceAttrOnDefinition(
/// attribute.
static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth,
bool &IntegerMode, bool &ComplexMode) {
IntegerMode = true;
ComplexMode = false;
switch (Str.size()) {
case 2:
switch (Str[0]) {
@ -3363,9 +3365,15 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident;
StringRef Str = Name->getName();
S.AddModeAttr(Attr.getRange(), D, Name, Attr.getAttributeSpellingListIndex());
}
void Sema::AddModeAttr(SourceRange AttrRange, Decl *D, IdentifierInfo *Name,
unsigned SpellingListIndex, bool InInstantiation) {
StringRef Str = Name->getName();
normalizeName(Str);
SourceLocation AttrLoc = AttrRange.getBegin();
unsigned DestWidth = 0;
bool IntegerMode = true;
@ -3381,99 +3389,126 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (VectorStringLength &&
!Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) &&
VectorSize.isPowerOf2()) {
parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth,
parseModeAttrArg(*this, Str.substr(VectorStringLength + 1), DestWidth,
IntegerMode, ComplexMode);
S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated);
// Avoid duplicate warning from template instantiation.
if (!InInstantiation)
Diag(AttrLoc, diag::warn_vector_mode_deprecated);
} else {
VectorSize = 0;
}
}
if (!VectorSize)
parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode);
parseModeAttrArg(*this, Str, DestWidth, IntegerMode, ComplexMode);
// FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
// and friends, at least with glibc.
// FIXME: Make sure floating-point mappings are accurate
// FIXME: Support XF and TF types
if (!DestWidth) {
Diag(AttrLoc, diag::err_machine_mode) << 0 /*Unknown*/ << Name;
return;
}
QualType OldTy;
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
OldTy = TD->getUnderlyingType();
else
else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
// Something like 'typedef enum { X } __attribute__((mode(XX))) T;'.
// Try to get type from enum declaration, default to int.
OldTy = ED->getIntegerType();
if (OldTy.isNull())
OldTy = Context.IntTy;
} else
OldTy = cast<ValueDecl>(D)->getType();
if (OldTy->isDependentType()) {
D->addAttr(::new (Context)
ModeAttr(AttrRange, Context, Name, SpellingListIndex));
return;
}
// 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<VectorType>())
OldElemTy = VT->getElementType();
if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType())
S.Diag(Attr.getLoc(), diag::err_mode_not_primitive);
// GCC allows 'mode' attribute on enumeration types (even incomplete), except
// for vector modes. So, 'enum X __attribute__((mode(QI)));' forms a complete
// type, 'enum { A } __attribute__((mode(V4SI)))' is rejected.
if ((isa<EnumDecl>(D) || OldElemTy->getAs<EnumType>()) &&
VectorSize.getBoolValue()) {
Diag(AttrLoc, diag::err_enum_mode_vector_type) << Name << AttrRange;
return;
}
bool IntegralOrAnyEnumType =
OldElemTy->isIntegralOrEnumerationType() || OldElemTy->getAs<EnumType>();
if (!OldElemTy->getAs<BuiltinType>() && !OldElemTy->isComplexType() &&
!IntegralOrAnyEnumType)
Diag(AttrLoc, diag::err_mode_not_primitive);
else if (IntegerMode) {
if (!OldElemTy->isIntegralOrEnumerationType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
if (!IntegralOrAnyEnumType)
Diag(AttrLoc, diag::err_mode_wrong_type);
} else if (ComplexMode) {
if (!OldElemTy->isComplexType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
Diag(AttrLoc, diag::err_mode_wrong_type);
} else {
if (!OldElemTy->isFloatingType())
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
}
// FIXME: Sync this with InitializePredefinedMacros; we need to match int8_t
// and friends, at least with glibc.
// FIXME: Make sure floating-point mappings are accurate
// FIXME: Support XF and TF types
if (!DestWidth) {
S.Diag(Attr.getLoc(), diag::err_machine_mode) << 0 /*Unknown*/ << Name;
return;
Diag(AttrLoc, diag::err_mode_wrong_type);
}
QualType NewElemTy;
if (IntegerMode)
NewElemTy = S.Context.getIntTypeForBitwidth(
DestWidth, OldElemTy->isSignedIntegerType());
NewElemTy = Context.getIntTypeForBitwidth(DestWidth,
OldElemTy->isSignedIntegerType());
else
NewElemTy = S.Context.getRealTypeForBitwidth(DestWidth);
NewElemTy = Context.getRealTypeForBitwidth(DestWidth);
if (NewElemTy.isNull()) {
S.Diag(Attr.getLoc(), diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
Diag(AttrLoc, diag::err_machine_mode) << 1 /*Unsupported*/ << Name;
return;
}
if (ComplexMode) {
NewElemTy = S.Context.getComplexType(NewElemTy);
NewElemTy = Context.getComplexType(NewElemTy);
}
QualType NewTy = NewElemTy;
if (VectorSize.getBoolValue()) {
NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(),
VectorType::GenericVector);
NewTy = Context.getVectorType(NewTy, VectorSize.getZExtValue(),
VectorType::GenericVector);
} else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) {
// Complex machine mode does not support base vector types.
if (ComplexMode) {
S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type);
Diag(AttrLoc, diag::err_complex_mode_vector_type);
return;
}
unsigned NumElements = S.Context.getTypeSize(OldElemTy) *
unsigned NumElements = Context.getTypeSize(OldElemTy) *
OldVT->getNumElements() /
S.Context.getTypeSize(NewElemTy);
Context.getTypeSize(NewElemTy);
NewTy =
S.Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
Context.getVectorType(NewElemTy, NumElements, OldVT->getVectorKind());
}
if (NewTy.isNull()) {
S.Diag(Attr.getLoc(), diag::err_mode_wrong_type);
Diag(AttrLoc, diag::err_mode_wrong_type);
return;
}
// Install the new type.
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
TD->setModedTypeSourceInfo(TD->getTypeSourceInfo(), NewTy);
else if (EnumDecl *ED = dyn_cast<EnumDecl>(D))
ED->setIntegerType(NewTy);
else
cast<ValueDecl>(D)->setType(NewTy);
D->addAttr(::new (S.Context)
ModeAttr(Attr.getRange(), S.Context, Name,
Attr.getAttributeSpellingListIndex()));
D->addAttr(::new (Context)
ModeAttr(AttrRange, Context, Name, SpellingListIndex));
}
static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {

View File

@ -227,6 +227,14 @@ static void instantiateDependentCUDALaunchBoundsAttr(
Attr.getSpellingListIndex());
}
static void
instantiateDependentModeAttr(Sema &S,
const MultiLevelTemplateArgumentList &TemplateArgs,
const ModeAttr &Attr, Decl *New) {
S.AddModeAttr(Attr.getRange(), New, Attr.getMode(),
Attr.getSpellingListIndex(), /*InInstantiation=*/true);
}
void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
const Decl *Tmpl, Decl *New,
LateInstantiatedAttrVec *LateAttrs,
@ -265,6 +273,11 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
continue;
}
if (const ModeAttr *Mode = dyn_cast<ModeAttr>(TmplAttr)) {
instantiateDependentModeAttr(*this, TemplateArgs, *Mode, New);
continue;
}
// Existing DLL attribute on the instantiation takes precedence.
if (TmplAttr->getKind() == attr::DLLExport ||
TmplAttr->getKind() == attr::DLLImport) {

View File

@ -0,0 +1,45 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
// Test checks that 'mode' attribute is handled correctly with enums, i. e. code
// 1. "typedef enum { A } __attribute__((mode(HI))) T;" is accepted,
// 2. "enum X __attribute__((mode(QI))) var;" forms a complete integer type.
int main() {
// CHECK: [[X1:%.+]] = alloca i8
enum { A1, B1 } __attribute__((mode(QI))) x1 = A1;
// CHECK: [[X2:%.+]] = alloca i16
enum { A2, B2 } x2 __attribute__((mode(HI))) = B2;
// CHECK: [[X3:%.+]] = alloca i32
typedef enum { A3, B3 } __attribute__((mode(SI))) T3;
T3 x3 = A3;
// CHECK: [[X4:%.+]] = alloca i64
typedef enum { A4, B4 } T4 __attribute__((mode(DI)));
T4 x4 = B4;
// CHECK: [[X5:%.+]] = alloca i8
typedef enum __attribute__((mode(QI))) { A5, B5 } T5;
T5 x5 = A5;
// CHECK: [[X6:%.+]] = alloca i8
typedef enum X __attribute__((mode(QI))) T6;
T6 x6;
// CHECK: [[X7:%.+]] = alloca i128
enum { A7, B7 } __attribute__((mode(TI))) x7 = A7;
// CHECK: [[X8:%.+]] = alloca i8
enum __attribute__((mode(QI))) { A8, B8 } x8 = B8;
// CHECK: store i8 0, i8* [[X1]]
// CHECK: store i16 1, i16* [[X2]]
// CHECK: store i32 0, i32* [[X3]]
// CHECK: store i64 1, i64* [[X4]]
// CHECK: store i8 0, i8* [[X5]]
// CHECK: store i128 0, i128* [[X7]]
// CHECK: store i8 1, i8* [[X8]]
return x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8;
}

View File

@ -0,0 +1,108 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o - | FileCheck %s
template <class T>
void CheckIntScalarTypes() {
// T will be substituted with 'int' and 'enum' types.
typedef T __attribute__((mode(QI))) T1;
typedef T __attribute__((mode(HI))) T2;
typedef T __attribute__((mode(SI))) T3;
typedef T __attribute__((mode(DI))) T4;
T1 a1;
T2 a2;
T3 a3;
T4 a4;
}
template <class T>
void CheckIntVectorTypes() {
// T will be substituted with 'int'.
typedef int __attribute__((mode(QI))) __attribute__((vector_size(8))) VT_11;
typedef T __attribute__((mode(V8QI))) VT_12;
typedef int __attribute__((mode(SI))) __attribute__((vector_size(16))) VT_21;
typedef T __attribute__((mode(V4SI))) VT_22;
typedef int __attribute__((mode(DI))) __attribute__((vector_size(64))) VT_31;
typedef T __attribute__((mode(V8DI))) VT_32;
VT_11 v11;
VT_12 v12;
VT_21 v21;
VT_22 v22;
VT_31 v31;
VT_32 v32;
}
template <class T>
void CheckFloatVectorTypes() {
// T will be substituted with 'float'.
typedef float __attribute__((mode(SF))) __attribute__((vector_size(128))) VT_41;
typedef T __attribute__((mode(V32SF))) VT_42;
typedef float __attribute__((mode(DF))) __attribute__((vector_size(256))) VT_51;
typedef T __attribute__((mode(V32DF))) VT_52;
VT_41 v41;
VT_42 v42;
VT_51 v51;
VT_52 v52;
}
template <class T>
void CheckInstantiationWithModedType() {
T x1;
}
typedef enum { A1, B1 } EnumTy;
typedef int __attribute__((mode(DI))) Int64Ty1;
typedef enum __attribute__((mode(DI))) { A2 } Int64Ty2;
typedef int __attribute__((mode(V8HI))) IntVecTy1;
void test() {
// CHECK: define {{.*}} void @_Z19CheckIntScalarTypesIiEvv()
// CHECK: %{{.+}} = alloca i8
// CHECK: %{{.+}} = alloca i16
// CHECK: %{{.+}} = alloca i32
// CHECK: %{{.+}} = alloca i64
CheckIntScalarTypes<int>();
// CHECK: define {{.*}} void @_Z19CheckIntScalarTypesI6EnumTyEvv()
// CHECK: %{{.+}} = alloca i8
// CHECK: %{{.+}} = alloca i16
// CHECK: %{{.+}} = alloca i32
// CHECK: %{{.+}} = alloca i64
CheckIntScalarTypes<EnumTy>();
// CHECK: define {{.*}} void @_Z19CheckIntVectorTypesIiEvv()
// CHECK: %{{.+}} = alloca <8 x i8>
// CHECK: %{{.+}} = alloca <8 x i8>
// CHECK: %{{.+}} = alloca <4 x i32>
// CHECK: %{{.+}} = alloca <4 x i32>
// CHECK: %{{.+}} = alloca <8 x i64>
// CHECK: %{{.+}} = alloca <8 x i64>
CheckIntVectorTypes<int>();
// CHECK: define {{.*}} void @_Z21CheckFloatVectorTypesIfEvv()
// CHECK: %{{.+}} = alloca <32 x float>
// CHECK: %{{.+}} = alloca <32 x float>
// CHECK: %{{.+}} = alloca <32 x double>
// CHECK: %{{.+}} = alloca <32 x double>
CheckFloatVectorTypes<float>();
// CHECK: define {{.*}} void @_Z31CheckInstantiationWithModedTypeIlEvv()
// CHECK: [[X1:%.+]] = alloca i64
CheckInstantiationWithModedType<Int64Ty1>();
// CHECK: define {{.*}} void @_Z31CheckInstantiationWithModedTypeI8Int64Ty2Evv()
// CHECK: [[X1]] = alloca i64
CheckInstantiationWithModedType<Int64Ty2>();
// CHECK: define {{.*}} void @_Z31CheckInstantiationWithModedTypeIDv8_sEvv()
// CHECK: [[X1]] = alloca <8 x i16>
CheckInstantiationWithModedType<IntVecTy1>();
}

View File

@ -0,0 +1,51 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// Test checks that 'mode' attribute is handled correctly with enums, i. e. code
// 1. "typedef enum { A } __attribute__((mode(HI))) T;" is accepted,
// 2. "enum X __attribute__((mode(QI))) var;" forms a complete integer type.
// 3. "enum { A } __attribute__((mode(V4SI))) var;" is not accepted (vector mode).
typedef enum { E4 } EnumType;
int main() {
// Vector mode are not allowed with enums.
typedef enum { E1 } __attribute__((mode(V4QI))) RejectedType1; // expected-error{{mode 'V4QI' is not supported for enumeration types}}
// expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated}}
typedef enum __attribute__((mode(V8HI))) { E2 } RejectedType2; // expected-error{{mode 'V8HI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
typedef enum E3 __attribute__((mode(V2SI))) RejectedType3; // expected-error{{mode 'V2SI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
typedef EnumType __attribute__((mode(V4DI))) RejectedType4; // expected-error{{mode 'V4DI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
EnumType v1 __attribute__((mode(V4QI))); // expected-error{{mode 'V4QI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
enum __attribute__((mode(V8HI))) { E5 } v2; // expected-error{{mode 'V8HI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
// Incomplete enums without mode attribute are not allowed.
typedef enum Y IncompleteYType; // expected-note{{forward declaration of 'enum Y'}}
enum X a1; // expected-error{{variable has incomplete type 'enum X'}}
// expected-note@-1{{forward declaration of 'enum X'}}
IncompleteYType a2; // expected-error{{variable has incomplete type 'IncompleteYType' (aka 'enum Y')}}
// OK with 'mode' attribute.
typedef enum Y __attribute__((mode(QI))) CompleteYType1;
typedef enum Y CompleteYType2 __attribute__((mode(HI)));
typedef enum { A1, B1 } __attribute__((mode(QI))) CompleteType3;
typedef enum { A2, B2 } CompleteType4 __attribute__((mode(QI)));
typedef enum __attribute__((mode(QI))) { A3, B3 } CompleteType5;
enum X __attribute__((mode(QI))) a3;
enum X a4 __attribute__((mode(HI)));
IncompleteYType __attribute__((mode(QI))) a5;
IncompleteYType a6 __attribute__((mode(HI)));
CompleteYType1 a7;
CompleteYType2 a8;
CompleteType3 a9;
CompleteType4 a10;
CompleteType5 a11;
enum __attribute__((mode(QI))) { A4, B4 } a12;
return 0;
}

View File

@ -26,8 +26,8 @@ typedef unsigned unwind_word __attribute((mode(unwind_word)));
int **__attribute((mode(QI)))* i32; // expected-error{{mode attribute}}
__attribute__((mode(QI))) int invalid_func() { return 1; } // expected-error{{'mode' attribute only applies to variables, fields and typedefs}}
enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{'mode' attribute only applies to variables, fields and typedefs}}
__attribute__((mode(QI))) int invalid_func() { return 1; } // expected-error{{'mode' attribute only applies to variables, enums, fields and typedefs}}
enum invalid_enum { A1 __attribute__((mode(QI))) }; // expected-error{{'mode' attribute only applies to variables, enums, fields and typedefs}}
typedef _Complex double c32 __attribute((mode(SC)));
int c32_test[sizeof(c32) == 8 ? 1 : -1];

View File

@ -0,0 +1,104 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
typedef enum { XX } EnumType;
struct S { int x; };
// Check enumerations. Vector modes on enum types must cause an error.
template <class T>
void CheckEnumerations() {
// Check that non-vector 'mode' attribute is OK with enumeration types.
typedef T __attribute__((mode(QI))) T1;
typedef T T2 __attribute__((mode(HI)));
typedef T __attribute__((mode(V8SI))) T3; // expected-error{{mode 'V8SI' is not supported for enumeration types}}
// expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated}}
typedef enum __attribute__((mode(HI))) { A4, B4 } T4;
typedef enum { A5, B5 } __attribute__((mode(SI))) T5;
typedef enum __attribute__((mode(V2SI))) { A6, B6 } T6; // expected-error{{mode 'V2SI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
typedef enum { A7, B7 } __attribute__((mode(V2QI))) T7; // expected-error{{mode 'V2QI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
}
// Check that attribute applies only for integer and floating-point types.
// OK when instantiated with 'int', error with structure types, for example.
template <class T>
void CheckPrimitiveTypes() {
typedef T __attribute__((mode(QI))) T1; // expected-error{{mode attribute only supported for integer and floating-point types}}
typedef T __attribute__((mode(V2SI))) VT1; // expected-error{{mode attribute only supported for integer and floating-point types}}
// expected-warning@-1{{specifying vector types with the 'mode' attribute is deprecated}}
}
// Check that attribute supports certain modes. Check that wrong machine modes
// are NOT diagnosed twice during instantiation.
template <class T>
void CheckMachineMode() {
typedef T __attribute__((mode(QI))) T1; // expected-error{{type of machine mode does not match type of base type}}
typedef T __attribute__((mode(HI))) T2; // expected-error{{type of machine mode does not match type of base type}}
typedef T __attribute__((mode(SI))) T3; // expected-error{{type of machine mode does not match type of base type}}
typedef T __attribute__((mode(DI))) T4; // expected-error{{type of machine mode does not match type of base type}}
typedef T __attribute__((mode(SF))) T5; // expected-error2{{type of machine mode does not match type of base type}}
typedef T __attribute__((mode(DF))) T6; // expected-error2{{type of machine mode does not match type of base type}}
typedef T __attribute__((mode(II))) T7; // expected-error{{unknown machine mode}}
typedef T __attribute__((mode(12))) T8; // expected-error{{'mode' attribute requires an identifier}}
}
// Check attributes on function parameters.
template <class T1, class T2>
void CheckParameters(T1 __attribute__((mode(SI))) paramSI, // expected-note2{{ignored: substitution failure}}
T1 __attribute__((mode(V4DI))) paramV4DI, // expected-warning{{deprecated}}
T2 __attribute__((mode(SF))) paramSF,
T2 __attribute__((mode(V4DF))) paramV4DF) { // expected-warning{{deprecated}}
}
// Check dependent structure.
template <class T>
struct TemplatedStruct {
// Check fields.
T __attribute__((mode(HI))) x1;
T __attribute__((mode(V4HI))) x2; // expected-error{{mode 'V4HI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
// Check typedefs.
typedef T __attribute__((mode(DI))) T1;
typedef T __attribute__((mode(V8DI))) T2; // expected-error{{mode 'V8DI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
// Check parameters.
void f1(T __attribute__((mode(QI))) x) {}
void f2(T __attribute__((mode(SF))) x) {} // expected-error2{{type of machine mode does not match type of base type}}
void f3(T __attribute__((mode(V4QI))) x) {} // expected-error{{mode 'V4QI' is not supported for enumeration types}}
// expected-warning@-1{{deprecated}}
// Check attribute on methods - it is invalid.
__attribute__((mode(QI))) T g1() { return 0; } // expected-error{{'mode' attribute only applies to variables, enums, fields and typedefs}}
};
int main() {
CheckEnumerations<int>();
CheckEnumerations<EnumType>(); // expected-note{{in instantiation of}}
CheckPrimitiveTypes<int>();
CheckPrimitiveTypes<S>(); // expected-note{{in instantiation of}}
// 'II' mode is unknown, no matter what we instantiate with.
CheckMachineMode<int>(); // expected-note{{in instantiation of}}
CheckMachineMode<EnumType>(); // expected-note{{in instantiation of}}
CheckMachineMode<float>(); // expected-note{{in instantiation of}}
int __attribute__((mode(V4DI))) valV4DI; // expected-warning{{deprecated}}
float __attribute__((mode(V4DF))) valV4DF; // expected-warning{{deprecated}}
// OK.
CheckParameters<int, float>(0, valV4DI, 1.0, valV4DF);
// Enumeral type with vector mode is invalid.
CheckParameters<EnumType, float>(0, valV4DI, 1.0, valV4DF); // expected-error{{no matching function for call}}
// 'V4DF' mode with 'int' type is invalid.
CheckParameters<int, int>(0, valV4DI, 1, valV4DF); // expected-error{{no matching function for call}}
TemplatedStruct<int> s1; // expected-note{{in instantiation of}}
TemplatedStruct<EnumType> s2; // expected-note{{in instantiation of}}
return 0;
}