[AArch64, inline-asm] Improve diagnostic that is printed when the size of a
variable that has regiser constraint "r" is not 64-bit.

General register operands are output using 64-bit "x" register names, regardless
of the size of the variable, unless the asm operand is prefixed with the "%w"
modifier. This surprises and confuses many users who aren't familiar with
aarch64 inline assembly rules.

With this commit, a note and fixit hint are printed which tell the users that
they need modifier "%w" in order to output a "w" register instead of an "x"
register.

<rdar://problem/12764785>

llvm-svn: 216260
diff --git a/clang/test/Sema/arm64-inline-asm.c b/clang/test/Sema/arm64-inline-asm.c
index 2cfbe46..d8e16a6 100644
--- a/clang/test/Sema/arm64-inline-asm.c
+++ b/clang/test/Sema/arm64-inline-asm.c
@@ -5,5 +5,5 @@
   asm volatile("USE(%x0)" :: "z"(0LL));
   asm volatile("USE(%w0)" :: "z"(0));
 
-  asm volatile("USE(%0)" :: "z"(0)); // expected-warning {{value size does not match register size specified by the constraint and modifier}}
+  asm volatile("USE(%0)" :: "z"(0)); // expected-warning {{value size does not match register size specified by the constraint and modifier}} expected-note {{use constraint modifier "w"}}
 }
diff --git a/clang/test/Sema/inline-asm-validate-aarch64.c b/clang/test/Sema/inline-asm-validate-aarch64.c
new file mode 100644
index 0000000..1364b64
--- /dev/null
+++ b/clang/test/Sema/inline-asm-validate-aarch64.c
@@ -0,0 +1,38 @@
+// RUN: %clang_cc1 -triple arm64-apple-darwin -fsyntax-only -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+typedef unsigned char uint8_t;
+
+uint8_t constraint_r(uint8_t *addr) {
+  uint8_t byte;
+
+  __asm__ volatile("ldrb %0, [%1]" : "=r" (byte) : "r" (addr) : "memory");
+// CHECK: warning: value size does not match register size specified by the constraint and modifier
+// CHECK: note: use constraint modifier "w"
+// CHECK: fix-it:{{.*}}:{8:26-8:28}:"%w0"
+
+  return byte;
+}
+
+uint8_t constraint_r_symbolic(uint8_t *addr) {
+  uint8_t byte;
+
+  __asm__ volatile("ldrb %[s0], [%[s1]]" : [s0] "=r" (byte) : [s1] "r" (addr) : "memory");
+// CHECK: warning: value size does not match register size specified by the constraint and modifier
+// CHECK: note: use constraint modifier "w"
+// CHECK: fix-it:{{.*}}:{19:26-19:31}:"%w[s0]"
+
+  return byte;
+}
+
+#define PERCENT "%"
+
+uint8_t constraint_r_symbolic_macro(uint8_t *addr) {
+  uint8_t byte;
+
+  __asm__ volatile("ldrb "PERCENT"[s0], [%[s1]]" : [s0] "=r" (byte) : [s1] "r" (addr) : "memory");
+// CHECK: warning: value size does not match register size specified by the constraint and modifier
+// CHECK: note: use constraint modifier "w"
+// CHECK-NOT: fix-it
+
+  return byte;
+}
diff --git a/clang/test/Sema/inline-asm-validate.c b/clang/test/Sema/inline-asm-validate.c
index 6fa760c..73335e7 100644
--- a/clang/test/Sema/inline-asm-validate.c
+++ b/clang/test/Sema/inline-asm-validate.c
@@ -3,6 +3,6 @@
 unsigned t, r, *p;
 
 int foo (void) {
-  __asm__ __volatile__( "stxr   %w[_t], %[_r], [%[_p]]" : [_t] "=&r" (t) : [_p] "p" (p), [_r] "r" (r) : "memory"); // expected-warning{{value size does not match register size specified by the constraint and modifier}}
+  __asm__ __volatile__( "stxr   %w[_t], %[_r], [%[_p]]" : [_t] "=&r" (t) : [_p] "p" (p), [_r] "r" (r) : "memory"); // expected-warning{{value size does not match register size specified by the constraint and modifier}} expected-note {{use constraint modifier "w"}}
   return 1;
 }