diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2008-05-27 03:33:27 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2008-05-27 03:33:27 +0000 |
commit | 3c0eb160ca1361a82b9f15b3b40a2425adc14d0f (patch) | |
tree | 1ba325230d8ddcb4586cdcef43ea08c3e417f875 /lib | |
parent | cbadaf6ced6d664015ee409f62ab1bc20ae0bf73 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51577 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/AttributeList.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 120 |
4 files changed, 143 insertions, 1 deletions
diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 2d8de97f3c..c99722c54a 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -54,6 +54,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { 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; diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e7e6605458..5d9113e99d 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -299,7 +299,13 @@ private: /// 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 @@ private: // 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). diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 38dbb9b09a..8b89045a71 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2384,6 +2384,17 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *Attr) { 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; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 9bb211bd30..d66b41d8e3 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -579,3 +579,123 @@ QualType Sema::HandleAddressSpaceTypeAttribute(QualType Type, 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; +} + + |