Bug 2344173 - New error building SGX "requested alignment is not an integer constant -Wtemplate-body" with G++ 15
Summary: New error building SGX "requested alignment is not an integer constant -Wtemp...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: gcc
Version: 42
Hardware: Unspecified
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: 2342978
TreeView+ depends on / blocked
 
Reported: 2025-02-06 12:14 UTC by Daniel Berrangé
Modified: 2026-05-06 13:33 UTC (History)
13 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2026-05-06 13:33:52 UTC
Type: ---
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
GNU Compiler Collection 118773 0 P1 RESOLVED [15 Regression] Invalid rejection of attribute with dependent argument since r15-3046 2026-05-06 13:32:54 UTC

Description Daniel Berrangé 2025-02-06 12:14:46 UTC
When attempting to build Intel SGX for Fedora 42 / Rawhide, I'm seeing a build failure from G++ that was not present in GCC <= 14. It complains when anything imports this header:

  https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/main/QuoteGeneration/common/inc/internal/linux/sgx_random_buffers.h

With a message like:

  In file included from ../quoting_enclave_3.cpp:41:
  ../../../../common/inc/internal/linux/sgx_random_buffers.h:261:44: error: requested alignment   is not an integer constant [-Wtemplate-body]
    261 |     using storage = char[size(C)] alignas(A);
        |                                            ^

I narrowed it down to this demo code:

  $ cat > demo.cpp <<EOF
  #include <utility>

  template <class T, std::size_t A, unsigned M = 0x1000>
  struct alignas(A)randomly_placed_buffer
  {
      static constexpr std::size_t size(std::size_t count = 1)
      {
          return sizeof(T) * count + M - A;
      }

      template <unsigned C = 1>
      using storage = char[size(C)] alignas(A);
  };
  EOF

I'm not too familiar with C++, I guess it is trying to say it doesn't know whether 'A' will be provided as a constant or a variable when the template is instantiated ?

The expected usage of this template would be

  template <class T, unsigned M = 0x1000>
  using randomly_placed_object = randomly_placed_buffer<T, alignof(T), M>;

where 'alignof(T)' should be a compile time constant, so in practice it would be fine IIUC.

I don't see a nice way to change the code to avoid this, so AFAICT the only option is to set '-Wno-template-body', or '-Wno-error=template-body'.

If you think G++ raising an error in this scenario is genuinely a desirable thing, feel free to close this as NOTABUG. 

I just wanted to file this bug in case this is an unexpected consequence of the new warning code, especially since it has defaulted to implying -Werror which is quite harsh IMHO.


Reproducible: Always

Steps to Reproduce:
1. Save above code snippet to demo.cpp
2. Run 'g++ -c demo.cpp'
Actual Results:  
$ g++ -Wno-error  -c demo.cpp 
demo.cpp:12:44: error: requested alignment is not an integer constant [-Wtemplate-body]
   12 |     using storage = char[size(C)] alignas(A);
      |                              

$ g++ --version
g++ (GCC) 15.0.1 20250201 (Red Hat 15.0.1-0)


Expected Results:  
Ideally no error, or at least merely a warning  ?

