// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=HEURISTIC // RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DEBUG // Verify auto-selection works between debug info and heuristic fallback. When // we have at least -gline-directives-only we can use DILocation for accurate // inline locations. // Without that debug info we fall back to a heuristic approach using srcloc // metadata. [[gnu::warning("dangerous function")]] void dangerous(); // Non-static, non-inline functions that get inlined at -O2. void wrapper() { dangerous(); } void middle() { wrapper(); } void caller() { middle(); } // HEURISTIC: :16:{{.*}}: warning: call to '{{.*}}dangerous{{.*}}' // HEURISTIC: :16:{{.*}}: note: called by function '{{.*}}wrapper{{.*}}' // HEURISTIC: :16:{{.*}}: note: inlined by function '{{.*}}middle{{.*}}' // HEURISTIC: :16:{{.*}}: note: inlined by function '{{.*}}caller{{.*}}' // HEURISTIC: note: use '-gline-directives-only' (implied by '-g1') or higher for more accurate inlining chain locations // DEBUG: :16:{{.*}}: warning: call to '{{.*}}dangerous{{.*}}' // DEBUG: :16:{{.*}}: note: called by function '{{.*}}wrapper{{.*}}' // DEBUG: :20:{{.*}}: note: inlined by function '{{.*}}middle{{.*}}' // DEBUG: :24:{{.*}}: note: inlined by function '{{.*}}caller{{.*}}' // DEBUG-NOT: note: use '-gline-directives-only' // Test that functions in anonymous namespaces are properly tracked for // inlining chain diagnostics. Anonymous namespace functions have internal // linkage and are prime candidates for inlining. [[gnu::warning("do not call")]] void bad_func(); namespace { void anon_helper() { bad_func(); } void anon_middle() { anon_helper(); } } // namespace void public_caller() { anon_middle(); } // HEURISTIC: :49:{{.*}}: warning: call to '{{.*}}bad_func{{.*}}' // HEURISTIC: :49:{{.*}}: note: called by function '{{.*}}anon_helper{{.*}}' // HEURISTIC: :53:{{.*}}: note: inlined by function '{{.*}}anon_middle{{.*}}' // HEURISTIC: :58:{{.*}}: note: inlined by function '{{.*}}public_caller{{.*}}' // DEBUG: :49:{{.*}}: warning: call to '{{.*}}bad_func{{.*}}' // DEBUG: :49:{{.*}}: note: called by function '{{.*}}anon_helper{{.*}}' // DEBUG: :53:{{.*}}: note: inlined by function '{{.*}}anon_middle{{.*}}' // DEBUG: :58:{{.*}}: note: inlined by function '{{.*}}public_caller{{.*}}' // always_inline forces inlining but doesn't imply // isInlined() in the language sense. [[gnu::warning("always inline warning")]] void always_inline_target(); __attribute__((always_inline)) void always_inline_wrapper() { always_inline_target(); } void always_inline_caller() { always_inline_wrapper(); } // HEURISTIC: :79:{{.*}}: warning: call to '{{.*}}always_inline_target{{.*}}' // HEURISTIC: :79:{{.*}}: note: called by function '{{.*}}always_inline_wrapper{{.*}}' // HEURISTIC: :83:{{.*}}: note: inlined by function '{{.*}}always_inline_caller{{.*}}' // DEBUG: :79:{{.*}}: warning: call to '{{.*}}always_inline_target{{.*}}' // DEBUG: :79:{{.*}}: note: called by function '{{.*}}always_inline_wrapper{{.*}}' // DEBUG: :83:{{.*}}: note: inlined by function '{{.*}}always_inline_caller{{.*}}'