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