r259497 - Fix for PR8901: attribute "mode" rejected for enums and dependent types.
Denis Zobnin via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 2 05:50:40 PST 2016
Author: dzobnin
Date: Tue Feb 2 07:50:39 2016
New Revision: 259497
URL: http://llvm.org/viewvc/llvm-project?rev=259497&view=rev
Log:
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
Added:
cfe/trunk/test/CodeGen/attr-mode-enums.c
cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp
cfe/trunk/test/Sema/attr-mode-enums.c
cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/AttributeList.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
cfe/trunk/test/Sema/attr-mode.c
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Tue Feb 2 07:50:39 2016
@@ -879,8 +879,8 @@ def MipsInterrupt : InheritableAttr, Tar
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];
}
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Feb 2 07:50:39 2016
@@ -2448,7 +2448,7 @@ def warn_attribute_wrong_decl_type : War
"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 : Warnin
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>;
Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Tue Feb 2 07:50:39 2016
@@ -856,7 +856,7 @@ enum AttributeDeclKind {
ExpectedObjectiveCInterfaceOrProtocol,
ExpectedKernelFunction,
ExpectedFunctionWithProtoType,
- ExpectedVariableFieldOrTypedef
+ ExpectedVariableEnumFieldOrTypedef
};
} // end namespace clang
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Feb 2 07:50:39 2016
@@ -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
//
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Feb 2 07:50:39 2016
@@ -3297,6 +3297,8 @@ bool Sema::checkMSInheritanceAttrOnDefin
/// 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
}
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
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) {
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Feb 2 07:50:39 2016
@@ -227,6 +227,14 @@ static void instantiateDependentCUDALaun
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 MultiL
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) {
Added: cfe/trunk/test/CodeGen/attr-mode-enums.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-mode-enums.c?rev=259497&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/attr-mode-enums.c (added)
+++ cfe/trunk/test/CodeGen/attr-mode-enums.c Tue Feb 2 07:50:39 2016
@@ -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;
+}
Added: cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp?rev=259497&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/attr-mode-vector-types-tmpl.cpp Tue Feb 2 07:50:39 2016
@@ -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>();
+}
Added: cfe/trunk/test/Sema/attr-mode-enums.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-mode-enums.c?rev=259497&view=auto
==============================================================================
--- cfe/trunk/test/Sema/attr-mode-enums.c (added)
+++ cfe/trunk/test/Sema/attr-mode-enums.c Tue Feb 2 07:50:39 2016
@@ -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 at -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 at -1{{deprecated}}
+ typedef enum E3 __attribute__((mode(V2SI))) RejectedType3; // expected-error{{mode 'V2SI' is not supported for enumeration types}}
+ // expected-warning at -1{{deprecated}}
+ typedef EnumType __attribute__((mode(V4DI))) RejectedType4; // expected-error{{mode 'V4DI' is not supported for enumeration types}}
+ // expected-warning at -1{{deprecated}}
+ EnumType v1 __attribute__((mode(V4QI))); // expected-error{{mode 'V4QI' is not supported for enumeration types}}
+ // expected-warning at -1{{deprecated}}
+ enum __attribute__((mode(V8HI))) { E5 } v2; // expected-error{{mode 'V8HI' is not supported for enumeration types}}
+ // expected-warning at -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 at -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;
+}
Modified: cfe/trunk/test/Sema/attr-mode.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/attr-mode.c?rev=259497&r1=259496&r2=259497&view=diff
==============================================================================
--- cfe/trunk/test/Sema/attr-mode.c (original)
+++ cfe/trunk/test/Sema/attr-mode.c Tue Feb 2 07:50:39 2016
@@ -26,8 +26,8 @@ typedef unsigned unwind_word __attribute
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];
Added: cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp?rev=259497&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp (added)
+++ cfe/trunk/test/SemaCXX/attr-mode-tmpl.cpp Tue Feb 2 07:50:39 2016
@@ -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 at -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 at -1{{deprecated}}
+ typedef enum { A7, B7 } __attribute__((mode(V2QI))) T7; // expected-error{{mode 'V2QI' is not supported for enumeration types}}
+ // expected-warning at -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 at -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 at -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 at -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 at -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;
+}
More information about the cfe-commits
mailing list