Comment 1 Jonathan Wakely 2025-02-06 12:35:52 UTC
(In reply to Daniel Berrangé from comment #0)
> I narrowed it down to this demo code:
> 
>   $ cat > demo.cpp <<EOF
>   #include <utility>
> 
>   template <class T, std::size_t A, unsigned M = 0x1000>
>   struct alignas(A)randomly_placed_buffer
>   {
>       static constexpr std::size_t size(std::size_t count = 1)
>       {
>           return sizeof(T) * count + M - A;
>       }
> 
>       template <unsigned C = 1>
>       using storage = char[size(C)] alignas(A);
>   };
>   EOF
> 
> I'm not too familiar with C++, I guess it is trying to say it doesn't know
> whether 'A' will be provided as a constant or a variable when the template
> is instantiated ?

It seems to be saying that, but it's nonsense. A is a template parameter so is always a constant that will be known when the template is instantiated.

> The expected usage of this template would be
> 
>   template <class T, unsigned M = 0x1000>
>   using randomly_placed_object = randomly_placed_buffer<T, alignof(T), M>;
> 
> where 'alignof(T)' should be a compile time constant, so in practice it
> would be fine IIUC.

It's always a compile-time constant, because you can't instantiate templates with non-constants.

I think the actual problem is that this use of alignas on a type alias is non-standard, and GCC seems to want to apply the alignas(A) immediately, before the template is instantiated, and at that point the value isn't known.

Other compiles just reject the code outright:

$ clang++ -c  x.cc
x.cc:12:37: error: 'alignas' attribute cannot be applied to types
   12 |       using storage = char[size(C)] alignas(A);
      |                                     ^
1 error generated.


$ edg --c++17 x.cc
"x.cc", line 12: error: alignas does not apply here
        using storage = char[size(C)] alignas(A);
                                      ^

1 error detected in the compilation of "x.cc".

 
> I don't see a nice way to change the code to avoid this, so AFAICT the only
> option is to set '-Wno-template-body', or '-Wno-error=template-body'.

You can disable it locally:

#pragma GCC diagnostic push
#if __GNUC__ >= 15
#pragma GCC diagnostic ignored "-Wtemplate-body"
#endif
      template <unsigned C = 1>
      struct storage = char[size(C)] alignas(A);
#pragma GCC diagnostic pop

But that only silences the -Wtemplate-body diagnostic, you'll still get an error if the template is ever instantiated:


x.cc: In instantiation of 'struct randomly_placed_buffer<long int, 16, 4096>':
x.cc:24:30:   required from here
   24 | randomly_placed_object<long> l{};
      |                              ^
x.cc:4:20: error: instantiating erroneous template
    4 |   struct alignas(A)randomly_placed_buffer
      |                    ^~~~~~~~~~~~~~~~~~~~~~
x.cc:16:46: note: first error appeared here
   16 |       using storage = char[size(C)] alignas(A);
      |                                              ^

And "erroneous template" is not at all clear what's going on!
 
> If you think G++ raising an error in this scenario is genuinely a desirable
> thing, feel free to close this as NOTABUG. 

I think this is a GCC regression. Either we should accept the misplaced alignas as an extension, or reject it with a correct error. What GCC 15 is doing is just unhelpful.

Even if we accept it, there should be a diagnostic with -pedantic to tell you it's not valid C++.


> I just wanted to file this bug in case this is an unexpected consequence of
> the new warning code, especially since it has defaulted to implying -Werror
> which is quite harsh IMHO.

I'll report this upstream.

Comment 2 Jakub Jelinek 2025-02-06 12:37:57 UTC
Testcase without headers:
namespace std { using size_t = decltype (sizeof 0); }
template <class T, std::size_t A, unsigned M = 0x1000>                                                                                                                              
struct alignas(A) randomly_placed_buffer                                                                                                                                             
{                                                                                                                                                                                   
  static constexpr std::size_t size(std::size_t count = 1)                                                                                                                        
  {                                                                                                                                                                               
    return sizeof(T) * count + M - A;                                                                                                                                           
  }                                                                                                                                                                               
  template <unsigned C = 1>                                                                                                                                                       
  using storage = char[size(C)] alignas(A);                                                                                                                                       
};                                                                                                                                                                                  
randomly_placed_buffer<char,4> r;

This started to be rejected with my https://gcc.gnu.org/r15-3046

Comment 3 Jakub Jelinek 2025-02-06 13:02:08 UTC
Note, we already do reject alignas on typedef/using or array types:
typedef int L alignas (int);                    // { dg-error "'alignas' on a type alias" }
using foobar alignas (int) = int;               // { dg-error "'alignas' on a type alias" }
int g[2] alignas (int);                         // { dg-error "'alignas' on a type other than class" }
but
using x = char[1] alignas(1);
using y = char alignas(1);
is still incorrectly accepted.

Comment 4 Jakub Jelinek 2025-02-06 14:44:27 UTC
Ah, actually we diagnose even those, but just with -pedantic or -pedantic-errors, otherwise it is accepted as an extension.

Comment 5 Jakub Jelinek 2025-02-06 15:13:14 UTC
Filed upstream and I have a fix.  In any case, as Jonathan said, this is invalid C++, so either use [[gnu::aligned(A)]] there instead, or appertain alignas only to what the standard allows, i.e. struct/class/union/enum definition, or to variables, members and the like, not other types.

Comment 6 Daniel Berrangé 2025-02-13 14:49:04 UTC
> Link ID: GNU Compiler Collection 118773

I tested the upstream patch mentioned on this ticket and it solves the linux-sgx build problems I had. Could we get an updated gcc built into both F42 & rawhide for this fix, as it is a blocker for importing linux-sgx which is a F42 approved change.

Comment 7 Jakub Jelinek 2025-02-13 15:47:01 UTC
That is not possible right now, there is an important recent upstream regression that needs to be fixed first.
There will be definitely a new gcc build within the new 14 days, but when exactly that will happen is hard to say now.

I'd strongly suggest to fix the broken linux-sgx code instead, as I wrote, it isn't valid C++ as written.
I don't see randomly_placed_buffer::storage being used anywhere, so perhaps just comment it out, or comment out the bogus alignas in there?

Comment 8 Fedora Release Engineering 2026-05-06 12:25:58 UTC
This message is a reminder that Fedora Linux 42 is nearing its end of life.
Fedora will stop maintaining and issuing updates for Fedora Linux 42 on 2026-05-13.
It is Fedora's policy to close all bug reports from releases that are no longer
maintained. At that time this bug will be closed as EOL if it remains open with a
'version' of '42'.

Package Maintainer: If you wish for this bug to remain open because you
plan to fix it in a currently maintained version, change the 'version' 
to a later Fedora Linux version. Note that the version field may be hidden.
Click the "Show advanced fields" button if you do not see it.

Thank you for reporting this issue and we are sorry that we were not 
able to fix it before Fedora Linux 42 is end of life. If you would still like 
to see this bug fixed and are able to reproduce it against a later version 
of Fedora Linux, you are encouraged to change the 'version' to a later version
prior to this bug being closed.

Comment 9 Jonathan Wakely 2026-05-06 13:33:52 UTC
This was fixed for the final GCC 15.1 release.


Note You need to log in before you can comment on or make changes to this bug.