]> granicus.if.org Git - clang/commitdiff
the 'mode' attribute is a decl attribute, not a type attribute. Move it to
authorChris Lattner <sabre@nondot.org>
Fri, 27 Jun 2008 22:18:37 +0000 (22:18 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 27 Jun 2008 22:18:37 +0000 (22:18 +0000)
SemaDeclAttr, and do some cleanups.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@52844 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticKinds.def
lib/Sema/Sema.h
lib/Sema/SemaDeclAttr.cpp
lib/Sema/SemaType.cpp

index 4b68c31516514a3b398168823c29167d4c018455..27e4e57532c0b571f26ad15668ffb9e23d33469d 100644 (file)
@@ -650,6 +650,8 @@ 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")
+DIAG(err_mode_wrong_decl, ERROR,
+     "declaration does not allow mode attribute")
 
 // Function Parameter Semantic Analysis.
 DIAG(err_param_with_void_type, ERROR,
index e0d97585bd0aaa5a73c35ccca3676f50eab5f7b5..0dda082d7e3021af10e8099df9fa6699b4efda83 100644 (file)
@@ -307,11 +307,10 @@ private:
   QualType HandleAddressSpaceTypeAttribute(QualType curType, 
                                            const AttributeList *rawAttr);
 
-  /// HandleModeTypeAttribute - this attribute modifies the width of a
+  /// HandleModeAttribute - this attribute modifies the width of a decl with
   /// primitive type.  Note that this is a variable attribute, and not
   /// a type attribute.
-  QualType HandleModeTypeAttribute(QualType curType, 
-                                   const AttributeList *rawAttr);
+  void HandleModeAttribute(Decl *d, const AttributeList &Attr);
 
   // HandleVectorTypeAttribute - this attribute is only applicable to 
   // integral and float scalars, although arrays, pointers, and function
index 8d715f1cdcd8c7cf0b7f79c71be173dc62787408..442da1422ff84842649deed1f0436d7aa343b6ad 100644 (file)
@@ -13,7 +13,7 @@
 
 #include "Sema.h"
 #include "clang/AST/ASTContext.h"
-
+#include "clang/Basic/TargetInfo.h"
 using namespace clang;
 
 static const FunctionTypeProto *getFunctionProto(Decl *d) {
@@ -80,20 +80,7 @@ void Sema::HandleDeclAttribute(Decl *New, const AttributeList *Attr) {
   case AttributeList::AT_address_space:
     // Ignore this, this is a type attribute, handled by ProcessTypeAttributes.
     break;
-  case AttributeList::AT_mode:
-    // Despite what would be logical, the mode attribute is a decl attribute,
-    // not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
-    // 'G' be HImode, not an intermediate pointer.
-    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_mode:       HandleModeAttribute(New, *Attr);  break;
   case AttributeList::AT_alias:      HandleAliasAttribute(New, Attr); break;
   case AttributeList::AT_deprecated: HandleDeprecatedAttribute(New, Attr);break;
   case AttributeList::AT_visibility: HandleVisibilityAttribute(New, Attr);break;
@@ -653,3 +640,129 @@ void Sema::HandleAlignedAttribute(Decl *d, const AttributeList *rawAttr) {
 
   d->addAttr(new AlignedAttr(Align));
 }
+
+/// HandleModeAttribute - Process a mode attribute on the specified decl.
+///
+/// Despite what would be logical, the mode attribute is a decl attribute,
+/// not a type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make
+/// 'G' be HImode, not an intermediate pointer.
+///
+void Sema::HandleModeAttribute(Decl *D, const 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;
+  }
+
+  IdentifierInfo *Name = Attr.getParameterName();
+  if (!Name) {
+    Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);
+    return;
+  }
+  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:
+    // FIXME: glibc uses 'word' to define register_t; this is narrower than a
+    // pointer on PIC16 and other embedded platforms.
+    if (!memcmp(Str, "word", 4))
+      DestWidth = Context.Target.getPointerWidth(0);
+    if (!memcmp(Str, "byte", 4))
+      DestWidth = Context.Target.getCharWidth();
+    break;
+  case 7:
+    if (!memcmp(Str, "pointer", 7))
+      DestWidth = Context.Target.getPointerWidth(0);
+    break;
+  }
+
+  QualType OldTy;
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+    OldTy = TD->getUnderlyingType();
+  else if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
+    OldTy = VD->getType();
+  else {
+    Diag(D->getLocation(), diag::err_mode_wrong_decl,
+         SourceRange(Attr.getLoc(), Attr.getLoc()));
+    return;
+  }
+  
+  // FIXME: Need proper fixed-width types
+  QualType NewTy;
+  switch (DestWidth) {
+  case 0:
+    Diag(Attr.getLoc(), diag::err_unknown_machine_mode, Name->getName());
+    return;
+  default:
+    Diag(Attr.getLoc(), diag::err_unsupported_machine_mode, Name->getName());
+    return;
+  case 8:
+    assert(IntegerMode);
+    if (OldTy->isSignedIntegerType())
+      NewTy = Context.SignedCharTy;
+    else
+      NewTy = Context.UnsignedCharTy;
+    break;
+  case 16:
+    assert(IntegerMode);
+    if (OldTy->isSignedIntegerType())
+      NewTy = Context.ShortTy;
+    else
+      NewTy = Context.UnsignedShortTy;
+    break;
+  case 32:
+    if (!IntegerMode)
+      NewTy = Context.FloatTy;
+    else if (OldTy->isSignedIntegerType())
+      NewTy = Context.IntTy;
+    else
+      NewTy = Context.UnsignedIntTy;
+    break;
+  case 64:
+    if (!IntegerMode)
+      NewTy = Context.DoubleTy;
+    else if (OldTy->isSignedIntegerType())
+      NewTy = Context.LongLongTy;
+    else
+      NewTy = Context.UnsignedLongLongTy;
+    break;
+  }
+
+  if (!OldTy->getAsBuiltinType())
+    Diag(Attr.getLoc(), diag::err_mode_not_primitive);
+  else if (!(IntegerMode && OldTy->isIntegerType()) &&
+           !(!IntegerMode && OldTy->isFloatingType())) {
+    Diag(Attr.getLoc(), diag::err_mode_wrong_type);
+  }
+
+  // Install the new type.
+  if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
+    TD->setUnderlyingType(NewTy);
+  else
+    cast<ValueDecl>(D)->setType(NewTy);
+}
index 9d6bcb9b0783b8e2da4c529db59cbc3c9b2b46b1..8fd72a01951bf9801f1f4dc2ce91388358485bd4 100644 (file)
@@ -560,123 +560,4 @@ QualType Sema::HandleAddressSpaceTypeAttribute(QualType Type,
   return Context.getASQualType(Type, ASIdx);
 }
 
-/// HandleModeTypeAttribute - Process a mode attribute on the
-/// specified type.
-QualType Sema::HandleModeTypeAttribute(QualType Type, 
-                                       const 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;
-}
-