[cfe-commits] r51577 - in /cfe/trunk: include/clang/Basic/DiagnosticKinds.def include/clang/Parse/AttributeList.h lib/Parse/AttributeList.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaType.cpp test/Sema/mode-attr-test.c

Eli Friedman eli.friedman at gmail.com
Mon May 26 20:33:29 PDT 2008


Author: efriedma
Date: Mon May 26 22:33:27 2008
New Revision: 51577

URL: http://llvm.org/viewvc/llvm-project?rev=51577&view=rev
Log:
Implementation of gcc mode attribute; this is significant because 
it fixes PR2204.  Not too much to say about the implementation; it works 
in a similar way to the vector size attribute.

At some point, we need to modify the targets to provide information 
about the appropriate types.


Added:
    cfe/trunk/test/Sema/mode-attr-test.c
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/include/clang/Parse/AttributeList.h
    cfe/trunk/lib/Parse/AttributeList.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaType.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=51577&r1=51576&r2=51577&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon May 26 22:33:27 2008
@@ -584,6 +584,8 @@
 // Attributes
 DIAG(err_attribute_wrong_number_arguments, ERROR,
      "attribute requires %0 argument(s)")
+DIAG(err_attribute_missing_parameter_name, ERROR,
+     "attribute requires unquoted parameter")
 DIAG(err_attribute_invalid_vector_type, ERROR,
      "invalid vector type '%0'")
 DIAG(err_attribute_argument_not_int, ERROR,
@@ -632,6 +634,14 @@
   "'%0' attribute ignored for field of type '%1'")
 DIAG(warn_attribute_type_not_supported, WARNING,
   "'%0' attribute argument not supported: '%1'")
+DIAG(err_unknown_machine_mode, ERROR,
+     "unknown machine mode '%0'")
+DIAG(err_unsupported_machine_mode, ERROR,
+     "unsupported machine mode '%0'")
+DIAG(err_mode_not_primitive, ERROR,
+     "mode attribute only supported for integer and floating-point types")
+DIAG(err_mode_wrong_type, ERROR,
+     "type of machine mode does not match type of base type")
 
 // Function Parameter Semantic Analysis.
 DIAG(err_param_with_void_type, ERROR,

Modified: cfe/trunk/include/clang/Parse/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/AttributeList.h?rev=51577&r1=51576&r2=51577&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/AttributeList.h (original)
+++ cfe/trunk/include/clang/Parse/AttributeList.h Mon May 26 22:33:27 2008
@@ -52,6 +52,7 @@
     AT_fastcall,
     AT_format,
     AT_malloc,
+    AT_mode,
     AT_noinline,
     AT_nonnull,
     AT_noreturn,

Modified: cfe/trunk/lib/Parse/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/AttributeList.cpp?rev=51577&r1=51576&r2=51577&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/AttributeList.cpp (original)
+++ cfe/trunk/lib/Parse/AttributeList.cpp Mon May 26 22:33:27 2008
@@ -54,6 +54,7 @@
   case 4:
     if (!memcmp(Str, "weak", 4)) return AT_weak;
     if (!memcmp(Str, "pure", 4)) return AT_pure;
+    if (!memcmp(Str, "mode", 4)) return AT_mode;
     break;
   case 6:
     if (!memcmp(Str, "packed", 6)) return AT_packed;

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=51577&r1=51576&r2=51577&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon May 26 22:33:27 2008
@@ -299,7 +299,13 @@
   /// The raw attribute contains 1 argument, the id of the address space 
   /// for the type.
   QualType HandleAddressSpaceTypeAttribute(QualType curType, 
-                                           AttributeList *rawAttr);                                
+                                           AttributeList *rawAttr);
+
+  /// HandleModeTypeAttribute - this attribute modifies the width of a
+  /// primitive type.  Note that this is a variable attribute, and not
+  /// a type attribute.
+  QualType HandleModeTypeAttribute(QualType curType, 
+                                   AttributeList *rawAttr);                                
 
   // HandleVectorTypeAttribute - this attribute is only applicable to 
   // integral and float scalars, although arrays, pointers, and function
@@ -723,6 +729,10 @@
   // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
   // functions and arrays to their respective pointers (C99 6.3.2.1).
   Expr *UsualUnaryConversions(Expr *&expr); 
+
+  // UsualUnaryConversionType - Same as UsualUnaryConversions, but works
+  // on types instead of expressions
+  QualType UsualUnaryConversionType(QualType Ty); 
   
   // DefaultFunctionArrayConversion - converts functions and arrays
   // to their respective pointers (C99 6.3.2.1). 

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=51577&r1=51576&r2=51577&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon May 26 22:33:27 2008
@@ -2384,6 +2384,17 @@
       vDecl->setType(newType);
     }
     break;
+  case AttributeList::AT_mode:
+    if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
+      QualType newType = HandleModeTypeAttribute(tDecl->getUnderlyingType(),
+                                                 Attr);
+      tDecl->setUnderlyingType(newType);
+    } else if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) {
+      QualType newType = HandleModeTypeAttribute(vDecl->getType(), Attr);
+      vDecl->setType(newType);
+    }
+    // FIXME: Diagnostic?
+    break;
   case AttributeList::AT_deprecated:
     HandleDeprecatedAttribute(New, Attr);
     break;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=51577&r1=51576&r2=51577&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon May 26 22:33:27 2008
@@ -579,3 +579,123 @@
   return Context.getASQualType(Type, ASIdx);
 }
 
