diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index c765deb8e6b0e3c0170e80ad7f44e548d105fb9f..5d5df5e1ac4edb999e00854d39b0004a475bd094 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -48,6 +48,8 @@ def err_vla_decl_has_static_storage : Error<
   "variable length array declaration can not have 'static' storage duration">;
 def err_vla_decl_has_extern_linkage : Error<
   "variable length array declaration can not have 'extern' linkage">;
+def ext_vla_folded_to_constant : Extension<
+  "variable length array folded to constant array as an extension">;
 
 // C99 variably modified types
 def err_variably_modified_template_arg : Error<
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 5fd8afa6acf4a4dd8da650cbca117ecd3c9e94eb..ec8fdc917c05408ff5d04a9deec270377dfb862e 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1100,6 +1100,28 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
   return Context.getRValueReferenceType(T);
 }
 
+/// Check whether the specified array size makes the array type a VLA.  If so,
+/// return true, if not, return the size of the array in SizeVal.
+static bool isArraySizeVLA(Expr *ArraySize, llvm::APSInt &SizeVal, Sema &S) {
+  // If the size is an ICE, it certainly isn't a VLA.
+  if (ArraySize->isIntegerConstantExpr(SizeVal, S.Context))
+    return false;
+    
+  // If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable
+  // value as an extension.
+  Expr::EvalResult Result;
+  if (S.LangOpts.GNUMode && ArraySize->Evaluate(Result, S.Context)) {
+    if (!Result.hasSideEffects() && Result.Val.isInt()) {
+      SizeVal = Result.Val.getInt();
+      S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+
 /// \brief Build an array type.
 ///
 /// \param T The type of each element in the array.
@@ -1200,11 +1222,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
       T = Context.getIncompleteArrayType(T, ASM, Quals);
   } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
     T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
-  } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
-             (!T->isDependentType() && !T->isIncompleteType() &&
-              !T->isConstantSizeType())) {
-    // Per C99, a variable array is an array with either a non-constant
-    // size or an element type that has a non-constant-size
+  } else if (!T->isDependentType() && !T->isIncompleteType() &&
+             !T->isConstantSizeType()) {
+    // C99: an array with an element type that has a non-constant-size is a VLA.
+    T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
+  } else if (isArraySizeVLA(ArraySize, ConstVal, *this)) {
+    // C99: an array with a non-ICE size is a VLA.  We accept any expression
+    // that we can fold to a non-zero positive value as an extension.
     T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
   } else {
     // C99 6.7.5.2p1: If the expression is a constant expression, it shall
diff --git a/test/Sema/const-eval.c b/test/Sema/const-eval.c
index 56c429c58c2ab2e390ddae4a6284aa2766349adf..bdb40ae54be3bc3e5d6e13d3a230bccf78a36589 100644
--- a/test/Sema/const-eval.c
+++ b/test/Sema/const-eval.c
@@ -36,7 +36,7 @@ int g17[(3?:1) - 2];
 EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1);
 
 struct s {
-  int a[(int)-1.0f]; // expected-error {{array size is negative}}
+  int a[(int)-1.0f]; // expected-error {{'a' declared as an array with a negative size}}
 };
 
 EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));
diff --git a/test/Sema/i-c-e.c b/test/Sema/i-c-e.c
index 4d7007cd077c9d7f770db263320765221af62a78..1aac51e204f150f18a8929733b7a8ae9db5c7b88 100644
--- a/test/Sema/i-c-e.c
+++ b/test/Sema/i-c-e.c
@@ -1,4 +1,4 @@
-// RUN: %clang %s -ffreestanding -fsyntax-only -Xclang -verify -pedantic -fpascal-strings
+// RUN: %clang %s -ffreestanding -fsyntax-only -Xclang -verify -pedantic -fpascal-strings -std=c99
 
 #include <stdint.h>
 #include <limits.h>
diff --git a/test/Sema/struct-decl.c b/test/Sema/struct-decl.c
index e1c7073e01b29708d8e3b315888e4dbca67331ef..6070e875f5a4c04eb002adfbd10b30504c81c8fe 100644
--- a/test/Sema/struct-decl.c
+++ b/test/Sema/struct-decl.c
@@ -6,7 +6,7 @@ struct bar {
 
 struct foo {
   char name[(int)&((struct bar *)0)->n];
-  char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{array size is negative}}
+  char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{'name2' declared as an array with a negative size}}
 };
 
 // PR3430
diff --git a/test/Sema/typedef-variable-type.c b/test/Sema/typedef-variable-type.c
index b805b1e0578f24be7dcb79f313f9a34b7e085c36..8a7ee8b911c097ab344b19bafbfe9f56f1c3d7a6 100644
--- a/test/Sema/typedef-variable-type.c
+++ b/test/Sema/typedef-variable-type.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic -Wno-typedef-redefinition
+// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic -Wno-typedef-redefinition -std=c99
 
 // Make sure we accept a single typedef
 typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}
diff --git a/test/Sema/vla.c b/test/Sema/vla.c
index ebf9b889ee2a8134af862b6cea8753318f5bd356..fd7a6bf3d72f94d3dc0a5899e1b91ac38688a6a3 100644
--- a/test/Sema/vla.c
+++ b/test/Sema/vla.c
@@ -42,7 +42,7 @@ void f3()
 }
 
 // PR3663
-static const unsigned array[((2 * (int)((((4) / 2) + 1.0/3.0) * (4) - 1e-8)) + 1)]; // expected-warning {{size of static array must be an integer constant expression}}
+static const unsigned array[((2 * (int)((((4) / 2) + 1.0/3.0) * (4) - 1e-8)) + 1)]; // expected-warning {{variable length array folded to constant array as an extension}}
 
 int a[*]; // expected-error {{star modifier used outside of function prototype}}
 int f4(int a[*][*]);
@@ -53,7 +53,7 @@ int pr2044b;
 int (*pr2044c(void))[pr2044b]; // expected-error {{variably modified type}}
 
 const int f5_ci = 1;
-void f5() { char a[][f5_ci] = {""}; } // expected-error {{variable-sized object may not be initialized}}
+void f5() { char a[][f5_ci] = {""}; } // expected-warning {{variable length array folded to constant array as an extension}}
 
 // PR5185
 void pr5185(int a[*]);
diff --git a/test/SemaCXX/c99-variable-length-array.cpp b/test/SemaCXX/c99-variable-length-array.cpp
index 98df1dbfe81e1df14cae4b77bef50391bf8cb0d7..3f1d6a8a55c004cbcfef00296b679f0089c701e4 100644
--- a/test/SemaCXX/c99-variable-length-array.cpp
+++ b/test/SemaCXX/c99-variable-length-array.cpp
@@ -121,3 +121,12 @@ namespace PR8209 {
     (void)new vla_type; // expected-error{{variably}}
   }
 }
+
+namespace rdar8733881 { // rdar://8733881
+
+static const int k_cVal3 = (int)(1000*0.2f);
+  int f() {
+    // Ok, fold to a constant size array as an extension.
+    char rgch[k_cVal3] = {0};
+  }
+}