From: Eli Friedman Date: Tue, 3 Mar 2009 06:41:03 +0000 (+0000) Subject: PR3691: Add support for complex modes. I also tossed in support for XF X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=73397496fec250f565f49e27f8ba79f94f4e7427;p=clang PR3691: Add support for complex modes. I also tossed in support for XF while I was at it. There are still a lot of diagnostics missing from this code, and it isn't completely correct for anything other than x86, but it should work correctly on x86 for valid cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65935 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 8757005a47..f7ead5cb68 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1234,17 +1234,25 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { unsigned DestWidth = 0; bool IntegerMode = true; + bool ComplexMode = false; 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; } + switch (Str[0]) { + case 'Q': DestWidth = 8; break; + case 'H': DestWidth = 16; break; + case 'S': DestWidth = 32; break; + case 'D': DestWidth = 64; break; + case 'X': DestWidth = 96; break; + case 'T': DestWidth = 128; break; + } + if (Str[1] == 'F') { + IntegerMode = false; + } else if (Str[1] == 'C') { + IntegerMode = false; + ComplexMode = true; + } else if (Str[1] != 'I') { + DestWidth = 0; + } break; case 4: // FIXME: glibc uses 'word' to define register_t; this is narrower than a @@ -1270,7 +1278,20 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { << "mode" << SourceRange(Attr.getLoc(), Attr.getLoc()); return; } - + + if (!OldTy->getAsBuiltinType() && !OldTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); + else if (IntegerMode) { + if (!OldTy->isIntegralType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } else if (ComplexMode) { + if (!OldTy->isComplexType()) + S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + } else { + if (!OldTy->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 32/64-bit integers don't get defined to types of @@ -1286,14 +1307,20 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; return; case 8: - assert(IntegerMode); + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } if (OldTy->isSignedIntegerType()) NewTy = S.Context.SignedCharTy; else NewTy = S.Context.UnsignedCharTy; break; case 16: - assert(IntegerMode); + if (!IntegerMode) { + S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; + return; + } if (OldTy->isSignedIntegerType()) NewTy = S.Context.ShortTy; else @@ -1315,19 +1342,20 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { else NewTy = S.Context.UnsignedLongLongTy; break; + case 96: + NewTy = S.Context.LongDoubleTy; + break; case 128: if (!IntegerMode) { S.Diag(Attr.getLoc(), diag::err_unsupported_machine_mode) << Name; return; } NewTy = S.Context.getFixedWidthIntType(128, OldTy->isSignedIntegerType()); + break; } - if (!OldTy->getAsBuiltinType()) - S.Diag(Attr.getLoc(), diag::err_mode_not_primitive); - else if (!(IntegerMode && OldTy->isIntegerType()) && - !(!IntegerMode && OldTy->isFloatingType())) { - S.Diag(Attr.getLoc(), diag::err_mode_wrong_type); + if (ComplexMode) { + NewTy = S.Context.getComplexType(NewTy); } // Install the new type. diff --git a/test/Sema/attr-mode.c b/test/Sema/attr-mode.c index 0f8d5da24a..4d6ce28892 100644 --- a/test/Sema/attr-mode.c +++ b/test/Sema/attr-mode.c @@ -15,3 +15,8 @@ typedef struct {int i,j,k;} invalid_4 __attribute((mode(SI))); // expected-error typedef float invalid_5 __attribute((mode(SI))); // expected-error{{type of machine mode does not match type of base type}} int **__attribute((mode(QI)))* i32; // expected-error{{mode attribute}} + +typedef _Complex double c32 __attribute((mode(SC))); +int c32_test[sizeof(c32) == 8 ? 1 : -1]; +typedef _Complex float c64 __attribute((mode(DC))); +typedef _Complex float c80 __attribute((mode(XC)));