+/// HandleModeTypeAttribute - Process a mode attribute on the
+/// specified type.
+QualType Sema::HandleModeTypeAttribute(QualType Type, 
+                                       AttributeList *Attr) {
+  // This attribute isn't documented, but glibc uses it.  It changes
+  // the width of an int or unsigned int to the specified size.
+
+  // Check that there aren't any arguments
+  if (Attr->getNumArgs() != 0) {
+    Diag(Attr->getLoc(), diag::err_attribute_wrong_number_arguments,
+         std::string("0"));
+    return Type;
+  }
+
+  IdentifierInfo * Name = Attr->getParameterName();
+  if (!Name) {
+    Diag(Attr->getLoc(), diag::err_attribute_missing_parameter_name);
+    return Type;
+  }
+  const char *Str = Name->getName();
+  unsigned Len = Name->getLength();
+
+  // Normalize the attribute name, __foo__ becomes foo.
+  if (Len > 4 && Str[0] == '_' && Str[1] == '_' &&
+      Str[Len - 2] == '_' && Str[Len - 1] == '_') {
+    Str += 2;
+    Len -= 4;
+  }
+
+  unsigned DestWidth = 0;
+  bool IntegerMode = true;
+
+  switch (Len) {
+  case 2:
+    if (!memcmp(Str, "QI", 2)) { DestWidth =  8; break; }
+    if (!memcmp(Str, "HI", 2)) { DestWidth = 16; break; }
+    if (!memcmp(Str, "SI", 2)) { DestWidth = 32; break; }
+    if (!memcmp(Str, "DI", 2)) { DestWidth = 64; break; }
+    if (!memcmp(Str, "TI", 2)) { DestWidth = 128; break; }
+    if (!memcmp(Str, "SF", 2)) { DestWidth = 32; IntegerMode = false; break; }
+    if (!memcmp(Str, "DF", 2)) { DestWidth = 64; IntegerMode = false; break; }
+    if (!memcmp(Str, "XF", 2)) { DestWidth = 96; IntegerMode = false; break; }
+    if (!memcmp(Str, "TF", 2)) { DestWidth = 128; IntegerMode = false; break; }
+    break;
+  case 4:
+    if (!memcmp(Str, "word", 4)) {
+      // FIXME: glibc uses this to define register_t; this is
+      // narrover than a pointer on PIC16 and other embedded
+      // platforms
+      DestWidth = Context.getTypeSize(Context.VoidPtrTy);
+      break;
+    }
+    if (!memcmp(Str, "byte", 4)) {
+      DestWidth = Context.getTypeSize(Context.CharTy);
+      break;
+    }
+    break;
+  case 7:
+    if (!memcmp(Str, "pointer", 7)) {
+      DestWidth = Context.getTypeSize(Context.VoidPtrTy);
+      IntegerMode = true;
+      break;
+    }
+    break;
+  }
+
+  // FIXME: Need proper fixed-width types
+  QualType RetTy;
+  switch (DestWidth) {
+  case 0:
+    Diag(Attr->getLoc(), diag::err_unknown_machine_mode, 
+         std::string(Str, Len));
+    return Type;
+  case 8:
+    assert(IntegerMode);
+    if (Type->isSignedIntegerType())
+      RetTy = Context.SignedCharTy;
+    else
+      RetTy = Context.UnsignedCharTy;
+    break;
+  case 16:
+    assert(IntegerMode);
+    if (Type->isSignedIntegerType())
+      RetTy = Context.ShortTy;
+    else
+      RetTy = Context.UnsignedShortTy;
+    break;
+  case 32:
+    if (!IntegerMode)
+      RetTy = Context.FloatTy;
+    else if (Type->isSignedIntegerType())
+      RetTy = Context.IntTy;
+    else
+      RetTy = Context.UnsignedIntTy;
+    break;
+  case 64:
+    if (!IntegerMode)
+      RetTy = Context.DoubleTy;
+    else if (Type->isSignedIntegerType())
+      RetTy = Context.LongLongTy;
+    else
+      RetTy = Context.UnsignedLongLongTy;
+    break;
+  default:
+    Diag(Attr->getLoc(), diag::err_unsupported_machine_mode,
+         std::string(Str, Len));
+    return Type;
+  }
+
+  if (!Type->getAsBuiltinType())
+    Diag(Attr->getLoc(), diag::err_mode_not_primitive);
+  else if (!(IntegerMode && Type->isIntegerType()) &&
+           !(!IntegerMode && Type->isFloatingType())) {
+    Diag(Attr->getLoc(), diag::err_mode_wrong_type);
+  }
+
+  return RetTy;
+}
+
+

Added: cfe/trunk/test/Sema/mode-attr-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/mode-attr-test.c?rev=51577&view=auto

==============================================================================
--- cfe/trunk/test/Sema/mode-attr-test.c (added)
+++ cfe/trunk/test/Sema/mode-attr-test.c Mon May 26 22:33:27 2008
@@ -0,0 +1,15 @@
+// RUN: clang -fsyntax-only -verify %s
+
+typedef int i16_1 __attribute((mode(HI)));
+int i16_1_test[sizeof(i16_1) == 2 ? 1 : -1];
+typedef int i16_2 __attribute((__mode__(__HI__)));
+int i16_2_test[sizeof(i16_1) == 2 ? 1 : -1];
+
+typedef float f64 __attribute((mode(DF)));
+int f64_test[sizeof(f64) == 8 ? 1 : -1];
+
+typedef int invalid_1 __attribute((mode)); // expected-error{{attribute requires unquoted parameter}}
+typedef int invalid_2 __attribute((mode())); // expected-error{{attribute requires unquoted parameter}}
+typedef int invalid_3 __attribute((mode(II))); // expected-error{{unknown machine mode}}
+typedef struct {int i,j,k;} invalid_4 __attribute((mode(SI))); // expected-error{{mode attribute only supported for integer and floating-point types}}
+typedef float invalid_5 __attribute((mode(SI))); // expected-error{{type of machine mode does not match type of base type}}





More information about the cfe-commits mailing list