Index: include/clang/Basic/DiagnosticKinds.def =================================================================== --- include/clang/Basic/DiagnosticKinds.def (revision 51367) +++ include/clang/Basic/DiagnosticKinds.def (working copy) @@ -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, Index: include/clang/Parse/AttributeList.h =================================================================== --- include/clang/Parse/AttributeList.h (revision 51367) +++ include/clang/Parse/AttributeList.h (working copy) @@ -52,6 +52,7 @@ AT_fastcall, AT_format, AT_malloc, + AT_mode, AT_noinline, AT_nonnull, AT_noreturn, Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp (revision 51367) +++ lib/Sema/SemaDecl.cpp (working copy) @@ -2383,6 +2383,17 @@ vDecl->setType(newType); } break; + case AttributeList::AT_mode: + if (TypedefDecl *tDecl = dyn_cast(New)) { + QualType newType = HandleModeTypeAttribute(tDecl->getUnderlyingType(), + Attr); + tDecl->setUnderlyingType(newType); + } else if (ValueDecl *vDecl = dyn_cast(New)) { + QualType newType = HandleModeTypeAttribute(vDecl->getType(), Attr); + vDecl->setType(newType); + } + // FIXME: Diagnostic? + break; case AttributeList::AT_deprecated: HandleDeprecatedAttribute(New, Attr); break; Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp (revision 51367) +++ lib/Sema/SemaType.cpp (working copy) @@ -579,3 +579,123 @@ return Context.getASQualType(Type, ASIdx); } +/// HandleAddressSpaceTypeAttribute - 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_annotate_no_string); + 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; +} + + Index: lib/Sema/Sema.h =================================================================== --- lib/Sema/Sema.h (revision 51367) +++ lib/Sema/Sema.h (working copy) @@ -299,8 +299,14 @@ /// 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 // return values are allowed in conjunction with this construct. Aggregates Index: lib/Parse/AttributeList.cpp =================================================================== --- lib/Parse/AttributeList.cpp (revision 51367) +++ lib/Parse/AttributeList.cpp (working copy) @@ -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;