https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77787
Bug ID: 77787 Summary: segfault in mangle.c Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: petschy at gmail dot com Target Milestone: --- Background: while trying to put cold data to a dedicated section I managed to crash the compiler. The idea was that rarely used strings, eg src file names and expressions of assertions will be separated from normal data, resulting in better dcache utilization: void prn(const char*); void foo() { __attribute__((section(".cold_rodata"))) static const char x[] = "foo"; prn(x); } inline void bar() { __attribute__((section(".cold_rodata"))) static const char x[] = "bar"; prn(x); } int main() { foo(); bar(); } Let's pretend that the x[] arrays were put there by ASSERT() macros. Unfortunately, this won;t compile: $ g++ -c 20160928-section_type_conflict.cpp 20160928-section_type_conflict.cpp:9:20: error: x causes a section type conflict with x static const char x[] = "bar"; ^ 20160928-section_type_conflict.cpp:4:20: note: ‘x’ was declared here static const char x[] = "foo"; ^ I know, I know: I shouldn't be using __attribute__ on non-globals. Unfortunately, there is no hot/cold attribute for data, only for code. For my specific case, a 'cold' data attribute would partly solve the problem, but that's probably another discussion. The explanation can be found here, along with proposed solutions: http://stackoverflow.com/questions/35091862/inline-static-data-causes-a-section-type-conflict I thought that rather than messing with __asm__, I go full ret^H^H^Hcrafty: instead of the static x[], I define a local struct with a static inline fn, which has the static x[] in the desired section. This way x[] is always in an inline function, so the conflict goes away. The result: gcc segfaults. 5.4.1, 6.2.1 and 7.0.0 all do it. I built a -g -O0 from 7.0, this is the output: common/src/dbgmac.h:264:23: internal compiler error: in operator[], at vec.h:732 DBG_STRING_DEF(expr_str, #expr); \ ^ common/src/platform.h:97:29: note: in definition of macro ‘CONCAT_’ #define CONCAT_(a_, b_) a_ ## b_ ^~ common/src/platform.h:99:33: note: in expansion of macro ‘CONCAT2’ #define CONCAT3(a_, b_, c_) CONCAT2(CONCAT2(a_, b_), c_) ^~~~~~~~~~ common/src/platform.h:98:29: note: in expansion of macro ‘CONCAT_’ #define CONCAT2(a_, b_) CONCAT_(a_, b_) ^~~~~~~~~~ common/src/platform.h:99:44: note: in expansion of macro ‘CONCAT2’ #define CONCAT3(a_, b_, c_) CONCAT2(CONCAT2(a_, b_), c_) ^~~~~~~~~~ common/src/dbgmac.h:73:34: note: in expansion of macro ‘CONCAT3’ #define UNIQ_VAR_NAME(n_) CONCAT3(n_, _, __LINE__) ^~~~~~~~~~ common/src/dbgmac.h:86:22: note: in expansion of macro ‘UNIQ_VAR_NAME’ static const char UNIQ_VAR_NAME(var_) [] = val_; \ ^~~~~~~~~~~~~~~~~ common/src/dbgmac.h:264:4: note: in expansion of macro ‘DBG_STRING_DEF’ DBG_STRING_DEF(expr_str, #expr); \ ^~~~~~~~~~~~~~~~~~ common/src/dbgmac.h:208:35: note: in expansion of macro ‘HARD_ASSERT’ #define ASSERT(expr, args...) HARD_ASSERT(expr, ## args); ^~~~~~~~~~~~~~~ common/src/json.hpp:1493:2: note: in expansion of macro ‘ASSERT’ ASSERT(div_ != 0); ^~~~~~~~~~ 0x7c190a vec<tree_node*, va_gc, vl_embed>::operator[](unsigned int) ../../gcc/vec.h:732 0xa2f260 local_class_index ../../gcc/cp/mangle.c:1845 0xa2f9ea discriminator_for_local_entity ../../gcc/cp/mangle.c:1881 0xa2fd6f write_local_name ../../gcc/cp/mangle.c:1972 0xa299c0 write_name ../../gcc/cp/mangle.c:917 0xa291f0 write_encoding ../../gcc/cp/mangle.c:779 0xa2fb5d write_local_name ../../gcc/cp/mangle.c:1941 0xa299c0 write_name ../../gcc/cp/mangle.c:917 0xa291f0 write_encoding ../../gcc/cp/mangle.c:779 0xa28c89 write_mangled_name ../../gcc/cp/mangle.c:744 0xa39b28 mangle_decl_string ../../gcc/cp/mangle.c:3709 0xa39b6e get_mangled_id ../../gcc/cp/mangle.c:3731 0xa3a032 mangle_decl(tree_node*) ../../gcc/cp/mangle.c:3801 0x145f393 decl_assembler_name(tree_node*) ../../gcc/tree.c:669 0xbd4c72 symbol_table::insert_to_assembler_name_hash(symtab_node*, bool) ../../gcc/symtab.c:171 0xbd4fef symbol_table::symtab_initialize_asm_name_hash() ../../gcc/symtab.c:263 0xbd71dc symtab_node::get_for_asmname(tree_node const*) ../../gcc/symtab.c:930 0xbf366d handle_alias_pairs ../../gcc/cgraphunit.c:1258 0xbf75e2 symbol_table::finalize_compilation_unit() ../../gcc/cgraphunit.c:2541 Please submit a full bug report, Nothing fancy on the command line, just -I's -D's, does it with -O0 and -O3, too (though since it's probably a mangle bug, the optimization level should not matter). Unfortunately, this is a closed source project, so I can't post the [preprocessed] code. I tried to reduce it, but as luck would have it, then everything goes just fine. Here is the reduced test: #include <stdio.h> #define CONCAT_(a_, b_) a_ ## b_ #define CONCAT2(a_, b_) CONCAT_(a_, b_) #define CONCAT3(a_, b_, c_) CONCAT2(CONCAT2(a_, b_), c_) #define CONCAT4(a_, b_, c_, d_) CONCAT2(CONCAT3(a_, b_, c_), d_) #define LIKELY(expr_) __builtin_expect(!!(expr_), 1) #define UNLIKELY(expr_) __builtin_expect(!!(expr_), 0) #define UNIQ_VAR_NAME(n_) CONCAT3(n_, _, __LINE__) #define DBG_STRING_DEF(var_, val_) \ struct CONCAT4(DbgStringDefHelper_, var_, _, __LINE__) { \ static inline const char* Get() { \ __attribute__((section(".rodata.cold.debug"))) \ static const char UNIQ_VAR_NAME(var_) [] = val_; \ return UNIQ_VAR_NAME(var_); \ } \ } #define DBG_STRING_GET(var_) CONCAT4(DbgStringDefHelper_, var_, _, __LINE__)::Get() #define ASSERT(expr, args...) \ if (LIKELY(expr)) { } else \ { \ DBG_STRING_DEF(file_str, __FILE__); \ DBG_STRING_DEF(expr_str, #expr); \ dbg_assert(DBG_STRING_GET(file_str), __LINE__, DBG_STRING_GET(expr_str), ## args); \ } void dbg_assert(const char* file_, int line_, const char* expr_, ...) { fprintf(stderr, "%s:%d: ASSERTION FAILED: '%s' is FALSE\n", file_, line_, expr_); } namespace baz { //inline void foo(int x) { ASSERT(x == 42); } template<typename T> //inline void bar(T x) { ASSERT(x == 42); } } // ns baz int main() { using namespace baz; foo(23); bar(11); } I tried to make the functions inline, and/or putting them in the global namespace, but no luck. The error message says that the bug was triggered by the assertion in the json header at line 1493. That's in a free standing function template, the last one in the header and in the whole preprocessed compilation unit. If I delete the fn from the header, the error remains, but then it is reported on the previous fn. If I delete many functions, the error remains, but moves to a different header. There are 28 assertions total, so I though maybe that's too much, but putting 30 assertions in bar() didn't trigger the error. I ran out of immediate ideas. I have the core dump, the error is 100% reproducible, just not in the reduced test. If you have ideas how to extract more info, please let me know. Meanwhile, I will try to enhance the test to trigger.