@@ -6059,6 +6059,37 @@ that entity.
60596059
60606060#endif /* GNU_NAKED_ATTRIBUTE_ALLOWED || MICROSOFT_EXTENSIONS_ALLOWED */
60616061
6062+ static a_boolean gnu_accepts_noinline_on_inline_routine (an_attribute_ptr ap )
6063+ /*
6064+ ap is a GNU "noinline" attribute being applied to an inline routine. Return
6065+ TRUE if GCC accepts that combination silently in the context of ap. For
6066+ example:
6067+
6068+ inline __attribute__((noinline)) int f() { return 0; } // No warning.
6069+
6070+ This idiom is used to ensure a noinline function in a header file does not
6071+ cause linker errors. GCC in C mode will warn on this while it does not in C++.
6072+ */
6073+ {
6074+ a_boolean result = FALSE;
6075+ a_decl_parse_state * dps = (a_decl_parse_state * )ap -> assoc_info ;
6076+
6077+ if (!C_mode ()) {
6078+ if (dps == NULL ) {
6079+ /* The attribute is not being applied as part of a declaration, which
6080+ means it is being copied to a template instance. */
6081+ result = TRUE;
6082+ } else {
6083+ result = ap -> on_primary_declaration &&
6084+ (dps -> dso_flags &
6085+ (DSO_INLINE | DSO_CONSTEXPR | DSO_CONSTEVAL )) != 0 &&
6086+ !dps -> inline_on_earlier_decl ;
6087+ } /* if */
6088+ } /* if */
6089+ return result ;
6090+ } /* gnu_accepts_noinline_on_inline_routine */
6091+
6092+
60626093static char * apply_noinline_attr (an_attribute_ptr ap ,
60636094 char * entity ,
60646095 an_il_entry_kind entity_kind )
@@ -6069,15 +6100,16 @@ and return the entity.
60696100{
60706101 if (entity_kind == iek_routine ) {
60716102 a_routine_ptr rp = (a_routine_ptr )entity ;
6103+ a_boolean has_always_inline = FALSE;
6104+ #if GNU_EXTENSIONS_ALLOWED
6105+ has_always_inline = find_attribute (ak_always_inline ,
6106+ rp -> source_corresp .attributes ) != NULL ;
6107+ #endif /* GNU_EXTENSIONS_ALLOWED */
60726108 rp -> never_inline = TRUE;
60736109 if (rp -> is_inline && is_gcc_attribute (ap ) &&
60746110 (!rp -> source_corresp .is_class_member ||
6075- rp -> defined_outside_of_parent
6076- #if GNU_EXTENSIONS_ALLOWED
6077- || find_attribute (ak_always_inline , rp -> source_corresp .attributes )
6078- != NULL
6079- #endif /* GNU_EXTENSIONS_ALLOWED */
6080- )) {
6111+ rp -> defined_outside_of_parent || has_always_inline ) &&
6112+ (has_always_inline || !gnu_accepts_noinline_on_inline_routine (ap ))) {
60816113 pos_warning (ec_inline_gnu_noinline_conflict , & ap -> position );
60826114 } /* if */
60836115 } else {
0 commit comments