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 8757005..f7ead5c 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1234,17 +1234,25 @@
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 @@
<< "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 @@
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 @@
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.