Bug 41091 - Using section attribute in c and c++ function causes section type conflict
Summary: Using section attribute in c and c++ function causes section type conflict
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2009-08-17 13:58 UTC by Mark Wielaard
Modified: 2022-05-18 17:03 UTC (History)
9 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.4.0, 4.9.4, 5.4.0, 6.4.0, 7.2.0, 8.0
Last reconfirmed: 2017-10-25 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Wielaard 2009-08-17 13:58:36 UTC
The following code that puts two static variables into their own section won't compile because of a section type conflict.

class C
{
public:
  void m()
  {
    static const int TWO __attribute__((section(".consts"))) = 2;
  }
}; 

static void c()
{
  static const int ONE __attribute__((section(".consts"))) = 1;
}

int
main (int argc, char **argv)
{
  C inst = C();
  inst.m();
  c();
  return 0;
}

$ g++ section.cxx 
section.cxx:12: error: ONE causes a section type conflict

The section should have the same type in both definitions, but apparently doesn't.
Comment 1 Andrew Pinski 2009-10-14 04:50:43 UTC
Actually, they have to have two different section types.

c::m()::TWO has to be in the comdat section for C::m().
While c()::ONE does not and can be in a normal section.
Comment 2 Mark Wielaard 2009-10-14 07:48:37 UTC
(In reply to comment #1)
> Actually, they have to have two different section types.
> 
> c::m()::TWO has to be in the comdat section for C::m().
> While c()::ONE does not and can be in a normal section.

INVALID? How is the user supposed to know (or care) about comdat? All they want is make sure the constants get put in the same section. So how can one specify that behavior for both ONE and TWO?
Comment 3 Mark Wielaard 2009-10-17 11:28:09 UTC
See comment #2.
Comment 4 Roland McGrath 2010-08-11 23:52:11 UTC
The compiler is being internally inconsistent here.  It somtimes decides that __attribute__((section ("name"))) means a "name" section in a COMDAT group, and sometimes decides that it means just a plain "name" section.  If it's going to have that behavior implicitly, then it should not call this a conflict.  Instead, it should implicitly recognize that the particular COMDAT version of "name" is a different animal than the non-COMDAT "name".

In fact, it has an arguably more severe version of this bug too:

	class C
	{
	public:
	  void m()
	  {
	    static int TWO __attribute__((section(".consts"))) = 2;
	  }
	};

	class D
	{
	public:
	  void m()
	  {
	    static int THREE __attribute__((section(".consts"))) = 2;
	  }
	};

	int
	main (int argc, char **argv)
	{
	  C inst = C();
	  inst.m();
	  D inst2 = D();
	  inst2.m();
	  return 0;
	}

For that, it happily puts TWO and THREE initializers both in the COMDAT group for C::m()::TWO, which is quite clearly wrong.  The left hand uses multiple different sections of the same name, but the right hand thinks that any section matching the simple name it's looking for is the same thing regardless of whether or not its a distinct COMDAT variant.
Comment 5 Martin Sebor 2017-02-07 23:34:24 UTC
I see no error for the test case in comment #0 with the top of trunk (GCC 7.0) so I'm resolving this report as fixed.  Please reopen it if the problem persists with different symptoms.
Comment 6 Benedek Thaler 2017-10-24 22:18:46 UTC
The following code reproduces this, or a very similar issue:

#define STORE(SECTION, STRING) \
  __attribute__((section(SECTION), used)) \
  static constexpr const char* s[] = { STRING }

void f()
{
  STORE(".custom", "normal_foobar");
}

inline void g()
{
  STORE(".custom", "inline_foobar");
}

template <typename = void>
void h()
{
  STORE(".custom", "template_foobar");
}

int main()
{
  f(); g(); h();
  return 0;
}

$ g++ -std=c++11 section.cpp
section.cpp: error: 's' causes a section type conflict with 's'

GCC 4.8, 5.2, 7.2, and trunk are affected (x86-64, checked on godbolt).
Depending on the compiler version, either the normal and the inline, or the normal and the function template clashes.

I suppose because of how comdat is handled, they might have slightly different needs, but it would be really nice to make it easier for the user.

(Clang compiles it fine)
Comment 7 Martin Sebor 2017-10-25 14:46:45 UTC
Thanks for the test case.  I can confirm the error on trunk (GCC 8.0).  Reopening.
Comment 8 David L. 2021-02-02 18:09:31 UTC
Issue persists in gcc 10.2, test program from comment #6 still errors out.

We're hitting this bug in production/real-world code [ https://github.com/FRRouting/frr/pull/6766 ].  What we're doing is very similar to SystemTap's trace points, I believe those might be affected as well.

clang++ works fine meanwhile.
Comment 9 Bobby Reynolds 2022-05-18 16:38:47 UTC
My team is also impacted by this issue (also with tracing code, as it turns out).

FWIW there's a great writeup explaining the issue on Stack Overflow:

https://stackoverflow.com/questions/35091862/inline-static-data-causes-a-section-type-conflict

In this writeup, the author suggests that perhaps -fno-gnu-unique should additionally cause GCC to _not_ use section grouping for the associated symbol; in this case GCC would simply emit a weak symbol without grouping, which I believe would match the (admittedly less robust) behavior of Clang.
Comment 10 Andrew Pinski 2022-05-18 17:03:52 UTC
I really doubt there is a good solution for this because of what c++ calls vague linkage. Clang's solution is broken too.