This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] 69780 - [4.9/5/6 Regression] ICE on __builtin_alloca_with_align, with small alignment


On 02/17/2016 03:50 PM, Jakub Jelinek wrote:
On Wed, Feb 17, 2016 at 01:48:26PM -0700, Martin Sebor wrote:
I shifted the alignment so that it could be compared against
MAX_STACK_ALIGNMENT.  But after some searching it seems as though
MAX_STACK_ALIGNMENT is in bits, rather than bytes as I had assumed,
so I've removed the shift.

The reason why MAX_STACK_ALIGNMENT is wrong is that on most targets
it is terribly small number (a couple of bytes usually), only i?86/x86_64 is
an exception, because it is the only target that supports dynamic stack
realignment.

I see. Thank you for the explanation.  I've confirmed it in
an arm-eabi cross compiler where MAX_STACK_ALIGNMENT is 64.

What I still don't understand is why a user-specified alignment
is being tested for inequality to MAX_STACK_ALIGNMENT in
check_cxx_fundamental_alignment_constraints (the code whose
example I followed):

7765 #undef MAX_TARGET_FIELD_ALIGNMENT
7766 /* For stack variables, the target supports at most
7767 MAX_STACK_ALIGNMENT. */
7768 else if (decl_function_context (node) != NULL
7769 && requested_alignment > (max_align = MAX_STACK_ALIGNMENT))
7770 alignment_too_large_p = true;

That would then seem also wrong, although I haven't been able to
trigger that code with a simple test case because the call to
decl_function_context() always returns null, so maybe the code
is never used.

All other targets do support more aligned variables than that, but because
they don't support dynamic stack realignment, they handle those more aligned
automatic variables by doing alloca instead.  Which is exactly why we need
__builtin_alloca_with_align to support those larger alignments.
There is no inherent reason why __builtin_alloca_with_align can't support
arbitrary (power of 2 > BITS_PER_UNITS of course) alignments, as long as
it fits into address space and the alignment doesn't run into other memory,
but that is the general problem of alloca, it is up to the user to ensure
he doesn't run out of the stack, and the alignment is no different.

I introduced the check for the upper bound because larger alignment
values (1L << 32 and greater) also cause an ICE.

Imposing the same constraint as on overaligned stack variables which
are rejected when the alignment is greater than 1 << 28 bytes avoids
the ICE:

  void f (void) {
    alignas (1LU << 29) int i;
  }

It looks like I was just unlucky enough to pick the wrong piece
of code to put the constraint in place (i.e.,
check_cxx_fundamental_alignment_constraints.

I've adjusted the patch to use similar logic as in
check_user_alignment().  I've also adjusted the documentation to
mention the upper bound, leaving the exact upper bound unspecified
since I get the impression that it's imposed by the internals of
the implementation and might change in the future.

No, see above.  And, if you want the exact largest possible power of 2
smaller than ~0U, you can use (unsigned int) INTTYPE_MINIMUM (int).

I was looking for the largest possible power of 2 greater than
~0U but something like this will do.  I believe it evaluates to
the same result as (UINT_MAX/2 + 1) and the latter seems clearer
and safer to me (based on the comments about compiler bugs near
the definition of INTTYPE_MINIMUM and based on the fact that
there are only two uses of the macro in the code base, neither
of which using int as its argument).

Attached is the updated patch.  Hopefully it's acceptable.

Martin
PR middle-end/69780 - [4.9/5/6 Regression] ICE on __builtin_alloca_with_align
	with small alignment
PR c/69759 - __builtin_alloca and __builtin_alloca_with_align undocumented

gcc/c-family/ChangeLog:
2016-02-17  Martin Sebor  <msebor@redhat.com>

	PR middle-end/69780
	* c-common.c (check_builtin_function_arguments): Validate and reject
	invalid arguments to __builtin_alloca_with_align.

gcc/ChangeLog:
2016-02-17  Martin Sebor  <msebor@redhat.com>

	PR c/69759
	* doc/extend.texi (Other Builtins): Document __builtin_alloca and
	__builtin_alloca_with_align.

gcc/testsuite/ChangeLog:
2016-02-17  Martin Sebor  <msebor@redhat.com>

	PR middle-end/69780
	* g++.dg/ext/builtin_alloca.C: New test.
	* gcc.dg/builtins-68.c: New test.

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 233476)
+++ gcc/c-family/c-common.c	(working copy)
@@ -9818,6 +9818,33 @@ check_builtin_function_arguments (tree f
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
+    case BUILT_IN_ALLOCA_WITH_ALIGN:
+      {
+	/* Get the requested alignment (in bits) if it's a constant
+	   integer expression.  */
+	unsigned HOST_WIDE_INT align = TREE_CODE (args[1]) == INTEGER_CST
+	  && tree_fits_uhwi_p (args[1]) ? tree_to_uhwi (args[1]) : 0;
+
+	/* Determine if the requested alignment is a power of 2.  */
+	if ((align & (align - 1)))
+	  align = 0;
+
+	/* The maximum alignment in bits corresponding to the same
+	   maximum in bytes enforced in check_user_alignment().  */
+	unsigned maxalign = (UINT_MAX >> 1) + 1;
+  
+	/* Reject invalid alignments.  */
+	if (align < BITS_PER_UNIT || maxalign < align)
+	  {
+	    error_at (EXPR_LOC_OR_LOC (args [1], input_location),
+		      "second argument to function %qE must be a constant "
+		      "integer power of 2 between %qi and %qu bits",
+		      fndecl, BITS_PER_UNIT, maxalign);
+	    return false;
+	  }
+      return true;
+      }
+
     case BUILT_IN_CONSTANT_P:
       return builtin_function_validate_nargs (fndecl, nargs, 1);
 
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 233476)
+++ gcc/doc/extend.texi	(working copy)
@@ -10144,6 +10144,8 @@ in the Cilk Plus language manual which c
 @node Other Builtins
 @section Other Built-in Functions Provided by GCC
 @cindex built-in functions
