diff --git a/gcc/protected-alloca.h b/gcc/protected-alloca.h
new file mode 100644
index 0000000..62f2a7b
--- /dev/null
+++ b/gcc/protected-alloca.h
@@ -0,0 +1,113 @@
+/* Alloca wrapper with a malloc fallback.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   Contributed by Aldy Hernandez <aldyh@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef _PROTECTED_ALLOCA_H_
+#define _PROTECTED_ALLOCA_H_
+
+#ifndef MAX_ALLOCA_SIZE
+#define MAX_ALLOCA_SIZE 4096
+#endif
+
+#ifdef __GNUC__
+#define _ALLOCA_INLINE_ __attribute__((always_inline))
+#else
+#define _ALLOCA_INLINE_
+#endif
+
+/* This is a wrapper class for alloca that falls back to malloc if the
+   allocation size is > MAX_ALLOCA_SIZE.  It is meant to replace:
+
+     char *str = (char *) alloca (N);
+
+   by this:
+
+     protected_alloca chunk (N);
+     char *str = (char *) chunk.pointer ();
+
+   or this:
+
+     protected_alloca chunk;
+     chunk.alloc (N);
+     char *str = (char *) chunk.pointer ();
+
+   If N > MAX_ALLOCA_SIZE, malloc is used, and whenever `chunk' goes
+   out of scope, the malloc'd memory will be freed.  Keep in mind that
+   the malloc'd memory gets freed when `chunk' goes out of scope, and
+   may be freed earlier than expected.  For example:
+
+     func()
+     {
+       char *str;
+       {
+         protected_alloca chunk (99999999);
+	 // If malloc'd, pointer will be freed when chunk goes out of scope.
+         str = (char *) chunk.pointer ();
+       }
+       use (str);  // BAD!  Use after free.
+     }
+
+   In this case, it is best to use the following idiom:
+
+     func()
+     {
+       void *ptr;
+       protected_alloca chunk;
+       {
+         chunk.alloc (9999999);
+	 str = (char *) chunk.pointer ();
+       }
+       // OK, pointer will be freed on function exit.
+       use (str);
+     }
+*/
+
+class protected_alloca {
+  void *p;
+  bool on_heap;
+public:
+  // GCC will refuse to inline a function that calls alloca unless
+  // `always_inline' is used, for fear of inlining an alloca call
+  // appearing in a loop.  Inlining this constructor won't make code
+  // any worse than it already is wrt loops.  We know what we're
+  // doing.
+  _ALLOCA_INLINE_ void
+  internal_alloc (size_t size)
+  {
+    if (size < MAX_ALLOCA_SIZE)
+      {
+	p = alloca (size);
+	on_heap = false;
+      }
+    else
+      {
+	p = xmalloc (size);
+	on_heap = true;
+      }
+  }
+  _ALLOCA_INLINE_
+  protected_alloca (size_t size) { internal_alloc (size); }
+  protected_alloca () { p = NULL; on_heap = false; }
+  ~protected_alloca () { if (on_heap) free (p); }
+  __attribute__((always_inline))
+  void alloc (size_t size) { gcc_assert (!p); internal_alloc (size); }
+  void *pointer () { return p; }
+};
+
+#endif // _PROTECTED_ALLOCA_H_
diff --git a/gcc/tree.c b/gcc/tree.c
index 11d3b51..621dcd5 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "print-tree.h"
 #include "ipa-utils.h"
 #include "selftest.h"
+#include "protected-alloca.h"
 
 /* Tree code classes.  */
 
@@ -9639,6 +9640,7 @@ get_file_function_name (const char *type)
   char *buf;
   const char *p;
   char *q;
+  protected_alloca q_alloca;
 
   /* If we already have a name we know to be unique, just use that.  */
   if (first_global_object_name)
@@ -9674,7 +9676,8 @@ get_file_function_name (const char *type)
 	file = LOCATION_FILE (input_location);
 
       len = strlen (file);
-      q = (char *) alloca (9 + 17 + len + 1);
+      q_alloca.alloc (9 + 17 + len + 1);
+      q = (char *) q_alloca.pointer ();
       memcpy (q, file, len + 1);
 
       snprintf (q + len, 9 + 17 + 1, "_%08X_" HOST_WIDE_INT_PRINT_HEX, 
@@ -9684,8 +9687,9 @@ get_file_function_name (const char *type)
     }
 
   clean_symbol_name (q);
-  buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
-			 + strlen (type));
+  protected_alloca buf_alloca (sizeof (FILE_FUNCTION_FORMAT) + strlen (p)
+			       + strlen (type));
+  buf = (char *) buf_alloca.pointer ();
 
   /* Set up the name of the file-level functions we may need.
      Use a global object (which is already required to be unique over
@@ -9709,7 +9713,8 @@ tree_check_failed (const_tree node, const char *file,
 {
   va_list args;
   const char *buffer;
-  unsigned length = 0;
+  protected_alloca buffer_alloca;
+  size_t length = 0;
   enum tree_code code;
 
   va_start (args, function);
@@ -9721,7 +9726,8 @@ tree_check_failed (const_tree node, const char *file,
       char *tmp;
       va_start (args, function);
       length += strlen ("expected ");
-      buffer = tmp = (char *) alloca (length);
+      buffer_alloca.alloc (length);
+      buffer = tmp = (char *) buffer_alloca.pointer ();
       length = 0;
       while ((code = (enum tree_code) va_arg (args, int)))
 	{
@@ -9752,7 +9758,8 @@ tree_not_check_failed (const_tree node, const char *file,
 {
   va_list args;
   char *buffer;
-  unsigned length = 0;
+  protected_alloca buffer_alloca;
+  size_t length = 0;
   enum tree_code code;
 
   va_start (args, function);
@@ -9760,7 +9767,8 @@ tree_not_check_failed (const_tree node, const char *file,
     length += 4 + strlen (get_tree_code_name (code));
   va_end (args);
   va_start (args, function);
-  buffer = (char *) alloca (length);
+  buffer_alloca.alloc (length);
+  buffer = (char *) buffer_alloca.pointer ();
   length = 0;
   while ((code = (enum tree_code) va_arg (args, int)))
     {
@@ -9802,14 +9810,16 @@ tree_range_check_failed (const_tree node, const char *file, int line,
 			 enum tree_code c2)
 {
   char *buffer;
-  unsigned length = 0;
+  protected_alloca buffer_alloca;
+  size_t length = 0;
   unsigned int c;
 
   for (c = c1; c <= c2; ++c)
     length += 4 + strlen (get_tree_code_name ((enum tree_code) c));
 
   length += strlen ("expected ");
-  buffer = (char *) alloca (length);
+  buffer_alloca.alloc (length);
+  buffer = (char *) buffer_alloca.pointer ();
   length = 0;
 
   for (c = c1; c <= c2; ++c)
@@ -9863,14 +9873,16 @@ omp_clause_range_check_failed (const_tree node, const char *file, int line,
 			       enum omp_clause_code c2)
 {
   char *buffer;
-  unsigned length = 0;
+  protected_alloca buffer_alloca;
+  size_t length = 0;
   unsigned int c;
 
   for (c = c1; c <= c2; ++c)
     length += 4 + strlen (omp_clause_code_name[c]);
 
   length += strlen ("expected ");
-  buffer = (char *) alloca (length);
+  buffer_alloca.alloc (length);
+  buffer = (char *) buffer_alloca.pointer ();
   length = 0;
 
   for (c = c1; c <= c2; ++c)
