Teach IsTailPaddedMemberArray() (used by -Warray-bounds) that a FieldDecl may have a Typedef type, and not always a ConstantArrayType.

Fixes <rdar://problem/11387038>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156464 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index d538fcf..bc4452f 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -4590,12 +4590,20 @@
   // substitution to form C89 tail-padded arrays.
 
   TypeSourceInfo *TInfo = FD->getTypeSourceInfo();
-  if (TInfo) {
-    ConstantArrayTypeLoc TL =
-      cast<ConstantArrayTypeLoc>(TInfo->getTypeLoc());
-    const Expr *SizeExpr = dyn_cast<IntegerLiteral>(TL.getSizeExpr());
+  while (TInfo) {
+    TypeLoc TL = TInfo->getTypeLoc();
+    // Look through typedefs.
+    const TypedefTypeLoc *TTL = dyn_cast<TypedefTypeLoc>(&TL);
+    if (TTL) {
+      const TypedefNameDecl *TDL = TTL->getTypedefNameDecl();
+      TInfo = TDL->getTypeSourceInfo();
+      continue;
+    }
+    ConstantArrayTypeLoc CTL = cast<ConstantArrayTypeLoc>(TL);
+    const Expr *SizeExpr = dyn_cast<IntegerLiteral>(CTL.getSizeExpr());
     if (!SizeExpr || SizeExpr->getExprLoc().isMacroID())
       return false;
+    break;
   }
 
   const RecordDecl *RD = dyn_cast<RecordDecl>(FD->getDeclContext());
diff --git a/test/Sema/array-bounds-ptr-arith.c b/test/Sema/array-bounds-ptr-arith.c
index 022335b..e3de06a 100644
--- a/test/Sema/array-bounds-ptr-arith.c
+++ b/test/Sema/array-bounds-ptr-arith.c
@@ -19,3 +19,21 @@
   int a[10];
   int *p = a - s->n;
 }
+
+// Test case reduced from <rdar://problem/11387038>.  This resulted in
+// an assertion failure because of the typedef instead of an explicit
+// constant array type.
+struct RDar11387038 {};
+typedef struct RDar11387038 RDar11387038Array[1];
+struct RDar11387038_Table {
+  RDar11387038Array z;
+};
+typedef struct RDar11387038_Table * TPtr;
+typedef TPtr *TabHandle;
+struct RDar11387038_B { TabHandle x; };
+typedef struct RDar11387038_B RDar11387038_B;
+
+void radar11387038() {
+  RDar11387038_B *pRDar11387038_B;
+  struct RDar11387038* y = &(*pRDar11387038_B->x)->z[4];
+}