Issue 208705
Summary [clang][Sema] Segfault in Expr::getReferencedDeclOfCallee via CheckNoInlineAttr during template instantiation of variadic function with [[clang::noinline]] on return statement
Labels
Assignees
Reporter YuanchengJiang
    The following code:

```cpp
template<int D>
template<int D>
int dependent(int x){ return x + D;}
[[clang::always_inline]]
int non_dependent(int x){return x;}
template<int ... D>
int variadic_qux(int x) {
  [[msvc::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
}
void use() {
  variadic_baz<0, 1, 2>(0); // #VARIADIC_INST
```

Resulted in this output:
```
/tmp/test.cpp:7:3: warning: 'msvc::noinline' attribute only applies to functions and statements [-Wignored-attributes]
    7 | [[msvc::noinline]] static int j = bar();
 |   ^
/tmp/test.cpp:7:35: error: use of undeclared identifier 'bar'
    7 | [[msvc::noinline]] static int j = bar();
      | ^~~
/tmp/test.cpp:10:3: warning: 'clang::noinline' attribute only applies to functions and statements [-Wignored-attributes]
   10 | [[clang::noinline]] static int i = bar();
      |   ^
/tmp/test.cpp:10:36: error: use of undeclared identifier 'bar'
   10 | [[clang::noinline]] static int i = bar();
      | ^~~
/tmp/test.cpp:11:15: error: expected ';' after struct
   11 | struct Tag1 {}
      |               ^
      | ;
/tmp/test.cpp:12:15: error: expected ';' after struct
   12 | struct Tag4 {}
      |               ^
      |               ;
/tmp/test.cpp:25:5: error: 'clang::noinline' attribute takes no arguments
   25 | [[clang::noinline(0)]] bar(); // expected-error {{'clang::noinline' attribute takes no arguments}}
      |     ^
/tmp/test.cpp:27:23: warning: 'clang::noinline' attribute is ignored because there exists no call _expression_ inside the statement [-Wignored-attributes]
   27 | [[clang::noinline]] x = 0; // expected-warning {{'clang::noinline' attribute is ignored because there exists no call _expression_ inside the statement}}
 |                       ^
/tmp/test.cpp:28:23: warning: 'clang::noinline' attribute is ignored because there exists no call _expression_ inside the statement [-Wignored-attributes]
   28 |   [[clang::noinline]] { asm("nop"); } // expected-warning {{'clang::noinline' attribute is ignored because there exists no call _expression_ inside the statement}}
      | ^
/tmp/test.cpp:29:5: warning: 'clang::noinline' attribute only applies to functions and statements [-Wignored-attributes]
   29 | [[clang::noinline]] label: x = 1; // expected-warning {{'clang::noinline' attribute only applies to functions and statements}}
      | ^
/tmp/test.cpp:32:23: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   32 |   [[clang::noinline]] always_inline_fn(); // expected-warning {{statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline'}}
      | ^
/tmp/test.cpp:5:24: note: conflicting attribute is here
    5 | [[gnu::always_inline]] void always_inline_fn(void) { }
      | ^
/tmp/test.cpp:33:23: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'flatten' [-Wignored-attributes]
   33 |   [[clang::noinline]] flatten_fn(); // expected-warning {{statement attribute 'clang::noinline' has higher precedence than function attribute 'flatten'}}
      | ^
/tmp/test.cpp:3:18: note: conflicting attribute is here
    3 | [[gnu::flatten]] void flatten_fn(void) { }
      | ^
/tmp/test.cpp:36:21: warning: attribute is ignored on this statement as it only applies to functions; use '[[clang::noinline]]' on statements [-Wignored-attributes]
   36 |   [[gnu::noinline]] bar(); // expected-warning {{attribute is ignored on this statement as it only applies to functions; use '[[clang::noinline]]' on statements}}
      | ^
/tmp/test.cpp:37:29: warning: attribute is ignored on this statement as it only applies to functions; use '[[clang::noinline]]' on statements [-Wignored-attributes]
   37 |   __attribute__((noinline)) bar(); // expected-warning {{attribute is ignored on this statement as it only applies to functions; use '[[clang::noinline]]' on statements}}
      | ^
/tmp/test.cpp:41:5: error: 'msvc::noinline' attribute takes no arguments
   41 |   [[msvc::noinline(0)]] bar(); // expected-error {{'msvc::noinline' attribute takes no arguments}}
      | ^
/tmp/test.cpp:43:22: warning: 'msvc::noinline' attribute is ignored because there exists no call _expression_ inside the statement [-Wignored-attributes]
   43 |   [[msvc::noinline]] x = 0; // expected-warning {{'msvc::noinline' attribute is ignored because there exists no call _expression_ inside the statement}}
      | ^
/tmp/test.cpp:44:22: warning: 'msvc::noinline' attribute is ignored because there exists no call _expression_ inside the statement [-Wignored-attributes]
   44 |   [[msvc::noinline]] { asm("nop"); } // expected-warning {{'msvc::noinline' attribute is ignored because there exists no call _expression_ inside the statement}}
      | ^
/tmp/test.cpp:45:5: warning: 'msvc::noinline' attribute only applies to functions and statements [-Wignored-attributes]
   45 |   [[msvc::noinline]] label: x = 1; // expected-warning {{'msvc::noinline' attribute only applies to functions and statements}}
      |     ^
/tmp/test.cpp:47:22: warning: statement attribute 'msvc::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   47 | [[msvc::noinline]] always_inline_fn(); // expected-warning {{statement attribute 'msvc::noinline' has higher precedence than function attribute 'always_inline'}}
      |                      ^
/tmp/test.cpp:5:24: note: conflicting attribute is here
    5 | [[gnu::always_inline]] void always_inline_fn(void) { }
      | ^
/tmp/test.cpp:48:22: warning: statement attribute 'msvc::noinline' has higher precedence than function attribute 'flatten' [-Wignored-attributes]
 48 |   [[msvc::noinline]] flatten_fn(); // expected-warning {{statement attribute 'msvc::noinline' has higher precedence than function attribute 'flatten'}}
      |                      ^
/tmp/test.cpp:3:18: note: conflicting attribute is here
    3 | [[gnu::flatten]] void flatten_fn(void) { }
      |                  ^
/tmp/test.cpp:56:33: error: comparison between pointer and integer ('void (*)()' and 'int')
   56 | [[clang::noinline]] return foo<D-1>(x + 1);
      | ~~~^~~~
/tmp/test.cpp:56:23: warning: 'clang::noinline' attribute is ignored because there exists no call _expression_ inside the statement [-Wignored-attributes]
   56 |   [[clang::noinline]] return foo<D-1>(x + 1);
      |                       ^
/tmp/test.cpp:59:3: warning: attribute declaration must precede definition [-Wignored-attributes]
   59 | [[clang::always_inline]]
      |   ^
/tmp/test.cpp:55:5: note: previous definition is here
   55 | int dependent(int x) {
      | ^
/tmp/test.cpp:60:5: error: redefinition of 'dependent'
   60 | int dependent(int x){ return x + D;}
      |     ^
/tmp/test.cpp:55:5: note: previous definition is here
   55 | int dependent(int x) {
      | ^
/tmp/test.cpp:70:23: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   70 |   [[clang::noinline]] non_dependent(x);
 |                       ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
/tmp/test.cpp:78:25: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   78 |     [[clang::noinline]] return non_dependent(x), baz<D-1>(x + 1);
      | ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
/tmp/test.cpp:92:23: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   92 | [[clang::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
 |                       ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
/tmp/test.cpp:98:22: warning: statement attribute 'msvc::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   98 |   [[msvc::noinline]] non_dependent(x);
 |                      ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
/tmp/test.cpp:106:24: warning: statement attribute 'msvc::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
  106 |     [[msvc::noinline]] return non_dependent(x), qux<D-1>(x + 1);
      | ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
/tmp/test.cpp:120:22: warning: statement attribute 'msvc::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
  120 | [[msvc::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
 |                      ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
/tmp/test.cpp:128:24: error: use of undeclared identifier 'get_line_constexpr'
  128 | const int global_three(get_line_constexpr());
 |                        ^~~~~~~~~~~~~~~~~~
/tmp/test.cpp:130:18: error: use of undeclared identifier 'get_line_constexpr'
  130 | int global_two = get_line_constexpr();
      | ^~~~~~~~~~~~~~~~~~
/tmp/test.cpp:165:2: error: expected ';' after struct
 165 | }
      |  ^
      |  ;
/tmp/test.cpp:78:25: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   78 |     [[clang::noinline]] return non_dependent(x), baz<D-1>(x + 1);
      | ^
/tmp/test.cpp:123:3: note: in instantiation of function template specialization 'baz<3>' requested here
  123 |   baz<3>(0); // #BAZ_INST
 |   ^
/tmp/test.cpp:67:1: note: conflicting attribute is here
   67 | int baz(int x) { // #BAZ
      | ^
/tmp/test.cpp:78:25: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   78 |     [[clang::noinline]] return non_dependent(x), baz<D-1>(x + 1);
      | ^
/tmp/test.cpp:78:50: note: in instantiation of function template specialization 'baz<2>' requested here
   78 |     [[clang::noinline]] return non_dependent(x), baz<D-1>(x + 1);
      | ^
/tmp/test.cpp:123:3: note: in instantiation of function template specialization 'baz<3>' requested here
  123 | baz<3>(0); // #BAZ_INST
      |   ^
/tmp/test.cpp:67:1: note: conflicting attribute is here
   67 | int baz(int x) { // #BAZ
      | ^
/tmp/test.cpp:78:25: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   78 |     [[clang::noinline]] return non_dependent(x), baz<D-1>(x + 1);
      | ^
/tmp/test.cpp:78:50: note: in instantiation of function template specialization 'baz<1>' requested here
   78 |     [[clang::noinline]] return non_dependent(x), baz<D-1>(x + 1);
      | ^
/tmp/test.cpp:78:50: note: in instantiation of function template specialization 'baz<2>' requested here
/tmp/test.cpp:123:3: note: in instantiation of function template specialization 'baz<3>' requested here
  123 |   baz<3>(0); // #BAZ_INST
 |   ^
/tmp/test.cpp:67:1: note: conflicting attribute is here
   67 | int baz(int x) { // #BAZ
      | ^
/tmp/test.cpp:92:50: error: no matching function for call to 'dependent'
   92 |   [[clang::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
      | ^~~~~~~~~~~~
/tmp/test.cpp:124:3: note: in instantiation of function template specialization 'variadic_baz<0, 1, 2>' requested here
  124 |   variadic_baz<0, 1, 2>(0); // #VARIADIC_INST
 |   ^
/tmp/test.cpp:60:5: note: candidate template ignored: substitution failure [with D = 2]
   60 | int dependent(int x){ return x + D;}
      | ^
/tmp/test.cpp:92:50: error: no matching function for call to 'dependent'
   92 |   [[clang::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
      | ^~~~~~~~~~~~
/tmp/test.cpp:60:5: note: candidate template ignored: substitution failure [with D = 1]
   60 | int dependent(int x){ return x + D;}
      |     ^
/tmp/test.cpp:92:50: error: no matching function for call to 'dependent'
   92 |   [[clang::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
      | ^~~~~~~~~~~~
/tmp/test.cpp:60:5: note: candidate template ignored: substitution failure [with D = 0]
   60 | int dependent(int x){ return x + D;}
      |     ^
/tmp/test.cpp:92:23: warning: statement attribute 'clang::noinline' has higher precedence than function attribute 'always_inline' [-Wignored-attributes]
   92 |   [[clang::noinline]] return non_dependent(x) + (dependent<D>(x) + ...);
      | ^
/tmp/test.cpp:63:1: note: conflicting attribute is here
   63 | int non_dependent(int x){return x;}
      | ^
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /usr/lib/llvm-22/bin/clang -cc1 -triple x86_64-pc-linux-gnu -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test.cpp -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/fuzz/WorkSpace/fusion-fuzz/projects/clang -fcoverage-compilation-dir=/home/fuzz/WorkSpace/fusion-fuzz/projects/clang -resource-dir /usr/lib/llvm-22/lib/clang/22 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/x86_64-linux-gnu/c++/15 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../include/c++/15/backward -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/15/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -ferr<truncated>Please see the issue for the entire body.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to