Bug 67368 - Inlining failed due to no_sanitize_address and always_inline conflict
Summary: Inlining failed due to no_sanitize_address and always_inline conflict
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: ipa (show other bugs)
Version: 4.9.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-08-27 07:51 UTC by Wojciech Mula
Modified: 2017-10-04 16:30 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-08-27 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wojciech Mula 2015-08-27 07:51:00 UTC
When compiling program

-- bug.cpp --
#include <emmintrin.h>

__attribute__((no_sanitize_address))                                             void foo() {
   __m128i z = _mm_setzero_si128();
}
-- eof --

using following command

$ g++ -c -fsanitize=address bug.cpp

GCC reports:

In file included from bug.cpp:1:0:
[...]/x86_64-unknown-linux-gnu/4.9.2/include/emmintrin.h: In function ‘void foo()’:
[...]/x86_64-unknown-linux-gnu/4.9.2/include/emmintrin.h:749:1: error: inlining failed in call to always_inline ‘__m128i _mm_setzero_si128()’: function attribute mismatch
 _mm_setzero_si128 (void)
 ^
bug.cpp:5:36: error: called from here
      __m128i z = _mm_setzero_si128();

Compiler version (built from the sources):

$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=[...]/libexec/gcc/x86_64-unknown-linux-gnu/4.9.2/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: [...]/source/gcc-4.9.2/configure --prefix=[...] --with-local-prefix=[...] --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 4.9.2 (GCC)

I've checked the sample program on https://gcc.godbolt.org/ and for versions 5.1.0 & 5.2.0 there is the same problem. However 4.9.2 from Ubuntu is not affected.
Comment 1 Richard Biener 2015-08-27 11:02:19 UTC
  /* Don't inline a function with mismatched sanitization attributes. */
  else if (!sanitize_attrs_match_for_inline_p (caller->decl, callee->decl))
    {
      e->inline_failed = CIF_ATTRIBUTE_MISMATCH;
      inlinable = false;

static bool
sanitize_attrs_match_for_inline_p (const_tree caller, const_tree callee)
{
  /* Don't care if sanitizer is disabled */
  if (!(flag_sanitize & SANITIZE_ADDRESS))
    return true;

  if (!caller || !callee)
    return true;

  return !!lookup_attribute ("no_sanitize_address",
      DECL_ATTRIBUTES (caller)) ==
      !!lookup_attribute ("no_sanitize_address",
      DECL_ATTRIBUTES (callee));

so it fails on purpose (not sure why though).  And it ignores always-inline.
I wonder if we should, for always-inline functions, inline anyway and output
a warning instead.
Comment 2 Yury Gribov 2015-08-27 11:36:17 UTC
(In reply to Richard Biener from comment #1)
> so it fails on purpose (not sure why though).  And it ignores always-inline.
> I wonder if we should, for always-inline functions, inline anyway and output
> a warning instead.

We prohibited this combination during ASan integration to kernel. Both always_inline and no_sanitize_address are strong requirements for compiler i.e. dropping any of these in favor of another would have unexpected effects and hurt usability.
Comment 3 Andrey Ryabinin 2015-09-08 15:11:58 UTC
(In reply to Yury Gribov from comment #2)
> (In reply to Richard Biener from comment #1)
> > so it fails on purpose (not sure why though).  And it ignores always-inline.
> > I wonder if we should, for always-inline functions, inline anyway and output
> > a warning instead.
> 
> We prohibited this combination during ASan integration to kernel. Both
> always_inline and no_sanitize_address are strong requirements for compiler
> i.e. dropping any of these in favor of another would have unexpected effects
> and hurt usability.

Nope, it was prohibited because no_sanitize_address didn't work for inlined function https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59600.
Comment 4 Loïc Yhuel 2017-10-04 16:30:35 UTC
(In reply to Andrey Ryabinin from comment #3)
> Nope, it was prohibited because no_sanitize_address didn't work for inlined
> function https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59600.

So this case should work : functions inlined into a no_sanitize_address function would have the sanitizer disabled.
Unlike the opposite, which could crash, this one only could fail to detect issues at runtime, so perhaps it should only be a warning.