forked from OSchip/llvm-project
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:
parent
96fe4ef5f7
commit
d9e2dcdb42
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -856,7 +856,7 @@ enum AttributeDeclKind {
|
|||
ExpectedObjectiveCInterfaceOrProtocol,
|
||||
ExpectedKernelFunction,
|
||||
ExpectedFunctionWithProtoType,
|
||||
ExpectedVariableFieldOrTypedef
|
||||
ExpectedVariableEnumFieldOrTypedef
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue