aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2010-01-26 06:39:24 +0000
committerChandler Carruth <chandlerc@gmail.com>2010-01-26 06:39:24 +0000
commitaec7caa3c40891727164167ece11d552422803d2 (patch)
treeff1876979a8df5c72869d01dcc0bdb65ccba5540
parentd0c4792ca6bde9d60002760c10eb605ed2eebde8 (diff)
Correctly treat 64 bit integers specified via the mode attribute as the 'long'
type when that type is 64 bits wide, and the 'long long' type when 'long' is only 32 bits wide. This fixes PR6108. Also adds a bunch of test cases to ensure proper conversion between equally sized standard types and mode-specified types on both 32 and 64 bit targets. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94527 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaDeclAttr.cpp10
-rw-r--r--test/Sema/attr-mode.c39
2 files changed, 46 insertions, 3 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index f36afeb7e7..40169b635d 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1607,9 +1607,15 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {
if (!IntegerMode)
NewTy = S.Context.DoubleTy;
else if (OldTy->isSignedIntegerType())
- NewTy = S.Context.LongLongTy;
+ if (S.Context.Target.getLongWidth() == 64)
+ NewTy = S.Context.LongTy;
+ else
+ NewTy = S.Context.LongLongTy;
else
- NewTy = S.Context.UnsignedLongLongTy;
+ if (S.Context.Target.getLongWidth() == 64)
+ NewTy = S.Context.UnsignedLongTy;
+ else
+ NewTy = S.Context.UnsignedLongLongTy;
break;
case 96:
NewTy = S.Context.LongDoubleTy;
diff --git a/test/Sema/attr-mode.c b/test/Sema/attr-mode.c
index 9acd2c6f65..0c5336282c 100644
--- a/test/Sema/attr-mode.c
+++ b/test/Sema/attr-mode.c
@@ -1,4 +1,7 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple i686-pc-linux-gnu -DTEST_32BIT_X86 -fsyntax-only \
+// RUN: -verify %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -DTEST_64BIT_X86 -fsyntax-only \
+// RUN: -verify %s
typedef int i16_1 __attribute((mode(HI)));
int i16_1_test[sizeof(i16_1) == 2 ? 1 : -1];
@@ -20,3 +23,37 @@ 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)));
+
+// PR6108: Correctly select 'long' built in type on 64-bit platforms for 64 bit
+// modes. Also test other mode-based conversions.
+typedef int i8_mode_t __attribute__ ((__mode__ (__QI__)));
+typedef unsigned int ui8_mode_t __attribute__ ((__mode__ (__QI__)));
+typedef int i16_mode_t __attribute__ ((__mode__ (__HI__)));
+typedef unsigned int ui16_mode_t __attribute__ ((__mode__ (__HI__)));
+typedef int i32_mode_t __attribute__ ((__mode__ (__SI__)));
+typedef unsigned int ui32_mode_t __attribute__ ((__mode__ (__SI__)));
+typedef int i64_mode_t __attribute__ ((__mode__ (__DI__)));
+typedef unsigned int ui64_mode_t __attribute__ ((__mode__ (__DI__)));
+void f_i8_arg(i8_mode_t* x) { (void)x; }
+void f_ui8_arg(ui8_mode_t* x) { (void)x; }
+void f_i16_arg(i16_mode_t* x) { (void)x; }
+void f_ui16_arg(ui16_mode_t* x) { (void)x; }
+void f_i32_arg(i32_mode_t* x) { (void)x; }
+void f_ui32_arg(ui32_mode_t* x) { (void)x; }
+void f_i64_arg(i64_mode_t* x) { (void)x; }
+void f_ui64_arg(ui64_mode_t* x) { (void)x; }
+void test_char_to_i8(signed char* y) { f_i8_arg(y); }
+void test_char_to_ui8(unsigned char* y) { f_ui8_arg(y); }
+void test_short_to_i16(short* y) { f_i16_arg(y); }
+void test_short_to_ui16(unsigned short* y) { f_ui16_arg(y); }
+void test_int_to_i32(int* y) { f_i32_arg(y); }
+void test_int_to_ui32(unsigned int* y) { f_ui32_arg(y); }
+#if TEST_32BIT_X86
+void test_long_to_i64(long long* y) { f_i64_arg(y); }
+void test_long_to_ui64(unsigned long long* y) { f_ui64_arg(y); }
+#elif TEST_64BIT_X86
+void test_long_to_i64(long* y) { f_i64_arg(y); }
+void test_long_to_ui64(unsigned long* y) { f_ui64_arg(y); }
+#else
+#error Unknown test architecture.
+#endif