+@findex __builtin_alloca
+@findex __builtin_alloca_with_align
 @findex __builtin_call_with_static_chain
 @findex __builtin_fpclassify
 @findex __builtin_isfinite
@@ -10690,6 +10692,90 @@ In the same fashion, GCC provides @code{
 @code{__builtin_} prefixed.  The @code{isinf} and @code{isnan}
 built-in functions appear both with and without the @code{__builtin_} prefix.
 
+@deftypefn {Built-in Function} void* __builtin_alloca (size_t size)
+The @code{__builtin_alloca} function must be called at block scope.
+The function allocates an object @var{size} bytes large on the stack
+of the calling function.  The object is aligned at the default stack
+alignment boundary for the target determined by the
+@code{__BIGGEST_ALIGNMENT__} macro.  @code{__builtin_alloca} returns
+a pointer to the first byte of the allocated object.  The lifetime of
+the allocated object ends just before the calling function returns to
+its caller.   This is so even when @code{__builtin_alloca} is called
+within a nested block.
+
+For example, the following function allocates eight objects of @code{n}
+bytes each on the stack, storing a pointer to each in consecutive elements
+of the array @code{a}.  It then passes the array to function @code{g()}
+which can safely use the storage pointed to by each of the array elements.
+
+@smallexample
+void f (unsigned n)
+@{
+  void *a [8];
+  for (int i = 0; i != 8; ++i)
+    a [i] = __builtin_alloca (n);
+
+  g (a, n);   // safe
+@}
+@end smallexample
+
+Since the @code{__builtin_alloca} function doesn't validate its arguments
+it is the responsibility of its caller to make sure the argument doesn't
+cause it doesn't exceed the stack size limit.
+The @code{__builtin_alloca} function is provided to make it possible to
+allocate arrays with a runtime bound on the stack.  Since C99 variable
+length arrays offer similar functionality under a portable, more convenient,
+and safer interface they are recommended instead, in both C99 and C++
+programs where GCC provides them as an extension.
+
+@end deftypefn
+
+@deftypefn {Built-in Function} void* __builtin_alloca_with_align (size_t size, size_t align)
+The @code{__builtin_alloca_with_align} function must be called at block
+scope.  The function allocates an object @var{align} bytes large on
+the stack of the calling function.  The allocated object is aligned on
+the boundary specified by the argument @var{align} whose unit is given
+in bits (not bytes).  @var{size} must be positive and not exceed the stack
+size limit.  @var{align} must be a constant integer expression that
+evaluates to a power of 2 greater than or equal to @code{__CHAR_BIT__}
+and less than some unspecified maximum.  Invocations with other values
+are rejected with an error indicating the valid bounds.
+The function returns a pointer to the first byte of the allocated object.
+The lifetime of the allocated object ends at he end of the block in which
+the function was called.  The allocated storage is released no later than
+just before the calling function returns to its called, but may be released
+at the end of the block in which the function was called.
+
+For example, in the following function the call to @code{g()} is unsafe
+because when @code{overalign} is non-zero, the space allocated by
+@code{__builtin_alloca_with_align} may have been released at the end
+of the @code{if} statement in which it was called.
+
+@smallexample
+void f (unsigned n, bool overalign)
+@{
+  void *p;
+  if (overalign)
+    p = __builtin_alloca_with_align (n, 64);
+  else
+    p = __builtin_alloc (n);
+
+  g (p, n);   // unsafe
+@}
+@end smallexample
+
+Since the @code{__builtin_alloca_with_align} function doesn't validate its
+arguments it is the responsibility of its caller to make sure the argument
+doesn't cause it to exceed the stack size limit.
+The @code{__builtin_alloca_with_align} function is provided to make
+it possible to allocate overaligned arrays with a runtime bound on
+the stack.  Since C99 variable length arrays offer the same functionality
+under a portable, more convenient, and safer interface they are recommended
+instead, in both C99 and C++ programs where GCC provides them as
+an extension.
+
+@end deftypefn
+
 @deftypefn {Built-in Function} int __builtin_types_compatible_p (@var{type1}, @var{type2})
 
 You can use the built-in function @code{__builtin_types_compatible_p} to
Index: gcc/testsuite/gcc.dg/builtins-68.c
===================================================================
--- gcc/testsuite/gcc.dg/builtins-68.c	(revision 0)
+++ gcc/testsuite/gcc.dg/builtins-68.c	(working copy)
@@ -0,0 +1,110 @@
+/* PR middle-end/69780 - [4.9/5/6 Regression] ICE on
+     __builtin_alloca_with_align with small alignment */
+/* { dg-require-effective-target alloca } */
+/* { dg-do compile } */
+/* { dg-options "-Wno-long-long" } */
+
+#define CHAR_BIT  __CHAR_BIT__
+#define INT_MAX   __INT_MAX__
+#define INT_MIN   (-INT_MAX - 1)
+#define LONG_MAX  __LONG_MAX__
+#define LLONG_MAX __LONG_LONG_MAX__
+
+static void* p;
+
+/* Verify that valid __builtin_alloca_with_align expressions are accepted.  */
+void test_valid (int n)
+{
+  enum {
+    A1   = CHAR_BIT *   1,
+    A2   = CHAR_BIT *   2,
+    A4   = CHAR_BIT *   4,
+    A8   = CHAR_BIT *   8,
+    A16  = CHAR_BIT *  16,
+    A32  = CHAR_BIT *  32
+  };
+
+  /* Valid alignments are power of 2 positive multiples of CHAR_BIT.  */
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  1);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  2);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  4);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  8);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT * 16);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT * 32);
+
+  p =  __builtin_alloca_with_align (n, A1);
+  p =  __builtin_alloca_with_align (n, A2);
+  p =  __builtin_alloca_with_align (n, A4);
+  p =  __builtin_alloca_with_align (n, A8);
+  p =  __builtin_alloca_with_align (n, A16);
+  p =  __builtin_alloca_with_align (n, A32);
+}
+
+/* Non-integer alignments must be rejected.  */
+void test_arg2_non_int (int n)
+{
+  /* Verify the full text of the diagnostic just once.  */
+  p =  __builtin_alloca_with_align (n, 0.0);         /* { dg-error "second argument to function .__builtin_alloca_with_align. must be a constant integer power of 2 between .8. and " } */
+
+  /* Disable diagnostic complaining about converting void* to int that
+     preempts the "constant integer expression" error.  */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wint-conversion"
+
+  p =  __builtin_alloca_with_align (n, (void*)0);    /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, "");          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, L"");         /* { dg-error "must be a constant integer" } */
+
+#pragma GCC diagnostic pop
+
+}
+
+/* Integer alignment that's not a constant expression must be rejected.  */
+void test_arg2_non_const (int n, int a1)
+{
+  extern const int a2;
+  static const int a3 = CHAR_BIT;
+  static volatile const int a4 = CHAR_BIT;
+  
+  p =  __builtin_alloca_with_align (n, a1);       /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, a2);       /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, a3);       /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, a4);       /* { dg-error "must be a constant integer" } */
+}
+
+/* Constant integer alignment that's not a power of 2 positive multiple
+   of CHAR_BIT less than (1LLU << 32) must be rejected.  */
+void test_arg2_non_pow2 (int n)
+{
+  p =  __builtin_alloca_with_align (n, INT_MIN);     /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, -1);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, !1);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, !0);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  0);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  1);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  2);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  3);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  4);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  5);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  6);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  7);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n,  9);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 10);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 11);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 12);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 13);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 14);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 15);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 17);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 31);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 33);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 63);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 65);          /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, INT_MAX);     /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, ~0U);         /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, LONG_MAX);    /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, ~0LU);        /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 1LLU << 34);  /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, LLONG_MAX);   /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, ~0LLU);       /* { dg-error "must be a constant integer" } */
+}
Index: gcc/testsuite/g++.dg/ext/builtin_alloca.C
===================================================================
--- gcc/testsuite/g++.dg/ext/builtin_alloca.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/builtin_alloca.C	(working copy)
@@ -0,0 +1,191 @@
+// PR middle-end/69780 - [4.9/5/6 Regression] ICE on
+//     __builtin_alloca_with_align with small alignment
+// { dg-require-effective-target alloca }
+// { dg-do compile }
+
+#define CHAR_BIT  __CHAR_BIT__
+#define INT_MAX   __INT_MAX__
+#define INT_MIN   (-INT_MAX - 1)
+#define LONG_MAX  __LONG_MAX__
+#define LLONG_MAX __LONG_LONG_MAX__
+
+static void* p;
+
+// Verify that valid __builtin_alloca_with_align expressions are accepted.
+void test_valid (int n)
+{
+  enum {
+    A1   = CHAR_BIT *   1,
+    A2   = CHAR_BIT *   2,
+    A4   = CHAR_BIT *   4,
+    A8   = CHAR_BIT *   8,
+    A16  = CHAR_BIT *  16,
+    A32  = CHAR_BIT *  32
+  };
+
+  const int a1 = A1;
+  const int a2 = A2;
+  const int a4 = A4;
+  const int a8 = A8;
+  const int a16 = A16;
+  const int a32 = A32;
+
+  // Valid alignments are power of 2 positive multiples of CHAR_BIT.
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  1);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  2);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  4);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT *  8);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT * 16);
+  p =  __builtin_alloca_with_align (n, CHAR_BIT * 32);
+
+  p =  __builtin_alloca_with_align (n, A1);
+  p =  __builtin_alloca_with_align (n, A2);
+  p =  __builtin_alloca_with_align (n, A4);
+  p =  __builtin_alloca_with_align (n, A8);
+  p =  __builtin_alloca_with_align (n, A16);
+  p =  __builtin_alloca_with_align (n, A32);
+
+  p =  __builtin_alloca_with_align (n, a1);
+  p =  __builtin_alloca_with_align (n, a2);
+  p =  __builtin_alloca_with_align (n, a4);
+  p =  __builtin_alloca_with_align (n, a8);
+  p =  __builtin_alloca_with_align (n, a16);
+  p =  __builtin_alloca_with_align (n, a32);
+}
+
+template <int A> struct X { enum { Align = A }; };
+
+template <int A>
+void test_valid_template (int n)
+{
+  // Valid alignments are power of 2 positive multiples of CHAR_BIT.
+  p =  __builtin_alloca_with_align (n, A);
+}
+
+template void test_valid_template<CHAR_BIT>(int);
+template void test_valid_template<CHAR_BIT * 2>(int);
+template void test_valid_template<CHAR_BIT * 4>(int);
+template void test_valid_template<CHAR_BIT * 8>(int);
+template void test_valid_template<CHAR_BIT * 16>(int);
+template void test_valid_template<CHAR_BIT * 32>(int);
+
+// Exercise the alignment in a dependent context.
+template <int A>
+void test_valid_template_dep (int n)
+{
+  // Valid alignments are power of 2 positive multiples of CHAR_BIT.
+  p =  __builtin_alloca_with_align (n, X<A>::Align);
+}
+
+template void test_valid_template_dep<CHAR_BIT>(int);
+template void test_valid_template_dep<CHAR_BIT * 2>(int);
+template void test_valid_template_dep<CHAR_BIT * 4>(int);
+template void test_valid_template_dep<CHAR_BIT * 8>(int);
+template void test_valid_template_dep<CHAR_BIT * 16>(int);
+template void test_valid_template_dep<CHAR_BIT * 32>(int);
+
+// Invalid size must be rejected (and not cause an ICE).
+void test_arg1_non_int (int n)
+{
+  extern void f ();
+
+  p =  __builtin_alloca_with_align ((void*)0, 32);   // { dg-error "invalid conversion" }
+
+  p =  __builtin_alloca_with_align ("", 32);         // { dg-error "invalid conversion" }
+  p =  __builtin_alloca_with_align (L"", 32);        // { dg-error "invalid conversion" }
+  p =  __builtin_alloca_with_align (f, 32);          // { dg-error "invalid conversion" }
+}
+
+// Non-integer alignment must be rejected.
+void test_arg2_non_int (int n)
+{
+  // Verify the full text of the diagnostic just once.
+  p =  __builtin_alloca_with_align (n, 0.0);         // { dg-error "second argument to function .__builtin_alloca_with_align. must be a constant integer power of 2 between .8. and " }
+
+  p =  __builtin_alloca_with_align (n, (void*)0);    // { dg-error "invalid conversion|must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, "");          // { dg-error "invalid conversion|must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, L"");         // { dg-error "invalid conversion|must be a constant integer" }
+}
+
+// Integer alignment that's not a constant expression must be rejected.
+void test_arg2_non_const (int n, int a1)
+{
+  extern const int a2;
+  static volatile const int a3 = CHAR_BIT;
+  
+  p =  __builtin_alloca_with_align (n, a1);       // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, a2);       // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, a3);       // { dg-error "must be a constant integer" }
+}
+
+// Constant integer alignment that's not a power of 2 positive multiple
+// of CHAR_BIT must be rejected.
+void test_arg2_non_pow2 (int n)
+{
+  p =  __builtin_alloca_with_align (n, INT_MIN);     // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, -1);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, !1);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, !0);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  0);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  1);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  2);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  3);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  4);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  5);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  6);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  7);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n,  9);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 10);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 11);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 12);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 13);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 14);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 15);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 17);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 31);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 33);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 63);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, 65);          // { dg-error "must be a constant integer" }
+  p =  __builtin_alloca_with_align (n, INT_MAX);     /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, ~0U);         /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, LONG_MAX);    /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, ~0LU);        /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, 1LLU << 34);  /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, LLONG_MAX);   /* { dg-error "must be a constant integer" } */
+  p =  __builtin_alloca_with_align (n, ~0LLU);       /* { dg-error "must be a constant integer" } */
+}
+
+// Exercise invalid alignment specified by a template argument.
+template <int A>
+void test_invalid_template_1 (int n)
+{
+  // Valid alignments are power of 2 positive multiples of CHAR_BIT.
+  p =  __builtin_alloca_with_align (n, A);           // { dg-error "must be a constant integer" }
+}
+
+template void test_invalid_template_1<1>(int);
+
+template <int A>
+void test_invalid_template_7 (int n)
+{
+  p =  __builtin_alloca_with_align (n, A);           // { dg-error "must be a constant integer" }
+}
+
+template void test_invalid_template_7<7>(int);
+
+template <int A>
+void test_invalid_template_9 (int n)
+{
+  p =  __builtin_alloca_with_align (n, A);           // { dg-error "must be a constant integer" }
+}
+
+template void test_invalid_template_9<9>(int);
+
+// Exercise invalid alignment specified by a template dependent argument.
+template <int A>
+void test_invalid_template_dep_1 (int n)
+{
+  p =  __builtin_alloca_with_align (n, X<A>::Align);     // { dg-error "must be a constant integer" }
+}
+
+template void test_invalid_template_dep_1<1>(int);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]