[MSVC] Implementation of __unaligned as a proper type qualifier
This patch implements __unaligned (MS extension) as a proper type qualifier
(before that, it was implemented as an ignored attribute).
It also fixes PR27367 and PR27666.
Differential Revision: http://reviews.llvm.org/D20103
llvm-svn: 269220
diff --git a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp
index 9938444..12bb8c7 100644
--- a/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-cxx11.cpp
@@ -293,3 +293,19 @@
}
// CHECK-DAG: @"\01??R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z"
// CHECK-DAG: @"\01??R<lambda_1>@?0???R<lambda_0>@?0??PR26105@@YAHXZ@QBE@H@Z@QBE@H@Z"
+
+int __unaligned * unaligned_foo1() { return 0; }
+int __unaligned * __unaligned * unaligned_foo2() { return 0; }
+__unaligned int unaligned_foo3() { return 0; }
+void unaligned_foo4(int __unaligned *p1) {}
+void unaligned_foo5(int __unaligned * __restrict p1) {}
+template <typename T> T unaligned_foo6(T t) { return t; }
+void unaligned_foo7() { unaligned_foo6<int *>(0); unaligned_foo6<int __unaligned *>(0); }
+
+// CHECK-DAG: @"\01?unaligned_foo1@@YAPFAHXZ"
+// CHECK-DAG: @"\01?unaligned_foo2@@YAPFAPFAHXZ"
+// CHECK-DAG: @"\01?unaligned_foo3@@YAHXZ"
+// CHECK-DAG: @"\01?unaligned_foo4@@YAXPFAH@Z"
+// CHECK-DAG: @"\01?unaligned_foo5@@YAXPIFAH@Z"
+// CHECK-DAG: @"\01??$unaligned_foo6@PAH@@YAPAHPAH@Z"
+// CHECK-DAG: @"\01??$unaligned_foo6@PFAH@@YAPFAHPFAH@Z"
diff --git a/clang/test/CodeGenCXX/mangle-ms-cxx14.cpp b/clang/test/CodeGenCXX/mangle-ms-cxx14.cpp
index 084eb7d..798a390 100644
--- a/clang/test/CodeGenCXX/mangle-ms-cxx14.cpp
+++ b/clang/test/CodeGenCXX/mangle-ms-cxx14.cpp
@@ -55,3 +55,8 @@
Foo<&x<int>, &x<int>> Zoo;
// CHECK-DAG: "\01?Zoo@@3U?$Foo@$1??$x@H@@3HA$1?1@3HA@@A"
+
+template <typename T> T unaligned_x;
+extern auto test_unaligned() { return unaligned_x<int __unaligned *>; }
+// CHECK-DAG: "\01??$unaligned_x@PFAH@@3PFAHA"
+
diff --git a/clang/test/Sema/MicrosoftExtensions.c b/clang/test/Sema/MicrosoftExtensions.c
index e703230..713daf5 100644
--- a/clang/test/Sema/MicrosoftExtensions.c
+++ b/clang/test/Sema/MicrosoftExtensions.c
@@ -170,3 +170,11 @@
__va_start(ap, f); // expected-warning {{incompatible pointer types passing 'my_va_list'}}
}
}
+
+// __unaligned handling
+void test_unaligned() {
+ __unaligned int *p1 = 0;
+ int *p2 = p1; // expected-warning {{initializing 'int *' with an expression of type '__unaligned int *' discards qualifiers}}
+ __unaligned int *p3 = p2;
+}
+
diff --git a/clang/test/Sema/address_spaces.c b/clang/test/Sema/address_spaces.c
index 1922c8a..3fe9315 100644
--- a/clang/test/Sema/address_spaces.c
+++ b/clang/test/Sema/address_spaces.c
@@ -20,7 +20,7 @@
_AS1 int arrarr[5][5]; // expected-error {{automatic variable qualified with an address space}}
__attribute__((address_space(-1))) int *_boundsA; // expected-error {{address space is negative}}
- __attribute__((address_space(0xFFFFFF))) int *_boundsB;
+ __attribute__((address_space(0x7FFFFF))) int *_boundsB;
__attribute__((address_space(0x1000000))) int *_boundsC; // expected-error {{address space is larger than the maximum supported}}
// chosen specifically to overflow 32 bits and come out reasonable
__attribute__((address_space(4294967500))) int *_boundsD; // expected-error {{address space is larger than the maximum supported}}
@@ -71,4 +71,4 @@
// Clang extension doesn't forbid operations on pointers to different address spaces.
char* cmp(_AS1 char *x, _AS2 char *y) {
return x < y ? x : y; // expected-warning {{pointer type mismatch ('__attribute__((address_space(1))) char *' and '__attribute__((address_space(2))) char *')}}
-}
\ No newline at end of file
+}
diff --git a/clang/test/Sema/invalid-assignment-constant-address-space.c b/clang/test/Sema/invalid-assignment-constant-address-space.c
index de2af64..77d6b33 100644
--- a/clang/test/Sema/invalid-assignment-constant-address-space.c
+++ b/clang/test/Sema/invalid-assignment-constant-address-space.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
-#define OPENCL_CONSTANT 16776962
+#define OPENCL_CONSTANT 8388354
int __attribute__((address_space(OPENCL_CONSTANT))) c[3] = {0};
void foo() {
diff --git a/clang/test/SemaCXX/MicrosoftExtensions.cpp b/clang/test/SemaCXX/MicrosoftExtensions.cpp
index 22cf2be..e24e45d 100644
--- a/clang/test/SemaCXX/MicrosoftExtensions.cpp
+++ b/clang/test/SemaCXX/MicrosoftExtensions.cpp
@@ -1,5 +1,7 @@
-// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify -fms-extensions -fexceptions -fcxx-exceptions
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify -fms-extensions -fexceptions -fcxx-exceptions -DTEST1
+// RUN: %clang_cc1 %s -triple i686-pc-win32 -fsyntax-only -Wmicrosoft -Wc++11-extensions -Wno-long-long -verify -fexceptions -fcxx-exceptions -DTEST2
+#if TEST1
// Microsoft doesn't validate exception specification.
namespace microsoft_exception_spec {
@@ -80,7 +82,69 @@
// __unaligned handling
typedef char __unaligned *aligned_type;
typedef struct UnalignedTag { int f; } __unaligned *aligned_type2;
+typedef char __unaligned aligned_type3;
+struct aligned_type4 {
+ int i;
+};
+
+__unaligned int aligned_type4::*p1_aligned_type4 = &aligned_type4::i;
+int aligned_type4::* __unaligned p2_aligned_type4 = &aligned_type4::i;
+__unaligned int aligned_type4::* __unaligned p3_aligned_type4 = &aligned_type4::i;
+
+// Check that __unaligned qualifier can be used for overloading
+void foo_unaligned(int *arg) {}
+void foo_unaligned(__unaligned int *arg) {}
+void foo_unaligned(int arg) {} // expected-note {{previous definition is here}}
+void foo_unaligned(__unaligned int arg) {} // expected-error {{redefinition of 'foo_unaligned'}}
+class A_unaligned {};
+class B_unaligned : public A_unaligned {};
+int foo_unaligned(__unaligned A_unaligned *arg) { return 0; }
+void *foo_unaligned(B_unaligned *arg) { return 0; }
+
+void test_unaligned() {
+ int *p1 = 0;
+ foo_unaligned(p1);
+
+ __unaligned int *p2 = 0;
+ foo_unaligned(p2);
+
+ __unaligned B_unaligned *p3 = 0;
+ int p4 = foo_unaligned(p3);
+
+ B_unaligned *p5 = p3; // expected-error {{cannot initialize a variable of type 'B_unaligned *' with an lvalue of type '__unaligned B_unaligned *'}}
+
+ __unaligned B_unaligned *p6 = p3;
+
+ p1_aligned_type4 = p2_aligned_type4;
+ p2_aligned_type4 = p1_aligned_type4; // expected-error {{assigning to 'int aligned_type4::*' from incompatible type '__unaligned int aligned_type4::*'}}
+ p3_aligned_type4 = p1_aligned_type4;
+}
+
+// Test from PR27367
+// We should accept assignment of an __unaligned pointer to a non-__unaligned
+// pointer to void
+typedef struct _ITEMIDLIST { int i; } ITEMIDLIST;
+typedef ITEMIDLIST __unaligned *LPITEMIDLIST;
+extern "C" __declspec(dllimport) void __stdcall CoTaskMemFree(void* pv);
+__inline void FreeIDListArray(LPITEMIDLIST *ppidls) {
+ CoTaskMemFree(*ppidls);
+ __unaligned int *x = 0;
+ void *y = x;
+}
+
+// Test from PR27666
+// We should accept type conversion of __unaligned to non-__unaligned references
+typedef struct in_addr {
+public:
+ in_addr(in_addr &a) {} // expected-note {{candidate constructor not viable: no known conversion from '__unaligned IN_ADDR *' (aka '__unaligned in_addr *') to 'in_addr &' for 1st argument; dereference the argument with *}}
+ in_addr(in_addr *a) {} // expected-note {{candidate constructor not viable: 1st argument ('__unaligned IN_ADDR *' (aka '__unaligned in_addr *')) would lose __unaligned qualifier}}
+} IN_ADDR;
+
+void f(IN_ADDR __unaligned *a) {
+ IN_ADDR local_addr = *a;
+ IN_ADDR local_addr2 = a; // expected-error {{no viable conversion from '__unaligned IN_ADDR *' (aka '__unaligned in_addr *') to 'IN_ADDR' (aka 'in_addr')}}
+}
template<typename T> void h1(T (__stdcall M::* const )()) { }
@@ -420,3 +484,15 @@
int S::fn() { return 0; } // expected-warning {{is missing exception specification}}
}
+
+#elif TEST2
+
+// Check that __unaligned is not recognized if MS extensions are not enabled
+typedef char __unaligned *aligned_type; // expected-error {{expected ';' after top level declarator}}
+
+#else
+
+#error Unknown test mode
+
+#endif
+