[clang] [llvm] [Clang] Show inlining hints for __attribute__((warning/error)) (PR #174892)
Justin Stitt via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 20 10:59:44 PST 2026
https://github.com/JustinStitt updated https://github.com/llvm/llvm-project/pull/174892
>From 9bf61d2ef2ae81d6aa4c5f5bd7e0aa062298f0e0 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Tue, 6 Jan 2026 15:36:33 -0800
Subject: [PATCH 1/9] [Clang] Add -fdiagnostics-show-inlining-chain for
warning/error attributes
When functions marked with __attribute__((warning/error)) are called
through inlined functions, Clang now optionally shows the inlining chain
that led to the call.
Three modes are supported:
- ``none`` is the default and results in no inline notes being shown
(matches the behavior before this change).
- ``heuristic`` tries to guess which functions will be inlined to
minimize the amount of source locations kept in memory and visible in
LLVM IR.
- ``debug`` leverages minimal debug directive tracking infrastructure to
get more reliable source locations over the heuristic mode while
having more compile-time overhead.
Fixes: https://github.com/ClangBuiltLinux/linux/issues/1571
Based-on: https://github.com/llvm/llvm-project/pull/73552
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
clang/docs/ReleaseNotes.rst | 15 +++
clang/include/clang/Basic/AttrDocs.td | 7 ++
clang/include/clang/Basic/CodeGenOptions.def | 2 +
clang/include/clang/Basic/CodeGenOptions.h | 8 ++
.../clang/Basic/DiagnosticFrontendKinds.td | 6 +
clang/include/clang/Options/Options.td | 15 +++
clang/lib/CodeGen/CGCall.cpp | 23 ++--
clang/lib/CodeGen/CodeGenAction.cpp | 31 +++++
clang/lib/Driver/ToolChains/Clang.cpp | 7 ++
clang/lib/Frontend/CompilerInvocation.cpp | 8 ++
.../backend-attribute-inlining-cross-tu.c | 64 ++++++++++
...nd-attribute-inlining-debug-vs-heuristic.c | 28 +++++
.../backend-attribute-inlining-modes.c | 47 ++++++++
.../Frontend/backend-attribute-inlining.c | 109 ++++++++++++++++++
llvm/include/llvm/IR/DiagnosticInfo.h | 26 ++++-
llvm/lib/IR/DiagnosticInfo.cpp | 38 +++++-
llvm/lib/Transforms/Utils/InlineFunction.cpp | 44 +++++++
17 files changed, 468 insertions(+), 10 deletions(-)
create mode 100644 clang/test/Frontend/backend-attribute-inlining-cross-tu.c
create mode 100644 clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
create mode 100644 clang/test/Frontend/backend-attribute-inlining-modes.c
create mode 100644 clang/test/Frontend/backend-attribute-inlining.c
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b91d99647855c..2723ff61ef022 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -90,6 +90,21 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------
+- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
+- New option ``-fsanitize-debug-trap-reasons=`` added to control emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
+- New options for enabling allocation token instrumentation: ``-fsanitize=alloc-token``, ``-falloc-token-max=``, ``-fsanitize-alloc-token-fast-abi``, ``-fsanitize-alloc-token-extended``.
+- The ``-resource-dir`` option is now displayed in the list of options shown by ``--help``.
+- New option ``-fmatrix-memory-layout`` added to control the memory layout of Clang matrix types. (e.g. ``-fmatrix-memory-layout=column-major`` or ``-fmatrix-memory-layout=row-major``).
+- New option ``-fdiagnostics-show-inlining-chain=`` added to show inlining chain
+ notes for ``__attribute__((warning))`` and ``__attribute__((error))``
+ diagnostics. When a function with these attributes is called from an inlined
+ context, Clang can now show which functions were inlined to reach the call.
+ Modes: ``none`` (default), ``heuristic`` (uses metadata tracking), ``debug``
+ (uses debug info for accurate source locations).
+
+Lanai Support
+^^^^^^^^^^^^^^
+- The option ``-mcmodel={small,medium,large}`` is supported again.
Deprecated Compiler Flags
-------------------------
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 812b48058d189..97331b1175cc9 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8397,6 +8397,13 @@ pointing to precise locations of the call site in the source.
dontcall(); // No Warning
sizeof(dontcall()); // No Warning
}
+
+When the call occurs through inlined functions, the
+``-fdiagnostics-show-inlining-chain=`` option can be used to show the
+inlining chain that led to the call. This helps identify which call site
+triggered the diagnostic when the attributed function is called from
+multiple locations through inline functions. See ``clang --help`` for
+available modes.
}];
}
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index baf8b093c10e6..59f12a821fa53 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -76,6 +76,8 @@ CODEGENOPT(CallGraphSection, 1, 0, Benign) ///< Emit a call graph section into t
///< object file.
CODEGENOPT(EmitCallSiteInfo, 1, 0, Benign) ///< Emit call site info only in the case of
///< '-g' + 'O>0' level.
+/// Tracking inlining chain in __attribute__((warning)) and __attribute__((error)) diagnostics
+ENUM_CODEGENOPT(InliningChain, InliningChainKind, 2, Inlining_None, Benign)
CODEGENOPT(IndirectTlsSegRefs, 1, 0, Benign) ///< Set when -mno-tls-direct-seg-refs
///< is specified.
CODEGENOPT(DisableTailCalls , 1, 0, Benign) ///< Do not emit tail calls.
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index c60ca507ff917..f34de98126768 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -120,6 +120,14 @@ class CodeGenOptions : public CodeGenOptionsBase {
Embed_Marker // Embed a marker as a placeholder for bitcode.
};
+ /// Inlining chain tracking __attribute__((warning)) or __attribute__((error))
+ /// diagnostics
+ enum InliningChainKind {
+ Inlining_Heuristic, /// Track via srcloc metadata on inline/static calls.
+ Inlining_Debug, /// Track via debug info (DILocation inlinedAt chain).
+ Inlining_None /// No tracking, no inlining notes shown (default).
+ };
+
enum class ExtendVariableLivenessKind {
None,
This,
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index e2b257ceae80d..3a7b7ccc73ab8 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -94,6 +94,12 @@ def err_fe_backend_error_attr :
def warn_fe_backend_warning_attr :
Warning<"call to '%0' declared with 'warning' attribute: %1">, BackendInfo,
InGroup<BackendWarningAttributes>;
+def note_fe_backend_in : Note<"called by function '%0'">, BackendInfo;
+def note_fe_backend_inlined : Note<"inlined by function '%0'">, BackendInfo;
+def warn_fe_inlining_debug_requires_g
+ : Warning<"'-fdiagnostics-show-inlining-chain=debug' requires at least "
+ "'-gline-directives-only'; falling back to 'heuristic' mode">,
+ InGroup<BackendWarningAttributes>;
def warn_toc_unsupported_type : Warning<"-mtocdata option is ignored "
"for %0 because %1">, InGroup<BackendWarningAttributes>;
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 2f57a5b13b917..862aa225bdf4f 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2158,6 +2158,21 @@ defm diagnostics_show_note_include_stack : BoolFOption<"diagnostics-show-note-in
DiagnosticOpts<"ShowNoteIncludeStack">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Display include stacks for diagnostic notes">,
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;
+def fdiagnostics_show_inlining_chain_EQ
+ : Joined<["-"], "fdiagnostics-show-inlining-chain=">,
+ Group<f_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<"Show inlining chain notes for __attribute__((warning/error)) "
+ "diagnostics: "
+ "'none' (default) shows no chain, 'heuristic' uses best-effort "
+ "metadata tracking, "
+ "'debug' uses debug info for accurate locations with increased "
+ "compile-time overhead">,
+ Values<"heuristic,debug,none">,
+ NormalizedValuesScope<"CodeGenOptions">,
+ NormalizedValues<["Inlining_Heuristic", "Inlining_Debug",
+ "Inlining_None"]>,
+ MarshallingInfoEnum<CodeGenOpts<"InliningChain">, "Inlining_None">;
def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group<f_clang_Group>;
def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<f_clang_Group>;
def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index d7bdeb3981cf8..2bc23d9737f5d 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6048,13 +6048,22 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (getDebugInfo() && TargetDecl && TargetDecl->hasAttr<MSAllocatorAttr>())
getDebugInfo()->addHeapAllocSiteMetadata(CI, RetTy->getPointeeType(), Loc);
- // Add metadata if calling an __attribute__((error(""))) or warning fn.
- if (TargetDecl && TargetDecl->hasAttr<ErrorAttr>()) {
- llvm::ConstantInt *Line =
- llvm::ConstantInt::get(Int64Ty, Loc.getRawEncoding());
- llvm::ConstantAsMetadata *MD = llvm::ConstantAsMetadata::get(Line);
- llvm::MDTuple *MDT = llvm::MDNode::get(getLLVMContext(), {MD});
- CI->setMetadata("srcloc", MDT);
+ // Add srcloc metadata for __attribute__((error/warning)) diagnostics.
+ // In heuristic mode, also track inline/static calls for inlining chain.
+ if (TargetDecl) {
+ bool NeedSrcLoc = TargetDecl->hasAttr<ErrorAttr>();
+ if (!NeedSrcLoc && CGM.getCodeGenOpts().getInliningChain() ==
+ CodeGenOptions::Inlining_Heuristic) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(TargetDecl))
+ NeedSrcLoc = FD->isInlined() || FD->isInlineSpecified() ||
+ FD->hasAttr<AlwaysInlineAttr>() ||
+ FD->getStorageClass() == SC_Static;
+ }
+ if (NeedSrcLoc) {
+ auto *Line = llvm::ConstantInt::get(Int64Ty, Loc.getRawEncoding());
+ auto *MD = llvm::ConstantAsMetadata::get(Line);
+ CI->setMetadata("srcloc", llvm::MDNode::get(getLLVMContext(), {MD}));
+ }
}
// 4. Finish the call.
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index a5ef4ac9d361d..e29db962336b4 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -732,6 +732,37 @@ void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
? diag::err_fe_backend_error_attr
: diag::warn_fe_backend_warning_attr)
<< llvm::demangle(D.getFunctionName()) << D.getNote();
+
+ if (CodeGenOpts.getInliningChain() == CodeGenOptions::Inlining_None)
+ return;
+
+ auto EmitNote = [&](SourceLocation Loc, StringRef FuncName, bool IsFirst) {
+ if (!Loc.isValid())
+ Loc = LocCookie;
+ unsigned DiagID =
+ IsFirst ? diag::note_fe_backend_in : diag::note_fe_backend_inlined;
+ Diags.Report(Loc, DiagID) << llvm::demangle(FuncName.str());
+ };
+
+ if (CodeGenOpts.getInliningChain() == CodeGenOptions::Inlining_Debug) {
+ SourceManager &SM = Context->getSourceManager();
+ FileManager &FM = SM.getFileManager();
+ for (const auto &[I, Info] : llvm::enumerate(D.getDebugInlineChain())) {
+ SourceLocation Loc;
+ if (Info.Line > 0)
+ if (auto FE = FM.getOptionalFileRef(Info.Filename))
+ Loc = SM.translateFileLineCol(*FE, Info.Line,
+ Info.Column ? Info.Column : 1);
+ EmitNote(Loc, Info.FuncName, I == 0);
+ }
+ return;
+ }
+
+ for (const auto &[I, Entry] : llvm::enumerate(D.getInliningDecisions())) {
+ SourceLocation Loc =
+ I == 0 ? LocCookie : SourceLocation::getFromRawEncoding(Entry.second);
+ EmitNote(Loc, Entry.first, I == 0);
+ }
}
void BackendConsumer::MisExpectDiagHandler(
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 4ca98600d6e93..10db88a499425 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4281,6 +4281,13 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Opt));
}
+ if (const Arg *A =
+ Args.getLastArg(options::OPT_fdiagnostics_show_inlining_chain_EQ)) {
+ std::string Opt =
+ std::string("-fdiagnostics-show-inlining-chain=") + A->getValue();
+ CmdArgs.push_back(Args.MakeArgString(Opt));
+ }
+
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index ab14661e06e11..177748e48f193 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2253,6 +2253,14 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
+ // Debug mode for inlining chain diagnostics requires at least
+ // -gline-directives-only to track inlining locations via DILocation.
+ if (Opts.getInliningChain() == CodeGenOptions::Inlining_Debug &&
+ Opts.getDebugInfo() < llvm::codegenoptions::DebugDirectivesOnly) {
+ Diags.Report(diag::warn_fe_inlining_debug_requires_g);
+ Opts.setInliningChain(CodeGenOptions::Inlining_Heuristic);
+ }
+
// Parse -fsanitize-recover= arguments.
// FIXME: Report unrecoverable sanitizers incorrectly specified here.
parseSanitizerKinds("-fsanitize-recover=",
diff --git a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
new file mode 100644
index 0000000000000..6c1cee3e9e212
--- /dev/null
+++ b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
@@ -0,0 +1,64 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain=heuristic -S %t/main.c -I%t -o /dev/null 2>&1 | FileCheck %s
+
+// Cross-TU inlining: header functions inlined into source file.
+
+//--- overflow.h
+__attribute__((warning("write overflow")))
+void __write_overflow(void);
+
+__attribute__((error("read overflow")))
+void __read_overflow(void);
+
+static inline void check_write(int size) {
+ if (size > 100)
+ __write_overflow();
+}
+
+static inline void check_read(int size) {
+ if (size > 50)
+ __read_overflow();
+}
+
+static inline void check_both(int size) {
+ check_write(size);
+ check_read(size);
+}
+
+//--- main.c
+#include "overflow.h"
+
+void test_simple_cross_tu(void) {
+ check_write(200);
+}
+// CHECK: warning: call to '__write_overflow' declared with 'warning' attribute: write overflow
+// CHECK: note: called by function 'check_write'
+// CHECK: main.c:{{.*}}: note: inlined by function 'test_simple_cross_tu'
+
+// Nested cross-TU inlining (header -> header -> source).
+static inline void local_wrapper(int x) {
+ check_both(x);
+}
+
+void test_nested_cross_tu(void) {
+ local_wrapper(200);
+}
+// CHECK: warning: call to '__write_overflow' declared with 'warning' attribute: write overflow
+// CHECK: note: called by function 'check_write'
+// CHECK: overflow.h:{{.*}}: note: inlined by function 'check_both'
+// CHECK: main.c:{{.*}}: note: inlined by function 'local_wrapper'
+// CHECK: main.c:{{.*}}: note: inlined by function 'test_nested_cross_tu'
+
+// CHECK: error: call to '__read_overflow' declared with 'error' attribute: read overflow
+// CHECK: note: called by function 'check_read'
+// CHECK: overflow.h:{{.*}}: note: inlined by function 'check_both'
+// CHECK: main.c:{{.*}}: note: inlined by function 'local_wrapper'
+// CHECK: main.c:{{.*}}: note: inlined by function 'test_nested_cross_tu'
+
+void test_error_cross_tu(void) {
+ check_read(100);
+}
+// CHECK: error: call to '__read_overflow' declared with 'error' attribute: read overflow
+// CHECK: note: called by function 'check_read'
+// CHECK: main.c:{{.*}}: note: inlined by function 'test_error_cross_tu'
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
new file mode 100644
index 0000000000000..284b23d5cace2
--- /dev/null
+++ b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=heuristic %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=HEURISTIC
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=debug -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DEBUG
+
+__attribute__((warning("dangerous function")))
+void dangerous(void);
+
+// Non-static, non-inline functions that get inlined at -O2.
+void wrapper(void) {
+ dangerous();
+}
+
+void middle(void) {
+ wrapper();
+}
+
+void caller(void) {
+ middle();
+}
+
+// HEURISTIC: :9:{{.*}}: warning: call to 'dangerous'
+// HEURISTIC: :9:{{.*}}: note: called by function 'wrapper'
+// HEURISTIC: :9:{{.*}}: note: inlined by function 'middle'
+// HEURISTIC: :9:{{.*}}: note: inlined by function 'caller'
+
+// DEBUG: :9:{{.*}}: warning: call to 'dangerous'
+// DEBUG: :9:{{.*}}: note: called by function 'wrapper'
+// DEBUG: :13:{{.*}}: note: inlined by function 'middle'
+// DEBUG: :17:{{.*}}: note: inlined by function 'caller'
diff --git a/clang/test/Frontend/backend-attribute-inlining-modes.c b/clang/test/Frontend/backend-attribute-inlining-modes.c
new file mode 100644
index 0000000000000..ebee1208a17dd
--- /dev/null
+++ b/clang/test/Frontend/backend-attribute-inlining-modes.c
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONE-DEFAULT
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=none %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONE-EXPLICIT
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=heuristic %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=HEURISTIC
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=debug -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DEBUG
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=debug %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=FALLBACK
+
+// Tests all three modes plus fallback behavior when debug info
+// (-gline-directives-only) is missing.
+
+__attribute__((warning("do not call")))
+void bad_func(void);
+
+static inline void level1(void) {
+ bad_func();
+}
+
+static inline void level2(void) {
+ level1();
+}
+
+void entry(void) {
+ level2();
+}
+
+// none (default): warning only, no inlining notes.
+// NONE-DEFAULT: warning: call to 'bad_func'
+// NONE-DEFAULT-NOT: note:
+
+// none (explicit): same as default.
+// NONE-EXPLICIT: warning: call to 'bad_func'
+// NONE-EXPLICIT-NOT: note:
+
+// HEURISTIC: :14:{{.*}}: warning: call to 'bad_func'
+// HEURISTIC: :14:{{.*}}: note: called by function 'level1'
+// HEURISTIC: :18:{{.*}}: note: inlined by function 'level2'
+// HEURISTIC: :22:{{.*}}: note: inlined by function 'entry'
+
+// DEBUG: :14:{{.*}}: warning: call to 'bad_func'
+// DEBUG: :14:{{.*}}: note: called by function 'level1'
+// DEBUG: :18:{{.*}}: note: inlined by function 'level2'
+// DEBUG: :22:{{.*}}: note: inlined by function 'entry'
+
+// FALLBACK: warning: '-fdiagnostics-show-inlining-chain=debug' requires at least '-gline-directives-only'; falling back to 'heuristic' mode
+// FALLBACK: :14:{{.*}}: warning: call to 'bad_func'
+// FALLBACK: :14:{{.*}}: note: called by function 'level1'
+// FALLBACK: :18:{{.*}}: note: inlined by function 'level2'
+// FALLBACK: :22:{{.*}}: note: inlined by function 'entry'
diff --git a/clang/test/Frontend/backend-attribute-inlining.c b/clang/test/Frontend/backend-attribute-inlining.c
new file mode 100644
index 0000000000000..5f91a38ebdc57
--- /dev/null
+++ b/clang/test/Frontend/backend-attribute-inlining.c
@@ -0,0 +1,109 @@
+// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain=heuristic -S %s -o /dev/null 2>&1 | FileCheck %s
+
+// Single-level inlining with warning attribute.
+__attribute__((warning("do not call directly")))
+void __warn_single(void);
+
+static inline void warn_wrapper(void) {
+ __warn_single();
+}
+
+void test_single_level(void) {
+ warn_wrapper();
+}
+// CHECK: warning: call to '__warn_single' declared with 'warning' attribute: do not call directly
+// CHECK: note: called by function 'warn_wrapper'
+// CHECK: :12:{{.*}}: note: inlined by function 'test_single_level'
+
+// Error attribute with inlining.
+__attribute__((error("never call this")))
+void __error_func(void);
+
+static inline void error_wrapper(void) {
+ __error_func();
+}
+
+void test_error_inlined(void) {
+ error_wrapper();
+}
+// CHECK: error: call to '__error_func' declared with 'error' attribute: never call this
+// CHECK: note: called by function 'error_wrapper'
+// CHECK: :27:{{.*}}: note: inlined by function 'test_error_inlined'
+
+// Deep nesting (5 levels).
+__attribute__((warning("deep call")))
+void __warn_deep(void);
+
+static inline void deep1(void) { __warn_deep(); }
+static inline void deep2(void) { deep1(); }
+static inline void deep3(void) { deep2(); }
+static inline void deep4(void) { deep3(); }
+static inline void deep5(void) { deep4(); }
+
+void test_deep_nesting(void) {
+ deep5();
+}
+// CHECK: warning: call to '__warn_deep' declared with 'warning' attribute: deep call
+// CHECK: note: called by function 'deep1'
+// CHECK: :38:{{.*}}: note: inlined by function 'deep2'
+// CHECK: :39:{{.*}}: note: inlined by function 'deep3'
+// CHECK: :40:{{.*}}: note: inlined by function 'deep4'
+// CHECK: :41:{{.*}}: note: inlined by function 'deep5'
+// CHECK: :44:{{.*}}: note: inlined by function 'test_deep_nesting'
+
+// Multiple call sites produce distinct diagnostics.
+__attribute__((warning("deprecated")))
+void __warn_multi(void);
+
+static inline void multi_wrapper(void) {
+ __warn_multi();
+}
+
+void call_site_a(void) { multi_wrapper(); }
+void call_site_b(void) { multi_wrapper(); }
+void call_site_c(void) { multi_wrapper(); }
+
+// CHECK: warning: call to '__warn_multi' declared with 'warning' attribute: deprecated
+// CHECK: note: called by function 'multi_wrapper'
+// CHECK: :62:{{.*}}: note: inlined by function 'call_site_a'
+
+// CHECK: warning: call to '__warn_multi' declared with 'warning' attribute: deprecated
+// CHECK: note: called by function 'multi_wrapper'
+// CHECK: :63:{{.*}}: note: inlined by function 'call_site_b'
+
+// CHECK: warning: call to '__warn_multi' declared with 'warning' attribute: deprecated
+// CHECK: note: called by function 'multi_wrapper'
+// CHECK: :64:{{.*}}: note: inlined by function 'call_site_c'
+
+// Different nesting depths from same inner function.
+__attribute__((warning("mixed depth")))
+void __warn_mixed(void);
+
+static inline void mixed_inner(void) { __warn_mixed(); }
+static inline void mixed_middle(void) { mixed_inner(); }
+
+void shallow(void) { mixed_inner(); }
+void deep(void) { mixed_middle(); }
+
+// CHECK: warning: call to '__warn_mixed' declared with 'warning' attribute: mixed depth
+// CHECK: note: called by function 'mixed_inner'
+// CHECK: :85:{{.*}}: note: inlined by function 'shallow'
+
+// CHECK: warning: call to '__warn_mixed' declared with 'warning' attribute: mixed depth
+// CHECK: note: called by function 'mixed_inner'
+// CHECK: :83:{{.*}}: note: inlined by function 'mixed_middle'
+// CHECK: :86:{{.*}}: note: inlined by function 'deep'
+
+// Incidental inlining (function not marked inline/static).
+// The "inlined by" note has no location since heuristic mode doesn't track it.
+__attribute__((warning("incidental")))
+void __warn_incidental(void);
+
+void not_marked_inline(void) { __warn_incidental(); }
+
+void test_incidental(void) { not_marked_inline(); }
+
+// CHECK: warning: call to '__warn_incidental' declared with 'warning' attribute: incidental
+// CHECK: note: called by function 'not_marked_inline'
+// CHECK: note: inlined by function 'test_incidental'
+// CHECK-NOT: :{{.*}}: note: inlined by function 'test_incidental'
diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 8f6fb4da0c839..0daaa462ba715 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -1192,19 +1192,41 @@ class LLVM_ABI DiagnosticInfoSrcMgr : public DiagnosticInfo {
LLVM_ABI void diagnoseDontCall(const CallInst &CI);
+/// Inlining location extracted from debug info.
+struct DebugInlineInfo {
+ StringRef FuncName;
+ StringRef Filename;
+ unsigned Line;
+ unsigned Column;
+};
+
class LLVM_ABI DiagnosticInfoDontCall : public DiagnosticInfo {
StringRef CalleeName;
StringRef Note;
uint64_t LocCookie;
+ MDNode *InlinedFromMD = nullptr;
+ SmallVector<DebugInlineInfo, 4> DebugInlineChain;
public:
DiagnosticInfoDontCall(StringRef CalleeName, StringRef Note,
- DiagnosticSeverity DS, uint64_t LocCookie)
+ DiagnosticSeverity DS, uint64_t LocCookie,
+ MDNode *InlinedFromMD = nullptr)
: DiagnosticInfo(DK_DontCall, DS), CalleeName(CalleeName), Note(Note),
- LocCookie(LocCookie) {}
+ LocCookie(LocCookie), InlinedFromMD(InlinedFromMD) {}
+
StringRef getFunctionName() const { return CalleeName; }
StringRef getNote() const { return Note; }
uint64_t getLocCookie() const { return LocCookie; }
+ MDNode *getInlinedFromMD() const { return InlinedFromMD; }
+ SmallVector<std::pair<StringRef, uint64_t>> getInliningDecisions() const;
+
+ void setDebugInlineChain(SmallVector<DebugInlineInfo, 4> &&Chain) {
+ DebugInlineChain = std::move(Chain);
+ }
+ ArrayRef<DebugInlineInfo> getDebugInlineChain() const {
+ return DebugInlineChain;
+ }
+
void print(DiagnosticPrinter &DP) const override;
static bool classof(const DiagnosticInfo *DI) {
return DI->getKind() == DK_DontCall;
diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp
index e48016fc4165f..73bf0eca0b964 100644
--- a/llvm/lib/IR/DiagnosticInfo.cpp
+++ b/llvm/lib/IR/DiagnosticInfo.cpp
@@ -484,8 +484,27 @@ void llvm::diagnoseDontCall(const CallInst &CI) {
if (MDNode *MD = CI.getMetadata("srcloc"))
LocCookie =
mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
+ MDNode *InlinedFromMD = CI.getMetadata("inlined.from");
DiagnosticInfoDontCall D(F->getName(), A.getValueAsString(), Sev,
- LocCookie);
+ LocCookie, InlinedFromMD);
+
+ if (const DebugLoc &DL = CI.getDebugLoc()) {
+ SmallVector<DebugInlineInfo, 4> DebugChain;
+ auto AddLocation = [&](const DILocation *Loc) {
+ if (auto *Scope = Loc->getScope())
+ if (auto *SP = Scope->getSubprogram())
+ DebugChain.push_back({SP->getName(), Loc->getFilename(),
+ Loc->getLine(), Loc->getColumn()});
+ };
+ if (const DILocation *Loc = DL.get()) {
+ AddLocation(Loc);
+ for (const DILocation *InlinedAt = Loc->getInlinedAt(); InlinedAt;
+ InlinedAt = InlinedAt->getInlinedAt())
+ AddLocation(InlinedAt);
+ }
+ D.setDebugInlineChain(std::move(DebugChain));
+ }
+
F->getContext().diagnose(D);
}
}
@@ -500,3 +519,20 @@ void DiagnosticInfoDontCall::print(DiagnosticPrinter &DP) const {
if (!getNote().empty())
DP << ": " << getNote();
}
+
+SmallVector<std::pair<StringRef, uint64_t>>
+DiagnosticInfoDontCall::getInliningDecisions() const {
+ SmallVector<std::pair<StringRef, uint64_t>> Chain;
+ if (!InlinedFromMD)
+ return Chain;
+
+ for (unsigned I = 0, E = InlinedFromMD->getNumOperands(); I + 1 < E; I += 2) {
+ auto *NameMD = dyn_cast<MDString>(InlinedFromMD->getOperand(I));
+ auto *LocMD =
+ mdconst::dyn_extract<ConstantInt>(InlinedFromMD->getOperand(I + 1));
+ if (NameMD && !NameMD->getString().empty())
+ Chain.emplace_back(NameMD->getString(),
+ LocMD ? LocMD->getZExtValue() : 0);
+ }
+ return Chain;
+}
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index aa902f687d8aa..2573c0b2d63a1 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -974,6 +974,46 @@ static void PropagateCallSiteMetadata(CallBase &CB, Function::iterator FStart,
}
}
+/// Track inlining chain via inlined.from metadata for dontcall diagnostics.
+static void PropagateInlinedFromMetadata(CallBase &CB, StringRef CalledFuncName,
+ StringRef CallerFuncName,
+ Function::iterator FStart,
+ Function::iterator FEnd) {
+ LLVMContext &Ctx = CB.getContext();
+ uint64_t InlineSiteLoc = 0;
+ if (auto *MD = CB.getMetadata("srcloc"))
+ if (auto *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)))
+ InlineSiteLoc = CI->getZExtValue();
+
+ auto *I64Ty = Type::getInt64Ty(Ctx);
+ auto MakeMDInt = [&](uint64_t V) {
+ return ConstantAsMetadata::get(ConstantInt::get(I64Ty, V));
+ };
+
+ for (BasicBlock &BB : make_range(FStart, FEnd)) {
+ for (Instruction &I : BB) {
+ auto *CI = dyn_cast<CallInst>(&I);
+ if (!CI || !CI->getMetadata("srcloc"))
+ continue;
+ auto *Callee = CI->getCalledFunction();
+ if (!Callee || (!Callee->hasFnAttribute("dontcall-error") &&
+ !Callee->hasFnAttribute("dontcall-warn")))
+ continue;
+
+ SmallVector<Metadata *, 8> Ops;
+ if (MDNode *Existing = CI->getMetadata("inlined.from"))
+ append_range(Ops, Existing->operands());
+ else {
+ Ops.push_back(MDString::get(Ctx, CalledFuncName));
+ Ops.push_back(MakeMDInt(0));
+ }
+ Ops.push_back(MDString::get(Ctx, CallerFuncName));
+ Ops.push_back(MakeMDInt(InlineSiteLoc));
+ CI->setMetadata("inlined.from", MDNode::get(Ctx, Ops));
+ }
+ }
+}
+
/// Bundle operands of the inlined function must be added to inlined call sites.
static void PropagateOperandBundles(Function::iterator InlinedBB,
Instruction *CallSiteEHPad) {
@@ -2839,6 +2879,10 @@ void llvm::InlineFunctionImpl(CallBase &CB, InlineFunctionInfo &IFI,
}
}
+ // Propagate inlined.from metadata for dontcall diagnostics.
+ PropagateInlinedFromMetadata(CB, CalledFunc->getName(), Caller->getName(),
+ FirstNewBlock, Caller->end());
+
// Register any cloned assumptions.
if (IFI.GetAssumptionCache)
for (BasicBlock &NewBlock :
>From e0bd8ec5b2ec10578445515abc9c443eb24008e0 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Thu, 8 Jan 2026 10:27:15 -0800
Subject: [PATCH 2/9] use scoped enum, binary flag, better docs
based on review:
1) use scoped enum
2) switch over to a binary flag instead of a ternary one.
3) improve docs and help text
4) add note regarding -gline-directives-only
5) use modern attribute spellings
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
clang/docs/ReleaseNotes.rst | 13 +++--
clang/include/clang/Basic/AttrDocs.td | 11 +++-
clang/include/clang/Basic/CodeGenOptions.def | 4 +-
clang/include/clang/Basic/CodeGenOptions.h | 8 ---
.../clang/Basic/DiagnosticFrontendKinds.td | 8 +--
clang/include/clang/Options/Options.td | 22 +++----
clang/lib/CodeGen/CGCall.cpp | 11 ++--
clang/lib/CodeGen/CodeGenAction.cpp | 16 +++++-
clang/lib/Driver/ToolChains/Clang.cpp | 10 ++--
clang/lib/Frontend/CompilerInvocation.cpp | 8 ---
.../backend-attribute-inlining-cross-tu.c | 9 ++-
...nd-attribute-inlining-debug-vs-heuristic.c | 31 ++++++----
.../backend-attribute-inlining-modes.c | 57 +++++++++----------
.../Frontend/backend-attribute-inlining.c | 17 +++---
14 files changed, 115 insertions(+), 110 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2723ff61ef022..cde8a437e8276 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -95,12 +95,13 @@ New Compiler Flags
- New options for enabling allocation token instrumentation: ``-fsanitize=alloc-token``, ``-falloc-token-max=``, ``-fsanitize-alloc-token-fast-abi``, ``-fsanitize-alloc-token-extended``.
- The ``-resource-dir`` option is now displayed in the list of options shown by ``--help``.
- New option ``-fmatrix-memory-layout`` added to control the memory layout of Clang matrix types. (e.g. ``-fmatrix-memory-layout=column-major`` or ``-fmatrix-memory-layout=row-major``).
-- New option ``-fdiagnostics-show-inlining-chain=`` added to show inlining chain
- notes for ``__attribute__((warning))`` and ``__attribute__((error))``
- diagnostics. When a function with these attributes is called from an inlined
- context, Clang can now show which functions were inlined to reach the call.
- Modes: ``none`` (default), ``heuristic`` (uses metadata tracking), ``debug``
- (uses debug info for accurate source locations).
+- New option ``-fdiagnostics-show-inlining-chain`` added to show inlining chain
+ notes for ``[[gnu::warning]]`` and ``[[gnu::error]]`` diagnostics. When a
+ function with these attributes is called from an inlined context, Clang can
+ now show which functions were inlined to reach the call. When debug info is
+ available (``-gline-directives-only`` or higher), accurate source locations
+ are used; otherwise, a heuristic fallback is used with a note suggesting
+ how to enable debug info for better accuracy.
Lanai Support
^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 97331b1175cc9..f9c6d6ccd606f 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8399,11 +8399,16 @@ pointing to precise locations of the call site in the source.
}
When the call occurs through inlined functions, the
-``-fdiagnostics-show-inlining-chain=`` option can be used to show the
+``-fdiagnostics-show-inlining-chain`` option can be used to show the
inlining chain that led to the call. This helps identify which call site
triggered the diagnostic when the attributed function is called from
-multiple locations through inline functions. See ``clang --help`` for
-available modes.
+multiple locations through inline functions.
+
+When enabled, this option automatically uses debug info for accurate source
+locations if available (requires at least ``-gline-directives-only``), or
+falls back to a heuristic based on metadata tracking. When falling back, a
+note is emitted suggesting ``-gline-directives-only`` for more accurate
+locations.
}];
}
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 59f12a821fa53..cd0675c6e35a0 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -76,8 +76,8 @@ CODEGENOPT(CallGraphSection, 1, 0, Benign) ///< Emit a call graph section into t
///< object file.
CODEGENOPT(EmitCallSiteInfo, 1, 0, Benign) ///< Emit call site info only in the case of
///< '-g' + 'O>0' level.
-/// Tracking inlining chain in __attribute__((warning)) and __attribute__((error)) diagnostics
-ENUM_CODEGENOPT(InliningChain, InliningChainKind, 2, Inlining_None, Benign)
+/// Show inlining chain notes for [[gnu::warning/error]] diagnostics.
+CODEGENOPT(ShowInliningChain, 1, 0, Benign)
CODEGENOPT(IndirectTlsSegRefs, 1, 0, Benign) ///< Set when -mno-tls-direct-seg-refs
///< is specified.
CODEGENOPT(DisableTailCalls , 1, 0, Benign) ///< Do not emit tail calls.
diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h
index f34de98126768..c60ca507ff917 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -120,14 +120,6 @@ class CodeGenOptions : public CodeGenOptionsBase {
Embed_Marker // Embed a marker as a placeholder for bitcode.
};
- /// Inlining chain tracking __attribute__((warning)) or __attribute__((error))
- /// diagnostics
- enum InliningChainKind {
- Inlining_Heuristic, /// Track via srcloc metadata on inline/static calls.
- Inlining_Debug, /// Track via debug info (DILocation inlinedAt chain).
- Inlining_None /// No tracking, no inlining notes shown (default).
- };
-
enum class ExtendVariableLivenessKind {
None,
This,
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 3a7b7ccc73ab8..ff924b3ace3dd 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -96,10 +96,10 @@ def warn_fe_backend_warning_attr :
InGroup<BackendWarningAttributes>;
def note_fe_backend_in : Note<"called by function '%0'">, BackendInfo;
def note_fe_backend_inlined : Note<"inlined by function '%0'">, BackendInfo;
-def warn_fe_inlining_debug_requires_g
- : Warning<"'-fdiagnostics-show-inlining-chain=debug' requires at least "
- "'-gline-directives-only'; falling back to 'heuristic' mode">,
- InGroup<BackendWarningAttributes>;
+def note_fe_backend_inlining_debug_info
+ : Note<"use '-gline-directives-only' or higher for more accurate "
+ "inlining chain locations">,
+ BackendInfo;
def warn_toc_unsupported_type : Warning<"-mtocdata option is ignored "
"for %0 because %1">, InGroup<BackendWarningAttributes>;
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 862aa225bdf4f..70b607c601a18 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2158,21 +2158,13 @@ defm diagnostics_show_note_include_stack : BoolFOption<"diagnostics-show-note-in
DiagnosticOpts<"ShowNoteIncludeStack">, DefaultFalse,
PosFlag<SetTrue, [], [ClangOption], "Display include stacks for diagnostic notes">,
NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;
-def fdiagnostics_show_inlining_chain_EQ
- : Joined<["-"], "fdiagnostics-show-inlining-chain=">,
- Group<f_Group>,
- Visibility<[ClangOption, CC1Option]>,
- HelpText<"Show inlining chain notes for __attribute__((warning/error)) "
- "diagnostics: "
- "'none' (default) shows no chain, 'heuristic' uses best-effort "
- "metadata tracking, "
- "'debug' uses debug info for accurate locations with increased "
- "compile-time overhead">,
- Values<"heuristic,debug,none">,
- NormalizedValuesScope<"CodeGenOptions">,
- NormalizedValues<["Inlining_Heuristic", "Inlining_Debug",
- "Inlining_None"]>,
- MarshallingInfoEnum<CodeGenOpts<"InliningChain">, "Inlining_None">;
+defm diagnostics_show_inlining_chain
+ : BoolFOption<"diagnostics-show-inlining-chain",
+ CodeGenOpts<"ShowInliningChain">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption, CC1Option],
+ "Show inlining chain notes for "
+ "[[gnu::warning/error]] diagnostics">,
+ NegFlag<SetFalse, [], [ClangOption, CC1Option]>>;
def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group<f_clang_Group>;
def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<f_clang_Group>;
def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 2bc23d9737f5d..76e504a5aa47b 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6048,16 +6048,17 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (getDebugInfo() && TargetDecl && TargetDecl->hasAttr<MSAllocatorAttr>())
getDebugInfo()->addHeapAllocSiteMetadata(CI, RetTy->getPointeeType(), Loc);
- // Add srcloc metadata for __attribute__((error/warning)) diagnostics.
- // In heuristic mode, also track inline/static calls for inlining chain.
+ // Add srcloc metadata for [[gnu::error/warning]] diagnostics.
+ // When ShowInliningChain is enabled, also track inline/static calls for the
+ // heuristic fallback when debug info is not available.
if (TargetDecl) {
bool NeedSrcLoc = TargetDecl->hasAttr<ErrorAttr>();
- if (!NeedSrcLoc && CGM.getCodeGenOpts().getInliningChain() ==
- CodeGenOptions::Inlining_Heuristic) {
+ if (!NeedSrcLoc && CGM.getCodeGenOpts().ShowInliningChain) {
if (const auto *FD = dyn_cast<FunctionDecl>(TargetDecl))
NeedSrcLoc = FD->isInlined() || FD->isInlineSpecified() ||
FD->hasAttr<AlwaysInlineAttr>() ||
- FD->getStorageClass() == SC_Static;
+ FD->getStorageClass() == SC_Static ||
+ FD->isInAnonymousNamespace();
}
if (NeedSrcLoc) {
auto *Line = llvm::ConstantInt::get(Int64Ty, Loc.getRawEncoding());
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index e29db962336b4..3a46acf0e17f0 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -733,7 +733,7 @@ void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
: diag::warn_fe_backend_warning_attr)
<< llvm::demangle(D.getFunctionName()) << D.getNote();
- if (CodeGenOpts.getInliningChain() == CodeGenOptions::Inlining_None)
+ if (!CodeGenOpts.ShowInliningChain)
return;
auto EmitNote = [&](SourceLocation Loc, StringRef FuncName, bool IsFirst) {
@@ -744,7 +744,8 @@ void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
Diags.Report(Loc, DiagID) << llvm::demangle(FuncName.str());
};
- if (CodeGenOpts.getInliningChain() == CodeGenOptions::Inlining_Debug) {
+ // Try debug info first for accurate source locations.
+ if (!D.getDebugInlineChain().empty()) {
SourceManager &SM = Context->getSourceManager();
FileManager &FM = SM.getFileManager();
for (const auto &[I, Info] : llvm::enumerate(D.getDebugInlineChain())) {
@@ -758,11 +759,20 @@ void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
return;
}
- for (const auto &[I, Entry] : llvm::enumerate(D.getInliningDecisions())) {
+ // Fall back to heuristic (srcloc metadata) when debug info is unavailable.
+ auto InliningDecisions = D.getInliningDecisions();
+ if (InliningDecisions.empty())
+ return;
+
+ for (const auto &[I, Entry] : llvm::enumerate(InliningDecisions)) {
SourceLocation Loc =
I == 0 ? LocCookie : SourceLocation::getFromRawEncoding(Entry.second);
EmitNote(Loc, Entry.first, I == 0);
}
+
+ // Suggest enabling debug info (at least -gline-directives-only) for more
+ // accurate locations.
+ Diags.Report(LocCookie, diag::note_fe_backend_inlining_debug_info);
}
void BackendConsumer::MisExpectDiagHandler(
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 10db88a499425..fc9cebbdbe21b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4282,10 +4282,12 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
}
if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_show_inlining_chain_EQ)) {
- std::string Opt =
- std::string("-fdiagnostics-show-inlining-chain=") + A->getValue();
- CmdArgs.push_back(Args.MakeArgString(Opt));
+ Args.getLastArg(options::OPT_fdiagnostics_show_inlining_chain,
+ options::OPT_fno_diagnostics_show_inlining_chain)) {
+ if (A->getOption().matches(options::OPT_fdiagnostics_show_inlining_chain))
+ CmdArgs.push_back("-fdiagnostics-show-inlining-chain");
+ else
+ CmdArgs.push_back("-fno-diagnostics-show-inlining-chain");
}
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 177748e48f193..ab14661e06e11 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2253,14 +2253,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.getDebugInfo() == llvm::codegenoptions::NoDebugInfo)
Opts.setDebugInfo(llvm::codegenoptions::LocTrackingOnly);
- // Debug mode for inlining chain diagnostics requires at least
- // -gline-directives-only to track inlining locations via DILocation.
- if (Opts.getInliningChain() == CodeGenOptions::Inlining_Debug &&
- Opts.getDebugInfo() < llvm::codegenoptions::DebugDirectivesOnly) {
- Diags.Report(diag::warn_fe_inlining_debug_requires_g);
- Opts.setInliningChain(CodeGenOptions::Inlining_Heuristic);
- }
-
// Parse -fsanitize-recover= arguments.
// FIXME: Report unrecoverable sanitizers incorrectly specified here.
parseSanitizerKinds("-fsanitize-recover=",
diff --git a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
index 6c1cee3e9e212..cf259cc77f232 100644
--- a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
+++ b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
@@ -1,14 +1,14 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
-// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain=heuristic -S %t/main.c -I%t -o /dev/null 2>&1 | FileCheck %s
+// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain -S %t/main.c -I%t -o /dev/null 2>&1 | FileCheck %s
// Cross-TU inlining: header functions inlined into source file.
//--- overflow.h
-__attribute__((warning("write overflow")))
+[[gnu::warning("write overflow")]]
void __write_overflow(void);
-__attribute__((error("read overflow")))
+[[gnu::error("read overflow")]]
void __read_overflow(void);
static inline void check_write(int size) {
@@ -62,3 +62,6 @@ void test_error_cross_tu(void) {
// CHECK: error: call to '__read_overflow' declared with 'error' attribute: read overflow
// CHECK: note: called by function 'check_read'
// CHECK: main.c:{{.*}}: note: inlined by function 'test_error_cross_tu'
+
+// Fallback note should appear (no debug info).
+// CHECK: note: use '-gline-directives-only' or higher for more accurate inlining chain locations
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
index 284b23d5cace2..4760b95f49c39 100644
--- a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
+++ b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
@@ -1,7 +1,14 @@
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=heuristic %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=HEURISTIC
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=debug -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DEBUG
+// 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
-__attribute__((warning("dangerous function")))
+// 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(void);
// Non-static, non-inline functions that get inlined at -O2.
@@ -17,12 +24,14 @@ void caller(void) {
middle();
}
-// HEURISTIC: :9:{{.*}}: warning: call to 'dangerous'
-// HEURISTIC: :9:{{.*}}: note: called by function 'wrapper'
-// HEURISTIC: :9:{{.*}}: note: inlined by function 'middle'
-// HEURISTIC: :9:{{.*}}: note: inlined by function 'caller'
+// 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' or higher for more accurate inlining chain locations
-// DEBUG: :9:{{.*}}: warning: call to 'dangerous'
-// DEBUG: :9:{{.*}}: note: called by function 'wrapper'
-// DEBUG: :13:{{.*}}: note: inlined by function 'middle'
-// DEBUG: :17:{{.*}}: note: inlined by function 'caller'
+// 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'
diff --git a/clang/test/Frontend/backend-attribute-inlining-modes.c b/clang/test/Frontend/backend-attribute-inlining-modes.c
index ebee1208a17dd..9768845458754 100644
--- a/clang/test/Frontend/backend-attribute-inlining-modes.c
+++ b/clang/test/Frontend/backend-attribute-inlining-modes.c
@@ -1,13 +1,13 @@
-// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONE-DEFAULT
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=none %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=NONE-EXPLICIT
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=heuristic %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=HEURISTIC
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=debug -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DEBUG
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain=debug %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=FALLBACK
+// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DISABLED
+// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ENABLED-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=ENABLED-DEBUG
-// Tests all three modes plus fallback behavior when debug info
-// (-gline-directives-only) is missing.
+// Test -fdiagnostics-show-inlining-chain behavior:
+// - Disabled (default): warning only, no inlining notes.
+// - Enabled without debug info: heuristic fallback + suggestion note.
+// - Enabled with debug info: accurate locations from DILocation.
-__attribute__((warning("do not call")))
+[[gnu::warning("do not call")]]
void bad_func(void);
static inline void level1(void) {
@@ -22,26 +22,21 @@ void entry(void) {
level2();
}
-// none (default): warning only, no inlining notes.
-// NONE-DEFAULT: warning: call to 'bad_func'
-// NONE-DEFAULT-NOT: note:
-
-// none (explicit): same as default.
-// NONE-EXPLICIT: warning: call to 'bad_func'
-// NONE-EXPLICIT-NOT: note:
-
-// HEURISTIC: :14:{{.*}}: warning: call to 'bad_func'
-// HEURISTIC: :14:{{.*}}: note: called by function 'level1'
-// HEURISTIC: :18:{{.*}}: note: inlined by function 'level2'
-// HEURISTIC: :22:{{.*}}: note: inlined by function 'entry'
-
-// DEBUG: :14:{{.*}}: warning: call to 'bad_func'
-// DEBUG: :14:{{.*}}: note: called by function 'level1'
-// DEBUG: :18:{{.*}}: note: inlined by function 'level2'
-// DEBUG: :22:{{.*}}: note: inlined by function 'entry'
-
-// FALLBACK: warning: '-fdiagnostics-show-inlining-chain=debug' requires at least '-gline-directives-only'; falling back to 'heuristic' mode
-// FALLBACK: :14:{{.*}}: warning: call to 'bad_func'
-// FALLBACK: :14:{{.*}}: note: called by function 'level1'
-// FALLBACK: :18:{{.*}}: note: inlined by function 'level2'
-// FALLBACK: :22:{{.*}}: note: inlined by function 'entry'
+// Disabled (default): warning only, no inlining notes.
+// DISABLED: warning: call to 'bad_func'
+// DISABLED-NOT: note:
+
+// Enabled without debug info: heuristic fallback.
+// All notes point to original call site (:14).
+// ENABLED-HEURISTIC: :14:{{.*}}: warning: call to 'bad_func'
+// ENABLED-HEURISTIC: :14:{{.*}}: note: called by function 'level1'
+// ENABLED-HEURISTIC: :18:{{.*}}: note: inlined by function 'level2'
+// ENABLED-HEURISTIC: :22:{{.*}}: note: inlined by function 'entry'
+// ENABLED-HEURISTIC: note: use '-gline-directives-only' or higher for more accurate inlining chain locations
+
+// Enabled with debug info: accurate locations.
+// ENABLED-DEBUG: :14:{{.*}}: warning: call to 'bad_func'
+// ENABLED-DEBUG: :14:{{.*}}: note: called by function 'level1'
+// ENABLED-DEBUG: :18:{{.*}}: note: inlined by function 'level2'
+// ENABLED-DEBUG: :22:{{.*}}: note: inlined by function 'entry'
+// ENABLED-DEBUG-NOT: note: use '-gline-directives-only'
diff --git a/clang/test/Frontend/backend-attribute-inlining.c b/clang/test/Frontend/backend-attribute-inlining.c
index 5f91a38ebdc57..45a8e601e805f 100644
--- a/clang/test/Frontend/backend-attribute-inlining.c
+++ b/clang/test/Frontend/backend-attribute-inlining.c
@@ -1,7 +1,7 @@
-// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain=heuristic -S %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain -S %s -o /dev/null 2>&1 | FileCheck %s
// Single-level inlining with warning attribute.
-__attribute__((warning("do not call directly")))
+[[gnu::warning("do not call directly")]]
void __warn_single(void);
static inline void warn_wrapper(void) {
@@ -16,7 +16,7 @@ void test_single_level(void) {
// CHECK: :12:{{.*}}: note: inlined by function 'test_single_level'
// Error attribute with inlining.
-__attribute__((error("never call this")))
+[[gnu::error("never call this")]]
void __error_func(void);
static inline void error_wrapper(void) {
@@ -31,7 +31,7 @@ void test_error_inlined(void) {
// CHECK: :27:{{.*}}: note: inlined by function 'test_error_inlined'
// Deep nesting (5 levels).
-__attribute__((warning("deep call")))
+[[gnu::warning("deep call")]]
void __warn_deep(void);
static inline void deep1(void) { __warn_deep(); }
@@ -52,7 +52,7 @@ void test_deep_nesting(void) {
// CHECK: :44:{{.*}}: note: inlined by function 'test_deep_nesting'
// Multiple call sites produce distinct diagnostics.
-__attribute__((warning("deprecated")))
+[[gnu::warning("deprecated")]]
void __warn_multi(void);
static inline void multi_wrapper(void) {
@@ -76,7 +76,7 @@ void call_site_c(void) { multi_wrapper(); }
// CHECK: :64:{{.*}}: note: inlined by function 'call_site_c'
// Different nesting depths from same inner function.
-__attribute__((warning("mixed depth")))
+[[gnu::warning("mixed depth")]]
void __warn_mixed(void);
static inline void mixed_inner(void) { __warn_mixed(); }
@@ -96,7 +96,7 @@ void deep(void) { mixed_middle(); }
// Incidental inlining (function not marked inline/static).
// The "inlined by" note has no location since heuristic mode doesn't track it.
-__attribute__((warning("incidental")))
+[[gnu::warning("incidental")]]
void __warn_incidental(void);
void not_marked_inline(void) { __warn_incidental(); }
@@ -107,3 +107,6 @@ void test_incidental(void) { not_marked_inline(); }
// CHECK: note: called by function 'not_marked_inline'
// CHECK: note: inlined by function 'test_incidental'
// CHECK-NOT: :{{.*}}: note: inlined by function 'test_incidental'
+
+// Fallback note should appear (no debug info).
+// CHECK: note: use '-gline-directives-only' or higher for more accurate inlining chain locations
>From 522ce70406ad542e2aeb606f0a780447c698e2c2 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Thu, 8 Jan 2026 15:01:22 -0800
Subject: [PATCH 3/9] mention -g1 in docs, better explain heuristic intentions
---
clang/docs/ReleaseNotes.rst | 6 +++---
clang/lib/CodeGen/CGCall.cpp | 8 +++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index cde8a437e8276..11df59b9e65b2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -99,9 +99,9 @@ New Compiler Flags
notes for ``[[gnu::warning]]`` and ``[[gnu::error]]`` diagnostics. When a
function with these attributes is called from an inlined context, Clang can
now show which functions were inlined to reach the call. When debug info is
- available (``-gline-directives-only`` or higher), accurate source locations
- are used; otherwise, a heuristic fallback is used with a note suggesting
- how to enable debug info for better accuracy.
+ available (``-gline-directives-only`` (implicitly enabled at ``-g1``) or
+ higher), accurate source locations are used; otherwise, a heuristic fallback
+ is used with a note suggesting how to enable debug info for better accuracy.
Lanai Support
^^^^^^^^^^^^^^
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 76e504a5aa47b..8c9bfa7c103f2 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6048,9 +6048,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (getDebugInfo() && TargetDecl && TargetDecl->hasAttr<MSAllocatorAttr>())
getDebugInfo()->addHeapAllocSiteMetadata(CI, RetTy->getPointeeType(), Loc);
- // Add srcloc metadata for [[gnu::error/warning]] diagnostics.
- // When ShowInliningChain is enabled, also track inline/static calls for the
- // heuristic fallback when debug info is not available.
+ // Add srcloc metadata for [[gnu::error/warning]] diagnostics. When
+ // ShowInliningChain is enabled, also track inline/static calls for the
+ // heuristic fallback when debug info is not available. This heuristic is
+ // conservative and best-effort since static or inline-annotated functions
+ // are still not guaranteed to be inlined.
if (TargetDecl) {
bool NeedSrcLoc = TargetDecl->hasAttr<ErrorAttr>();
if (!NeedSrcLoc && CGM.getCodeGenOpts().ShowInliningChain) {
>From 880c8d48e4ed4838e4f36d79c78c734b189f36ab Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Thu, 8 Jan 2026 16:41:11 -0800
Subject: [PATCH 4/9] drop isInlineSpecified, test anon namespace, add more -g1
notes
change clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c to a
c++ file so I can test anonymous namespaces.
add more -g1 notes in AttrDocs and diagnostic note.
---
clang/include/clang/Basic/AttrDocs.td | 8 +--
.../clang/Basic/DiagnosticFrontendKinds.td | 4 +-
clang/lib/CodeGen/CGCall.cpp | 3 +-
.../backend-attribute-inlining-cross-tu.c | 2 +-
...nd-attribute-inlining-debug-vs-heuristic.c | 37 ----------
...-attribute-inlining-debug-vs-heuristic.cpp | 68 +++++++++++++++++++
.../backend-attribute-inlining-modes.c | 2 +-
.../Frontend/backend-attribute-inlining.c | 2 +-
8 files changed, 78 insertions(+), 48 deletions(-)
delete mode 100644 clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
create mode 100644 clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index f9c6d6ccd606f..6ea1a007d58cf 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8405,10 +8405,10 @@ triggered the diagnostic when the attributed function is called from
multiple locations through inline functions.
When enabled, this option automatically uses debug info for accurate source
-locations if available (requires at least ``-gline-directives-only``), or
-falls back to a heuristic based on metadata tracking. When falling back, a
-note is emitted suggesting ``-gline-directives-only`` for more accurate
-locations.
+locations if available (``-gline-directives-only`` (implicitly enabled at
+``-g1``) or higher), or falls back to a heuristic based on metadata tracking.
+When falling back, a note is emitted suggesting ``-gline-directives-only`` for
+more accurate locations.
}];
}
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index ff924b3ace3dd..8180766d63464 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -97,8 +97,8 @@ def warn_fe_backend_warning_attr :
def note_fe_backend_in : Note<"called by function '%0'">, BackendInfo;
def note_fe_backend_inlined : Note<"inlined by function '%0'">, BackendInfo;
def note_fe_backend_inlining_debug_info
- : Note<"use '-gline-directives-only' or higher for more accurate "
- "inlining chain locations">,
+ : Note<"use '-gline-directives-only' (implied by '-g1') or higher for "
+ "more accurate inlining chain locations">,
BackendInfo;
def warn_toc_unsupported_type : Warning<"-mtocdata option is ignored "
"for %0 because %1">, InGroup<BackendWarningAttributes>;
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 8c9bfa7c103f2..039b552fe5042 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6057,8 +6057,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
bool NeedSrcLoc = TargetDecl->hasAttr<ErrorAttr>();
if (!NeedSrcLoc && CGM.getCodeGenOpts().ShowInliningChain) {
if (const auto *FD = dyn_cast<FunctionDecl>(TargetDecl))
- NeedSrcLoc = FD->isInlined() || FD->isInlineSpecified() ||
- FD->hasAttr<AlwaysInlineAttr>() ||
+ NeedSrcLoc = FD->isInlined() || FD->hasAttr<AlwaysInlineAttr>() ||
FD->getStorageClass() == SC_Static ||
FD->isInAnonymousNamespace();
}
diff --git a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
index cf259cc77f232..3d67ae946a230 100644
--- a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
+++ b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
@@ -64,4 +64,4 @@ void test_error_cross_tu(void) {
// CHECK: main.c:{{.*}}: note: inlined by function 'test_error_cross_tu'
// Fallback note should appear (no debug info).
-// CHECK: note: use '-gline-directives-only' or higher for more accurate inlining chain locations
+// CHECK: note: use '-gline-directives-only' (implied by '-g1') or higher for more accurate inlining chain locations
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
deleted file mode 100644
index 4760b95f49c39..0000000000000
--- a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// 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(void);
-
-// Non-static, non-inline functions that get inlined at -O2.
-void wrapper(void) {
- dangerous();
-}
-
-void middle(void) {
- wrapper();
-}
-
-void caller(void) {
- 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' 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'
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
new file mode 100644
index 0000000000000..ffdc59fa2852d
--- /dev/null
+++ b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
@@ -0,0 +1,68 @@
+// 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: :48:{{.*}}: warning: call to 'bad_func()'
+// HEURISTIC: :48:{{.*}}: note: called by function '(anonymous namespace)::anon_helper()'
+// HEURISTIC: :52:{{.*}}: note: inlined by function '(anonymous namespace)::anon_middle()'
+// HEURISTIC: :57:{{.*}}: note: inlined by function 'public_caller()'
+
+// DEBUG: :48:{{.*}}: warning: call to 'bad_func()'
+// DEBUG: :48:{{.*}}: note: called by function 'anon_helper'
+// DEBUG: :52:{{.*}}: note: inlined by function 'anon_middle'
+// DEBUG: :57:{{.*}}: note: inlined by function 'public_caller'
diff --git a/clang/test/Frontend/backend-attribute-inlining-modes.c b/clang/test/Frontend/backend-attribute-inlining-modes.c
index 9768845458754..adc010671fffd 100644
--- a/clang/test/Frontend/backend-attribute-inlining-modes.c
+++ b/clang/test/Frontend/backend-attribute-inlining-modes.c
@@ -32,7 +32,7 @@ void entry(void) {
// ENABLED-HEURISTIC: :14:{{.*}}: note: called by function 'level1'
// ENABLED-HEURISTIC: :18:{{.*}}: note: inlined by function 'level2'
// ENABLED-HEURISTIC: :22:{{.*}}: note: inlined by function 'entry'
-// ENABLED-HEURISTIC: note: use '-gline-directives-only' or higher for more accurate inlining chain locations
+// ENABLED-HEURISTIC: note: use '-gline-directives-only' (implied by '-g1') or higher for more accurate inlining chain locations
// Enabled with debug info: accurate locations.
// ENABLED-DEBUG: :14:{{.*}}: warning: call to 'bad_func'
diff --git a/clang/test/Frontend/backend-attribute-inlining.c b/clang/test/Frontend/backend-attribute-inlining.c
index 45a8e601e805f..734ce0fc30bba 100644
--- a/clang/test/Frontend/backend-attribute-inlining.c
+++ b/clang/test/Frontend/backend-attribute-inlining.c
@@ -109,4 +109,4 @@ void test_incidental(void) { not_marked_inline(); }
// CHECK-NOT: :{{.*}}: note: inlined by function 'test_incidental'
// Fallback note should appear (no debug info).
-// CHECK: note: use '-gline-directives-only' or higher for more accurate inlining chain locations
+// CHECK: note: use '-gline-directives-only' (implied by '-g1') or higher for more accurate inlining chain locations
>From e58af011a3048cf8a16a91f0edcca81f5187ab4c Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Thu, 8 Jan 2026 16:49:35 -0800
Subject: [PATCH 5/9] add test for always_inline
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
...-attribute-inlining-debug-vs-heuristic.cpp | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
index ffdc59fa2852d..edaaf8e7814d2 100644
--- a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
+++ b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
@@ -66,3 +66,26 @@ void public_caller() {
// DEBUG: :48:{{.*}}: note: called by function 'anon_helper'
// DEBUG: :52:{{.*}}: note: inlined by function 'anon_middle'
// DEBUG: :57:{{.*}}: 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: :78:{{.*}}: warning: call to 'always_inline_target()'
+// HEURISTIC: :78:{{.*}}: note: called by function 'always_inline_wrapper()'
+// HEURISTIC: :82:{{.*}}: note: inlined by function 'always_inline_caller()'
+
+// DEBUG: :78:{{.*}}: warning: call to 'always_inline_target()'
+// DEBUG: :78:{{.*}}: note: called by function 'always_inline_wrapper'
+// DEBUG: :82:{{.*}}: note: inlined by function 'always_inline_caller'
>From a91087f1f3173a8c1f53ec9ea45219d81752f75e Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Fri, 9 Jan 2026 09:40:10 -0800
Subject: [PATCH 6/9] use broader pattern matching for msvc tests
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
...-attribute-inlining-debug-vs-heuristic.cpp | 45 ++++++++++---------
1 file changed, 23 insertions(+), 22 deletions(-)
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
index edaaf8e7814d2..3a58be1327844 100644
--- a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
+++ b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
@@ -24,16 +24,17 @@ 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: :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: :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
@@ -57,15 +58,15 @@ void public_caller() {
anon_middle();
}
-// HEURISTIC: :48:{{.*}}: warning: call to 'bad_func()'
-// HEURISTIC: :48:{{.*}}: note: called by function '(anonymous namespace)::anon_helper()'
-// HEURISTIC: :52:{{.*}}: note: inlined by function '(anonymous namespace)::anon_middle()'
-// HEURISTIC: :57:{{.*}}: note: inlined by function 'public_caller()'
+// 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: :48:{{.*}}: warning: call to 'bad_func()'
-// DEBUG: :48:{{.*}}: note: called by function 'anon_helper'
-// DEBUG: :52:{{.*}}: note: inlined by function 'anon_middle'
-// DEBUG: :57:{{.*}}: 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.
@@ -82,10 +83,10 @@ void always_inline_caller() {
always_inline_wrapper();
}
-// HEURISTIC: :78:{{.*}}: warning: call to 'always_inline_target()'
-// HEURISTIC: :78:{{.*}}: note: called by function 'always_inline_wrapper()'
-// HEURISTIC: :82:{{.*}}: note: inlined by function 'always_inline_caller()'
+// 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: :78:{{.*}}: warning: call to 'always_inline_target()'
-// DEBUG: :78:{{.*}}: note: called by function 'always_inline_wrapper'
-// DEBUG: :82:{{.*}}: 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{{.*}}'
>From b4e0175024aafba12cb66356731a08e1917232e9 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Tue, 13 Jan 2026 16:10:08 -0800
Subject: [PATCH 7/9] drop accidentally picked up release notes
I accidentally picked these up when resolving a conflict during a
routine rebase onto upstream.
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
clang/docs/ReleaseNotes.rst | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 11df59b9e65b2..f21a0d8c423d8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -90,11 +90,6 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------
-- New option ``-fno-sanitize-debug-trap-reasons`` added to disable emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
-- New option ``-fsanitize-debug-trap-reasons=`` added to control emitting trap reasons into the debug info when compiling with trapping UBSan (e.g. ``-fsanitize-trap=undefined``).
-- New options for enabling allocation token instrumentation: ``-fsanitize=alloc-token``, ``-falloc-token-max=``, ``-fsanitize-alloc-token-fast-abi``, ``-fsanitize-alloc-token-extended``.
-- The ``-resource-dir`` option is now displayed in the list of options shown by ``--help``.
-- New option ``-fmatrix-memory-layout`` added to control the memory layout of Clang matrix types. (e.g. ``-fmatrix-memory-layout=column-major`` or ``-fmatrix-memory-layout=row-major``).
- New option ``-fdiagnostics-show-inlining-chain`` added to show inlining chain
notes for ``[[gnu::warning]]`` and ``[[gnu::error]]`` diagnostics. When a
function with these attributes is called from an inlined context, Clang can
@@ -103,10 +98,6 @@ New Compiler Flags
higher), accurate source locations are used; otherwise, a heuristic fallback
is used with a note suggesting how to enable debug info for better accuracy.
-Lanai Support
-^^^^^^^^^^^^^^
-- The option ``-mcmodel={small,medium,large}`` is supported again.
-
Deprecated Compiler Flags
-------------------------
>From 7ff74718529507baa696be44488cc0e4cb7081e4 Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Fri, 16 Jan 2026 11:53:26 -0800
Subject: [PATCH 8/9] remove flag, now enabled by default
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
clang/docs/ReleaseNotes.rst | 15 ++++++++-------
clang/include/clang/Basic/AttrDocs.td | 19 ++++++++-----------
clang/include/clang/Basic/CodeGenOptions.def | 2 --
clang/include/clang/Options/Options.td | 17 ++++++-----------
clang/lib/CodeGen/CGCall.cpp | 11 +++++------
clang/lib/CodeGen/CodeGenAction.cpp | 3 ---
clang/lib/Driver/ToolChains/Clang.cpp | 9 ---------
.../backend-attribute-inlining-cross-tu.c | 2 +-
...-attribute-inlining-debug-vs-heuristic.cpp | 4 ++--
.../backend-attribute-inlining-modes.c | 4 ++--
.../Frontend/backend-attribute-inlining.c | 2 +-
11 files changed, 33 insertions(+), 55 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f21a0d8c423d8..950032d2f80f5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -90,13 +90,6 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------
-- New option ``-fdiagnostics-show-inlining-chain`` added to show inlining chain
- notes for ``[[gnu::warning]]`` and ``[[gnu::error]]`` diagnostics. When a
- function with these attributes is called from an inlined context, Clang can
- now show which functions were inlined to reach the call. When debug info is
- available (``-gline-directives-only`` (implicitly enabled at ``-g1``) or
- higher), accurate source locations are used; otherwise, a heuristic fallback
- is used with a note suggesting how to enable debug info for better accuracy.
Deprecated Compiler Flags
-------------------------
@@ -112,6 +105,14 @@ Attribute Changes in Clang
Improvements to Clang's diagnostics
-----------------------------------
+- ``[[gnu::warning]]`` and ``[[gnu::error]]`` diagnostics now have notes
+ describing inlining locations. When a function with these attributes is
+ called from an inlined context, Clang can now show which functions were
+ inlined to reach the call. When debug info is available
+ (``-gline-directives-only`` (implicitly enabled at ``-g1``) or higher),
+ accurate source locations are used; otherwise, a heuristic fallback is used
+ with a note suggesting how to enable debug info for better accuracy.
+
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 6ea1a007d58cf..466fc5cfa9425 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -8398,17 +8398,14 @@ pointing to precise locations of the call site in the source.
sizeof(dontcall()); // No Warning
}
-When the call occurs through inlined functions, the
-``-fdiagnostics-show-inlining-chain`` option can be used to show the
-inlining chain that led to the call. This helps identify which call site
-triggered the diagnostic when the attributed function is called from
-multiple locations through inline functions.
-
-When enabled, this option automatically uses debug info for accurate source
-locations if available (``-gline-directives-only`` (implicitly enabled at
-``-g1``) or higher), or falls back to a heuristic based on metadata tracking.
-When falling back, a note is emitted suggesting ``-gline-directives-only`` for
-more accurate locations.
+When the call occurs through inlined functions, the inlining chain that led to
+the call is shown. This helps identify which call site triggered the diagnostic
+when the attributed function is called from multiple locations through inline
+functions.
+
+The most accurate source location information for inline notes can be obtained
+when ``-gline-directives-only`` (implied by ``-g1`` or higher) is enabled.
+Otherwise, a heuristic approach is used to track source locations.
}];
}
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index cd0675c6e35a0..baf8b093c10e6 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -76,8 +76,6 @@ CODEGENOPT(CallGraphSection, 1, 0, Benign) ///< Emit a call graph section into t
///< object file.
CODEGENOPT(EmitCallSiteInfo, 1, 0, Benign) ///< Emit call site info only in the case of
///< '-g' + 'O>0' level.
-/// Show inlining chain notes for [[gnu::warning/error]] diagnostics.
-CODEGENOPT(ShowInliningChain, 1, 0, Benign)
CODEGENOPT(IndirectTlsSegRefs, 1, 0, Benign) ///< Set when -mno-tls-direct-seg-refs
///< is specified.
CODEGENOPT(DisableTailCalls , 1, 0, Benign) ///< Do not emit tail calls.
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 70b607c601a18..e3ff5d3c17b6d 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2154,17 +2154,12 @@ defm diagnostics_show_option : BoolFOption<"diagnostics-show-option",
DiagnosticOpts<"ShowOptionNames">, DefaultTrue,
NegFlag<SetFalse, [], [ClangOption, CC1Option]>,
PosFlag<SetTrue, [], [ClangOption], "Print option name with mappable diagnostics">>;
-defm diagnostics_show_note_include_stack : BoolFOption<"diagnostics-show-note-include-stack",
- DiagnosticOpts<"ShowNoteIncludeStack">, DefaultFalse,
- PosFlag<SetTrue, [], [ClangOption], "Display include stacks for diagnostic notes">,
- NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;
-defm diagnostics_show_inlining_chain
- : BoolFOption<"diagnostics-show-inlining-chain",
- CodeGenOpts<"ShowInliningChain">, DefaultFalse,
- PosFlag<SetTrue, [], [ClangOption, CC1Option],
- "Show inlining chain notes for "
- "[[gnu::warning/error]] diagnostics">,
- NegFlag<SetFalse, [], [ClangOption, CC1Option]>>;
+defm diagnostics_show_note_include_stack
+ : BoolFOption<"diagnostics-show-note-include-stack",
+ DiagnosticOpts<"ShowNoteIncludeStack">, DefaultFalse,
+ PosFlag<SetTrue, [], [ClangOption],
+ "Display include stacks for diagnostic notes">,
+ NegFlag<SetFalse>, BothFlags<[], [ClangOption, CC1Option]>>;
def fdiagnostics_format_EQ : Joined<["-"], "fdiagnostics-format=">, Group<f_clang_Group>;
def fdiagnostics_show_category_EQ : Joined<["-"], "fdiagnostics-show-category=">, Group<f_clang_Group>;
def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tree">,
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp
index 039b552fe5042..99fbefbaf18ad 100644
--- a/clang/lib/CodeGen/CGCall.cpp
+++ b/clang/lib/CodeGen/CGCall.cpp
@@ -6048,14 +6048,13 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (getDebugInfo() && TargetDecl && TargetDecl->hasAttr<MSAllocatorAttr>())
getDebugInfo()->addHeapAllocSiteMetadata(CI, RetTy->getPointeeType(), Loc);
- // Add srcloc metadata for [[gnu::error/warning]] diagnostics. When
- // ShowInliningChain is enabled, also track inline/static calls for the
- // heuristic fallback when debug info is not available. This heuristic is
- // conservative and best-effort since static or inline-annotated functions
- // are still not guaranteed to be inlined.
+ // Add srcloc metadata for [[gnu::error/warning]] diagnostics. Track
+ // inline/static calls for the heuristic fallback when debug info is not
+ // available. This heuristic is conservative and best-effort since static or
+ // inline-annotated functions are still not guaranteed to be inlined.
if (TargetDecl) {
bool NeedSrcLoc = TargetDecl->hasAttr<ErrorAttr>();
- if (!NeedSrcLoc && CGM.getCodeGenOpts().ShowInliningChain) {
+ if (!NeedSrcLoc) {
if (const auto *FD = dyn_cast<FunctionDecl>(TargetDecl))
NeedSrcLoc = FD->isInlined() || FD->hasAttr<AlwaysInlineAttr>() ||
FD->getStorageClass() == SC_Static ||
diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp
index 3a46acf0e17f0..3e492b9517fe2 100644
--- a/clang/lib/CodeGen/CodeGenAction.cpp
+++ b/clang/lib/CodeGen/CodeGenAction.cpp
@@ -733,9 +733,6 @@ void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) {
: diag::warn_fe_backend_warning_attr)
<< llvm::demangle(D.getFunctionName()) << D.getNote();
- if (!CodeGenOpts.ShowInliningChain)
- return;
-
auto EmitNote = [&](SourceLocation Loc, StringRef FuncName, bool IsFirst) {
if (!Loc.isValid())
Loc = LocCookie;
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index fc9cebbdbe21b..4ca98600d6e93 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4281,15 +4281,6 @@ static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,
CmdArgs.push_back(Args.MakeArgString(Opt));
}
- if (const Arg *A =
- Args.getLastArg(options::OPT_fdiagnostics_show_inlining_chain,
- options::OPT_fno_diagnostics_show_inlining_chain)) {
- if (A->getOption().matches(options::OPT_fdiagnostics_show_inlining_chain))
- CmdArgs.push_back("-fdiagnostics-show-inlining-chain");
- else
- CmdArgs.push_back("-fno-diagnostics-show-inlining-chain");
- }
-
if (const Arg *A = Args.getLastArg(options::OPT_fdiagnostics_format_EQ)) {
CmdArgs.push_back("-fdiagnostics-format");
CmdArgs.push_back(A->getValue());
diff --git a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
index 3d67ae946a230..18cc0606e1bb5 100644
--- a/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
+++ b/clang/test/Frontend/backend-attribute-inlining-cross-tu.c
@@ -1,6 +1,6 @@
// RUN: rm -rf %t
// RUN: split-file %s %t
-// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain -S %t/main.c -I%t -o /dev/null 2>&1 | FileCheck %s
+// RUN: not %clang -O2 -S %t/main.c -I%t -o /dev/null 2>&1 | FileCheck %s
// Cross-TU inlining: header functions inlined into source file.
diff --git a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
index 3a58be1327844..65e4eea8f2a44 100644
--- a/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
+++ b/clang/test/Frontend/backend-attribute-inlining-debug-vs-heuristic.cpp
@@ -1,5 +1,5 @@
-// 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
+// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=HEURISTIC
+// RUN: %clang_cc1 -O2 -emit-obj -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
diff --git a/clang/test/Frontend/backend-attribute-inlining-modes.c b/clang/test/Frontend/backend-attribute-inlining-modes.c
index adc010671fffd..f626045af0b95 100644
--- a/clang/test/Frontend/backend-attribute-inlining-modes.c
+++ b/clang/test/Frontend/backend-attribute-inlining-modes.c
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DISABLED
-// RUN: %clang_cc1 -O2 -emit-obj -fdiagnostics-show-inlining-chain %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ENABLED-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=ENABLED-DEBUG
+// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ENABLED-HEURISTIC
+// RUN: %clang_cc1 -O2 -emit-obj -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ENABLED-DEBUG
// Test -fdiagnostics-show-inlining-chain behavior:
// - Disabled (default): warning only, no inlining notes.
diff --git a/clang/test/Frontend/backend-attribute-inlining.c b/clang/test/Frontend/backend-attribute-inlining.c
index 734ce0fc30bba..0c49c395b3f83 100644
--- a/clang/test/Frontend/backend-attribute-inlining.c
+++ b/clang/test/Frontend/backend-attribute-inlining.c
@@ -1,4 +1,4 @@
-// RUN: not %clang -O2 -fdiagnostics-show-inlining-chain -S %s -o /dev/null 2>&1 | FileCheck %s
+// RUN: not %clang -O2 -S %s -o /dev/null 2>&1 | FileCheck %s
// Single-level inlining with warning attribute.
[[gnu::warning("do not call directly")]]
>From eba4a6786ab23c2a3207f6ec5bf930fe8b75555d Mon Sep 17 00:00:00 2001
From: Justin Stitt <justinstitt at google.com>
Date: Fri, 16 Jan 2026 13:59:16 -0800
Subject: [PATCH 9/9] update stale clang tests
Signed-off-by: Justin Stitt <justinstitt at google.com>
---
clang/test/CodeGen/attr-nomerge.cpp | 6 +--
clang/test/CodeGenCXX/builtin-invoke.cpp | 4 +-
.../inheriting-constructor-cleanup.cpp | 2 +-
.../test/CodeGenCXX/type-aware-allocators.cpp | 2 +-
.../coro-await-resume-eh.cpp | 2 +-
clang/test/DebugInfo/CXX/member-call.cpp | 4 +-
.../backend-attribute-inlining-modes.c | 26 ++++--------
...ibute_parallel_for_num_threads_codegen.cpp | 8 ++--
..._parallel_for_simd_num_threads_codegen.cpp | 12 +++---
clang/test/OpenMP/scope_codegen.cpp | 8 ++--
clang/test/OpenMP/single_codegen.cpp | 12 +++---
...ibute_parallel_for_num_threads_codegen.cpp | 4 +-
..._parallel_for_simd_num_threads_codegen.cpp | 6 +--
clang/test/OpenMP/threadprivate_codegen.cpp | 42 +++++++++----------
.../Inputs/basic-cplusplus.cpp.expected | 41 ++++++++++++------
...plicit-template-instantiation.cpp.expected | 20 ++++-----
16 files changed, 103 insertions(+), 96 deletions(-)
diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp
index 1cf5bb1619b31..f9c0235de89f9 100644
--- a/clang/test/CodeGen/attr-nomerge.cpp
+++ b/clang/test/CodeGen/attr-nomerge.cpp
@@ -92,10 +92,10 @@ void something_else_again() {
// CHECK: call void @_ZN1AC1Ev({{.*}}) #[[ATTR0]]
// CHECK: call void @_ZN1A1fEv({{.*}}) #[[ATTR0]]
// CHECK: call void @_ZN1A1gEv({{.*}}) #[[ATTR0]]
-// CHECK: call void @_ZN1A2f1Ev() #[[ATTR0]]
-// CHECK: call void @_ZN1BC1Ev({{.*}}){{$}}
+// CHECK: call void @_ZN1A2f1Ev(){{.*}}#[[ATTR0]]
+// CHECK: call void @_ZN1BC1Ev({{.*}}){{.*}}{{$}}
// CHECK: call void @_ZN1B1gEv({{.*}}){{$}}
-// CHECK: call void @_ZN1BC1Ev({{.*}}){{$}}
+// CHECK: call void @_ZN1BC1Ev({{.*}}){{.*}}{{$}}
// CHECK: load ptr, ptr
// CHECK: load ptr, ptr
// CHECK: %[[AG:.*]] = load ptr, ptr
diff --git a/clang/test/CodeGenCXX/builtin-invoke.cpp b/clang/test/CodeGenCXX/builtin-invoke.cpp
index 0f84f83e18add..a4f65f1a5df1e 100644
--- a/clang/test/CodeGenCXX/builtin-invoke.cpp
+++ b/clang/test/CodeGenCXX/builtin-invoke.cpp
@@ -47,8 +47,8 @@ extern "C" void call_memptr(std::reference_wrapper<Callable> wrapper) {
// CHECK-EMPTY:
// CHECK-NEXT: memptr.virtual:
// CHECK-NEXT: %vtable = load ptr, ptr %0, align 8
- // CHECK-NEXT: %1 = getelementptr i8, ptr %vtable, i64 sub (i64 ptrtoint (ptr @_ZN8Callable4funcEv to i64), i64 1), !nosanitize !2
- // CHECK-NEXT: %memptr.virtualfn = load ptr, ptr %1, align 8, !nosanitize !2
+ // CHECK-NEXT: %1 = getelementptr i8, ptr %vtable, i64 sub (i64 ptrtoint (ptr @_ZN8Callable4funcEv to i64), i64 1), !nosanitize !
+ // CHECK-NEXT: %memptr.virtualfn = load ptr, ptr %1, align 8, !nosanitize !
// CHECK-NEXT: br label %memptr.end
// CHECK-EMPTY:
// CHECK-NEXT: memptr.nonvirtual:
diff --git a/clang/test/CodeGenCXX/inheriting-constructor-cleanup.cpp b/clang/test/CodeGenCXX/inheriting-constructor-cleanup.cpp
index 722166fd86488..fc350bca36b98 100644
--- a/clang/test/CodeGenCXX/inheriting-constructor-cleanup.cpp
+++ b/clang/test/CodeGenCXX/inheriting-constructor-cleanup.cpp
@@ -37,7 +37,7 @@ void f() {
// EXCEPTIONS: %[[TMP1:.*]] = alloca %struct.S1
// EXCEPTIONS: %[[TMP2:.*]] = alloca %struct.S2
// EXCEPTIONS: invoke void (ptr, ptr, ptr, ptr, ...) @_ZN4BaseC2ERK2S1RK2S2PKcz(ptr {{.*}}, ptr noundef nonnull align 1 dereferenceable(1) %[[TMP1]], ptr noundef nonnull align 1 dereferenceable(1) %[[TMP2]], ptr {{.*}})
- // EXCEPTIONS-NEXT: to label %[[CONT:.*]] unwind label %[[LPAD:.*]]
+ // EXCEPTIONS-NEXT: to label %[[CONT:.*]] unwind label %[[LPAD:.*]], !srcloc
// EXCEPTIONS: [[CONT]]:
// EXCEPTIONS-NEXT: call void @_ZN9InheritorD1Ev(ptr {{.*}})
diff --git a/clang/test/CodeGenCXX/type-aware-allocators.cpp b/clang/test/CodeGenCXX/type-aware-allocators.cpp
index cce9197ed0d12..a91087aa4b659 100644
--- a/clang/test/CodeGenCXX/type-aware-allocators.cpp
+++ b/clang/test/CodeGenCXX/type-aware-allocators.cpp
@@ -163,7 +163,7 @@ extern "C" void test_ensure_type_aware_overrides() {
// CHECK: call void [[S6_DFN]](
// CHECK: [[S7_ALLOC:%.*]] = call {{.*}} @_ZN2S6nwI2S7EEPvSt13type_identityIT_EmSt11align_val_t(
// CHECK: @_ZN2S7C1Ev({{.*}}[[S7_ALLOC]])
-// CHECK-NEXT: unwind label %[[S7LPAD:.*]]
+// CHECK-NEXT: unwind label %[[S7LPAD:.*]], !srcloc
// CHECK: [[S7_VTABLE:%vtable.*]] = load
// CHECK: [[S7_DFN_ADDR:%.*]] = getelementptr inbounds ptr, ptr [[S7_VTABLE]], i64 1
// CHECK: [[S7_DFN:%.*]] = load ptr, ptr [[S7_DFN_ADDR]]
diff --git a/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp b/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp
index 8253337ba7390..1ad8fe0cc43ba 100644
--- a/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp
+++ b/clang/test/CodeGenCoroutines/coro-await-resume-eh.cpp
@@ -34,7 +34,7 @@ throwing_task f() {
// CHECK: init.ready:
// CHECK-NEXT: store i1 true, ptr %[[RESUMETHREW:.+]], align 1
// CHECK-NEXT: invoke void @_ZN18throwing_awaitable12await_resumeEv
- // CHECK-NEXT: to label %[[RESUMECONT:.+]] unwind label %[[RESUMELPAD:.+]]
+ // CHECK-NEXT: to label %[[RESUMECONT:.+]] unwind label %[[RESUMELPAD:.+]], !srcloc
// If 'await_resume' does not throw an exception, 'false' is stored in
// variable RESUMETHREW.
diff --git a/clang/test/DebugInfo/CXX/member-call.cpp b/clang/test/DebugInfo/CXX/member-call.cpp
index 2b60de8aee491..d73147ba8efb6 100644
--- a/clang/test/DebugInfo/CXX/member-call.cpp
+++ b/clang/test/DebugInfo/CXX/member-call.cpp
@@ -16,8 +16,8 @@ void test(Foo *f) {
}
// CHECK-LABEL: @_Z4testP3Foo
-// CHECK: call {{.*}} @_ZN3Foo3fooEv{{.*}}, !dbg ![[CALL1LOC:.*]]
-// CHECK: call void @_ZN3Bar3barEv{{.*}}, !dbg ![[CALL2LOC:.*]]
+// CHECK: call {{.*}} @_ZN3Foo3fooEv{{.*}}, !dbg ![[CALL1LOC:.*]], !srcloc
+// CHECK: call void @_ZN3Bar3barEv{{.*}}, !dbg ![[CALL2LOC:.*]], !srcloc
// CHECK: ![[CALL1LOC]] = !DILocation(line: [[LINE:[0-9]+]], column: 6,
// CHECK: ![[CALL2LOC]] = !DILocation(line: [[LINE]], column: 13,
diff --git a/clang/test/Frontend/backend-attribute-inlining-modes.c b/clang/test/Frontend/backend-attribute-inlining-modes.c
index f626045af0b95..653e5bb0390bd 100644
--- a/clang/test/Frontend/backend-attribute-inlining-modes.c
+++ b/clang/test/Frontend/backend-attribute-inlining-modes.c
@@ -1,12 +1,6 @@
-// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=DISABLED
// RUN: %clang_cc1 -O2 -emit-obj %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ENABLED-HEURISTIC
// RUN: %clang_cc1 -O2 -emit-obj -debug-info-kind=line-directives-only %s -o /dev/null 2>&1 | FileCheck %s --check-prefix=ENABLED-DEBUG
-// Test -fdiagnostics-show-inlining-chain behavior:
-// - Disabled (default): warning only, no inlining notes.
-// - Enabled without debug info: heuristic fallback + suggestion note.
-// - Enabled with debug info: accurate locations from DILocation.
-
[[gnu::warning("do not call")]]
void bad_func(void);
@@ -22,21 +16,17 @@ void entry(void) {
level2();
}
-// Disabled (default): warning only, no inlining notes.
-// DISABLED: warning: call to 'bad_func'
-// DISABLED-NOT: note:
-
// Enabled without debug info: heuristic fallback.
// All notes point to original call site (:14).
-// ENABLED-HEURISTIC: :14:{{.*}}: warning: call to 'bad_func'
-// ENABLED-HEURISTIC: :14:{{.*}}: note: called by function 'level1'
-// ENABLED-HEURISTIC: :18:{{.*}}: note: inlined by function 'level2'
-// ENABLED-HEURISTIC: :22:{{.*}}: note: inlined by function 'entry'
+// ENABLED-HEURISTIC: :8:{{.*}}: warning: call to 'bad_func'
+// ENABLED-HEURISTIC: :8:{{.*}}: note: called by function 'level1'
+// ENABLED-HEURISTIC: :12:{{.*}}: note: inlined by function 'level2'
+// ENABLED-HEURISTIC: :16:{{.*}}: note: inlined by function 'entry'
// ENABLED-HEURISTIC: note: use '-gline-directives-only' (implied by '-g1') or higher for more accurate inlining chain locations
// Enabled with debug info: accurate locations.
-// ENABLED-DEBUG: :14:{{.*}}: warning: call to 'bad_func'
-// ENABLED-DEBUG: :14:{{.*}}: note: called by function 'level1'
-// ENABLED-DEBUG: :18:{{.*}}: note: inlined by function 'level2'
-// ENABLED-DEBUG: :22:{{.*}}: note: inlined by function 'entry'
+// ENABLED-DEBUG: :8:{{.*}}: warning: call to 'bad_func'
+// ENABLED-DEBUG: :8:{{.*}}: note: called by function 'level1'
+// ENABLED-DEBUG: :12:{{.*}}: note: inlined by function 'level2'
+// ENABLED-DEBUG: :16:{{.*}}: note: inlined by function 'entry'
// ENABLED-DEBUG-NOT: note: use '-gline-directives-only'
diff --git a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
index bf979d79fc61b..60ed7a227731e 100644
--- a/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_num_threads_codegen.cpp
@@ -2508,7 +2508,7 @@ int main() {
// CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK1-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK1-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -3760,7 +3760,7 @@ int main() {
// CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK5-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK5-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK5: invoke.cont:
// CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -5012,7 +5012,7 @@ int main() {
// CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK9-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK9-NEXT: [[CALL:%.*]] = invoke noundef i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK9-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK9-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK9: invoke.cont:
// CHECK9-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -6264,7 +6264,7 @@ int main() {
// CHECK13-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK13-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK13-NEXT: [[CALL:%.*]] = invoke noundef i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK13-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK13-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK13: invoke.cont:
// CHECK13-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
index 0d4b9b245743d..62a1f68070dbc 100644
--- a/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -112,7 +112,7 @@ int main() {
// CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK1-NEXT: call void @_ZN1SC1El(ptr nonnull align 8 dereferenceable(24) [[S]], i64 0)
// CHECK1-NEXT: [[CALL:%.*]] = invoke signext i8 @_ZN1ScvcEv(ptr nonnull align 8 dereferenceable(24) [[S]])
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -1450,7 +1450,7 @@ int main() {
// CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK3-NEXT: call void @_ZN1SC1El(ptr nonnull align 8 dereferenceable(24) [[S]], i64 0)
// CHECK3-NEXT: [[CALL:%.*]] = invoke signext i8 @_ZN1ScvcEv(ptr nonnull align 8 dereferenceable(24) [[S]])
-// CHECK3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK3: invoke.cont:
// CHECK3-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
@@ -1787,7 +1787,7 @@ int main() {
// CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK5-NEXT: call void @_ZN1SC1El(ptr nonnull align 8 dereferenceable(24) [[S]], i64 0)
// CHECK5-NEXT: [[CALL:%.*]] = invoke signext i8 @_ZN1ScvcEv(ptr nonnull align 8 dereferenceable(24) [[S]])
-// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK5: invoke.cont:
// CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -3123,7 +3123,7 @@ int main() {
// CHECK9-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK9-NEXT: call void @_ZN1SC1El(ptr nonnull align 8 dereferenceable(24) [[S]], i64 0)
// CHECK9-NEXT: [[CALL:%.*]] = invoke i8 @_ZN1ScvcEv(ptr nonnull align 8 dereferenceable(24) [[S]])
-// CHECK9-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK9-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK9: invoke.cont:
// CHECK9-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK9-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -4461,7 +4461,7 @@ int main() {
// CHECK11-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK11-NEXT: call void @_ZN1SC1El(ptr nonnull align 8 dereferenceable(24) [[S]], i64 0)
// CHECK11-NEXT: [[CALL:%.*]] = invoke i8 @_ZN1ScvcEv(ptr nonnull align 8 dereferenceable(24) [[S]])
-// CHECK11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK11-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK11: invoke.cont:
// CHECK11-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK11-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
@@ -4798,7 +4798,7 @@ int main() {
// CHECK13-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK13-NEXT: call void @_ZN1SC1El(ptr nonnull align 8 dereferenceable(24) [[S]], i64 0)
// CHECK13-NEXT: [[CALL:%.*]] = invoke i8 @_ZN1ScvcEv(ptr nonnull align 8 dereferenceable(24) [[S]])
-// CHECK13-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK13-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK13: invoke.cont:
// CHECK13-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK13-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/scope_codegen.cpp b/clang/test/OpenMP/scope_codegen.cpp
index ef69b8302fa2d..35a0aef5c027b 100644
--- a/clang/test/OpenMP/scope_codegen.cpp
+++ b/clang/test/OpenMP/scope_codegen.cpp
@@ -185,7 +185,7 @@ int main() {
// CHECK1: arrayctor.loop:
// CHECK1-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK1-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK1-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
@@ -267,7 +267,7 @@ int main() {
// CHECK1-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
// CHECK1-NEXT: store i8 [[TMP1]], ptr [[A1]], align 1
// CHECK1-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[C2]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: store ptr [[C2]], ptr [[TMP]], align 8
// CHECK1-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[TC]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
@@ -683,7 +683,7 @@ int main() {
// CHECK4: arrayctor.loop:
// CHECK4-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK4-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK4: invoke.cont:
// CHECK4-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK4-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
@@ -765,7 +765,7 @@ int main() {
// CHECK4-NEXT: [[TMP1:%.*]] = load i8, ptr [[A]], align 1
// CHECK4-NEXT: store i8 [[TMP1]], ptr [[A1]], align 1
// CHECK4-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[C2]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
-// CHECK4-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]]
+// CHECK4-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[TERMINATE_LPAD:%.*]], !srcloc
// CHECK4: invoke.cont:
// CHECK4-NEXT: store ptr [[C2]], ptr [[TMP]], align 8
// CHECK4-NEXT: invoke void @_ZN9TestClassC1ERKS_(ptr noundef nonnull align 4 dereferenceable(4) [[TC]], ptr noundef nonnull align 4 dereferenceable(4) @tc)
diff --git a/clang/test/OpenMP/single_codegen.cpp b/clang/test/OpenMP/single_codegen.cpp
index a4c9b015b615f..00f606a2350f9 100644
--- a/clang/test/OpenMP/single_codegen.cpp
+++ b/clang/test/OpenMP/single_codegen.cpp
@@ -170,7 +170,7 @@ void array_func(int n, int a[n], St s[2]) {
// CHECK1: arrayctor.loop:
// CHECK1-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK1-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK1-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]]
@@ -246,7 +246,7 @@ void array_func(int n, int a[n], St s[2]) {
// CHECK1: arrayctor.loop:
// CHECK1-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK1-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK1-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
@@ -1048,7 +1048,7 @@ void array_func(int n, int a[n], St s[2]) {
// CHECK2: arrayctor.loop:
// CHECK2-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK2-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK2-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK2: invoke.cont:
// CHECK2-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK2-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
@@ -1140,7 +1140,7 @@ void array_func(int n, int a[n], St s[2]) {
// CHECK2: arrayctor.loop:
// CHECK2-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK2-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK2-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK2: invoke.cont:
// CHECK2-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK2-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]]
@@ -1977,7 +1977,7 @@ void array_func(int n, int a[n], St s[2]) {
// CHECK4: arrayctor.loop:
// CHECK4-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ @tc2, [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK4-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK4: invoke.cont:
// CHECK4-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS:%.*]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK4-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], getelementptr inbounds ([[CLASS_TESTCLASS]], ptr @tc2, i64 2)
@@ -2024,7 +2024,7 @@ void array_func(int n, int a[n], St s[2]) {
// CHECK4: arrayctor.loop:
// CHECK4-NEXT: [[ARRAYCTOR_CUR:%.*]] = phi ptr [ [[ARRAY_BEGIN]], [[ENTRY:%.*]] ], [ [[ARRAYCTOR_NEXT:%.*]], [[INVOKE_CONT:%.*]] ]
// CHECK4-NEXT: invoke void @_ZN9TestClassC1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYCTOR_CUR]])
-// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]]
+// CHECK4-NEXT: to label [[INVOKE_CONT]] unwind label [[LPAD:%.*]], !srcloc
// CHECK4: invoke.cont:
// CHECK4-NEXT: [[ARRAYCTOR_NEXT]] = getelementptr inbounds [[CLASS_TESTCLASS]], ptr [[ARRAYCTOR_CUR]], i64 1
// CHECK4-NEXT: [[ARRAYCTOR_DONE:%.*]] = icmp eq ptr [[ARRAYCTOR_NEXT]], [[ARRAYCTOR_END]]
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
index d097631f7d0e5..2ea44a5a07bef 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_num_threads_codegen.cpp
@@ -93,7 +93,7 @@ int main() {
// CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK1-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK1-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -1380,7 +1380,7 @@ int main() {
// CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK5-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK5-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK5: invoke.cont:
// CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
index d5f3af343fced..3884a48b36ee8 100644
--- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
+++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_num_threads_codegen.cpp
@@ -95,7 +95,7 @@ int main() {
// CHECK1-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK1-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK1-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK1-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
@@ -1468,7 +1468,7 @@ int main() {
// CHECK3-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK3-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK3-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK3: invoke.cont:
// CHECK3-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK3-NEXT: store i32 0, ptr [[DOTOMP_LB]], align 4
@@ -1815,7 +1815,7 @@ int main() {
// CHECK5-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK5-NEXT: call void @_ZN1SC1El(ptr noundef nonnull align 8 dereferenceable(24) [[S]], i64 noundef 0)
// CHECK5-NEXT: [[CALL:%.*]] = invoke noundef signext i8 @_ZN1ScvcEv(ptr noundef nonnull align 8 dereferenceable(24) [[S]])
-// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK5-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK5: invoke.cont:
// CHECK5-NEXT: store i8 [[CALL]], ptr [[A]], align 1
// CHECK5-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___TGT_KERNEL_ARGUMENTS]], ptr [[KERNEL_ARGS]], i32 0, i32 0
diff --git a/clang/test/OpenMP/threadprivate_codegen.cpp b/clang/test/OpenMP/threadprivate_codegen.cpp
index 154c5f45642a4..f7f97483bf803 100644
--- a/clang/test/OpenMP/threadprivate_codegen.cpp
+++ b/clang/test/OpenMP/threadprivate_codegen.cpp
@@ -1037,7 +1037,7 @@ int foobar() {
// CHECK1-NEXT: store ptr [[TMP1]], ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK1-NEXT: store ptr [[TMP1]], ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[TMP1]], i32 noundef 1)
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S1:%.*]], ptr [[TMP1]], i64 1
// CHECK1-NEXT: store ptr [[ARRAYINIT_ELEMENT]], ptr [[ARRAYINIT_ENDOFINIT1]], align 8
@@ -1053,7 +1053,7 @@ int foobar() {
// CHECK1-NEXT: store ptr [[ARRAYINIT_ELEMENT6]], ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK1-NEXT: store ptr [[ARRAYINIT_ELEMENT6]], ptr [[ARRAYINIT_ENDOFINIT7]], align 8
// CHECK1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT6]], i32 noundef 4)
-// CHECK1-NEXT: to label [[INVOKE_CONT9:%.*]] unwind label [[LPAD8:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT9:%.*]] unwind label [[LPAD8:%.*]], !srcloc
// CHECK1: invoke.cont9:
// CHECK1-NEXT: [[ARRAYINIT_ELEMENT10:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[ARRAYINIT_ELEMENT6]], i64 1
// CHECK1-NEXT: store ptr [[ARRAYINIT_ELEMENT10]], ptr [[ARRAYINIT_ENDOFINIT7]], align 8
@@ -1251,7 +1251,7 @@ int foobar() {
// CHECK1-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK1-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -1264,7 +1264,7 @@ int foobar() {
// CHECK1-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK1-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i32 noundef 4)
-// CHECK1-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]], !srcloc
// CHECK1: invoke.cont7:
// CHECK1-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), i32 noundef 5)
@@ -1372,7 +1372,7 @@ int foobar() {
// CHECK1-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_S1:%.*]], ptr [[TMP4]], i32 0, i32 0
// CHECK1-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4
// CHECK1-NEXT: invoke void @_ZZ4mainEN5SmainC1Ei(ptr noundef nonnull align 8 dereferenceable(24) @_ZZ4mainE2sm, i32 noundef [[TMP5]])
-// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK1: invoke.cont:
// CHECK1-NEXT: [[TMP6:%.*]] = call i32 @__cxa_atexit(ptr @_ZZ4mainEN5SmainD1Ev, ptr @_ZZ4mainE2sm, ptr @__dso_handle) #[[ATTR3]]
// CHECK1-NEXT: call void @__cxa_guard_release(ptr @_ZGVZ4mainE2sm) #[[ATTR3]]
@@ -1774,7 +1774,7 @@ int foobar() {
// CHECK2-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK2-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK2: invoke.cont:
// CHECK2-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -1787,7 +1787,7 @@ int foobar() {
// CHECK2-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK2-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i32 noundef 4)
-// CHECK2-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]], !srcloc
// CHECK2: invoke.cont7:
// CHECK2-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), i32 noundef 5)
@@ -1886,7 +1886,7 @@ int foobar() {
// CHECK2-NEXT: store ptr [[TMP1]], ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK2-NEXT: store ptr [[TMP1]], ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[TMP1]], i32 noundef 1)
-// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK2: invoke.cont:
// CHECK2-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr inbounds [[STRUCT_S1:%.*]], ptr [[TMP1]], i64 1
// CHECK2-NEXT: store ptr [[ARRAYINIT_ELEMENT]], ptr [[ARRAYINIT_ENDOFINIT1]], align 8
@@ -1902,7 +1902,7 @@ int foobar() {
// CHECK2-NEXT: store ptr [[ARRAYINIT_ELEMENT6]], ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK2-NEXT: store ptr [[ARRAYINIT_ELEMENT6]], ptr [[ARRAYINIT_ENDOFINIT7]], align 8
// CHECK2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[ARRAYINIT_ELEMENT6]], i32 noundef 4)
-// CHECK2-NEXT: to label [[INVOKE_CONT9:%.*]] unwind label [[LPAD8:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT9:%.*]] unwind label [[LPAD8:%.*]], !srcloc
// CHECK2: invoke.cont9:
// CHECK2-NEXT: [[ARRAYINIT_ELEMENT10:%.*]] = getelementptr inbounds [[STRUCT_S1]], ptr [[ARRAYINIT_ELEMENT6]], i64 1
// CHECK2-NEXT: store ptr [[ARRAYINIT_ELEMENT10]], ptr [[ARRAYINIT_ENDOFINIT7]], align 8
@@ -2023,7 +2023,7 @@ int foobar() {
// CHECK2-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_S1:%.*]], ptr [[TMP4]], i32 0, i32 0
// CHECK2-NEXT: [[TMP5:%.*]] = load i32, ptr [[A]], align 4
// CHECK2-NEXT: invoke void @_ZZ4mainEN5SmainC1Ei(ptr noundef nonnull align 8 dereferenceable(24) @_ZZ4mainE2sm, i32 noundef [[TMP5]])
-// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK2: invoke.cont:
// CHECK2-NEXT: [[TMP6:%.*]] = call i32 @__cxa_atexit(ptr @_ZZ4mainEN5SmainD1Ev, ptr @_ZZ4mainE2sm, ptr @__dso_handle) #[[ATTR3]]
// CHECK2-NEXT: call void @__cxa_guard_release(ptr @_ZGVZ4mainE2sm) #[[ATTR3]]
@@ -2446,7 +2446,7 @@ int foobar() {
// SIMD1-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8
// SIMD1-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// SIMD1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// SIMD1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// SIMD1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// SIMD1: invoke.cont:
// SIMD1-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// SIMD1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -2459,7 +2459,7 @@ int foobar() {
// SIMD1-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT]], align 8
// SIMD1-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// SIMD1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i32 noundef 4)
-// SIMD1-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]]
+// SIMD1-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]], !srcloc
// SIMD1: invoke.cont7:
// SIMD1-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// SIMD1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), i32 noundef 5)
@@ -2562,7 +2562,7 @@ int foobar() {
// SIMD1: init:
// SIMD1-NEXT: [[TMP2:%.*]] = load i32, ptr @_ZL3gs1, align 4
// SIMD1-NEXT: invoke void @_ZZ4mainEN5SmainC1Ei(ptr noundef nonnull align 8 dereferenceable(24) @_ZZ4mainE2sm, i32 noundef [[TMP2]])
-// SIMD1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// SIMD1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// SIMD1: invoke.cont:
// SIMD1-NEXT: [[TMP3:%.*]] = call i32 @__cxa_atexit(ptr @_ZZ4mainEN5SmainD1Ev, ptr @_ZZ4mainE2sm, ptr @__dso_handle) #[[ATTR3]]
// SIMD1-NEXT: call void @__cxa_guard_release(ptr @_ZGVZ4mainE2sm) #[[ATTR3]]
@@ -3439,7 +3439,7 @@ int foobar() {
// CHECK-TLS1-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK-TLS1-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK-TLS1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// CHECK-TLS1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-TLS1-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK-TLS1: invoke.cont:
// CHECK-TLS1-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK-TLS1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -3452,7 +3452,7 @@ int foobar() {
// CHECK-TLS1-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK-TLS1-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK-TLS1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i32 noundef 4)
-// CHECK-TLS1-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]]
+// CHECK-TLS1-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]], !srcloc
// CHECK-TLS1: invoke.cont7:
// CHECK-TLS1-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK-TLS1-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), i32 noundef 5)
@@ -4170,7 +4170,7 @@ int foobar() {
// CHECK-TLS2-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK-TLS2-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK-TLS2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// CHECK-TLS2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// CHECK-TLS2-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// CHECK-TLS2: invoke.cont:
// CHECK-TLS2-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// CHECK-TLS2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -4183,7 +4183,7 @@ int foobar() {
// CHECK-TLS2-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT]], align 8
// CHECK-TLS2-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK-TLS2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i32 noundef 4)
-// CHECK-TLS2-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]]
+// CHECK-TLS2-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]], !srcloc
// CHECK-TLS2: invoke.cont7:
// CHECK-TLS2-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// CHECK-TLS2-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), i32 noundef 5)
@@ -4513,7 +4513,7 @@ int foobar() {
// CHECK-TLS3-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8, !dbg [[DBG185:![0-9]+]]
// CHECK-TLS3-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8, !dbg [[DBG187:![0-9]+]]
// CHECK-TLS3-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// CHECK-TLS3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !dbg [[DBG188:![0-9]+]]
+// CHECK-TLS3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !dbg [[DBG188:![0-9]+]],
// CHECK-TLS3: invoke.cont:
// CHECK-TLS3-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8, !dbg [[DBG187]]
// CHECK-TLS3-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -5567,7 +5567,7 @@ int foobar() {
// SIMD3-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT]], align 8
// SIMD3-NEXT: store ptr @arr_x, ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// SIMD3-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) @arr_x, i32 noundef 1)
-// SIMD3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// SIMD3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// SIMD3: invoke.cont:
// SIMD3-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1:%.*]], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT1]], align 8
// SIMD3-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr @arr_x, i64 1), i32 noundef 2)
@@ -5580,7 +5580,7 @@ int foobar() {
// SIMD3-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT]], align 8
// SIMD3-NEXT: store ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// SIMD3-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i32 noundef 4)
-// SIMD3-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]]
+// SIMD3-NEXT: to label [[INVOKE_CONT7:%.*]] unwind label [[LPAD6:%.*]], !srcloc
// SIMD3: invoke.cont7:
// SIMD3-NEXT: store ptr getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), ptr [[ARRAYINIT_ENDOFINIT5]], align 8
// SIMD3-NEXT: invoke void @_ZN2S1C1Ei(ptr noundef nonnull align 4 dereferenceable(4) getelementptr inbounds ([[STRUCT_S1]], ptr getelementptr inbounds ([3 x %struct.S1], ptr @arr_x, i64 1), i64 1), i32 noundef 5)
@@ -5683,7 +5683,7 @@ int foobar() {
// SIMD3: init:
// SIMD3-NEXT: [[TMP2:%.*]] = load i32, ptr @_ZL3gs1, align 4
// SIMD3-NEXT: invoke void @_ZZ4mainEN5SmainC1Ei(ptr noundef nonnull align 8 dereferenceable(24) @_ZZ4mainE2sm, i32 noundef [[TMP2]])
-// SIMD3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]]
+// SIMD3-NEXT: to label [[INVOKE_CONT:%.*]] unwind label [[LPAD:%.*]], !srcloc
// SIMD3: invoke.cont:
// SIMD3-NEXT: [[TMP3:%.*]] = call i32 @__cxa_atexit(ptr @_ZZ4mainEN5SmainD1Ev, ptr @_ZZ4mainE2sm, ptr @__dso_handle) #[[ATTR3]]
// SIMD3-NEXT: call void @__cxa_guard_release(ptr @_ZGVZ4mainE2sm) #[[ATTR3]]
diff --git a/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected b/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
index 96370b4bec2d9..76e5361690ddf 100644
--- a/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
+++ b/clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
@@ -83,9 +83,9 @@ int main() {
// CHECK-NEXT: [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4
// CHECK-NEXT: store i32 0, ptr [[RETVAL]], align 4
// CHECK-NEXT: call void @_ZN3FooC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 1)
-// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2)
-// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3)
-// CHECK-NEXT: [[CALL2:%.*]] = call noundef i32 @_ZL18static_noinline_fni(i32 noundef 0)
+// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2), !srcloc [[META2:![0-9]+]]
+// CHECK-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3), !srcloc [[META3:![0-9]+]]
+// CHECK-NEXT: [[CALL2:%.*]] = call noundef i32 @_ZL18static_noinline_fni(i32 noundef 0), !srcloc [[META4:![0-9]+]]
// CHECK-NEXT: store i32 [[CALL2]], ptr [[RETVAL]], align 4
// CHECK-NEXT: call void @_ZN3FooD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[F]]) #[[ATTR2]]
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4
@@ -184,9 +184,9 @@ int main() {
// MACHO-NEXT: [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4
// MACHO-NEXT: store i32 0, ptr [[RETVAL]], align 4
// MACHO-NEXT: call void @_ZN3FooC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 1)
-// MACHO-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2)
-// MACHO-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3)
-// MACHO-NEXT: [[CALL2:%.*]] = call noundef i32 @_ZL18static_noinline_fni(i32 noundef 0)
+// MACHO-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2), !srcloc [[META2:![0-9]+]]
+// MACHO-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3), !srcloc [[META3:![0-9]+]]
+// MACHO-NEXT: [[CALL2:%.*]] = call noundef i32 @_ZL18static_noinline_fni(i32 noundef 0), !srcloc [[META4:![0-9]+]]
// MACHO-NEXT: store i32 [[CALL2]], ptr [[RETVAL]], align 4
// MACHO-NEXT: call void @_ZN3FooD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[F]]) #[[ATTR2]]
// MACHO-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4
@@ -239,9 +239,9 @@ int main() {
// MSVC-NEXT: [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4
// MSVC-NEXT: store i32 0, ptr [[RETVAL]], align 4
// MSVC-NEXT: [[CALL:%.*]] = call noundef ptr @"??0Foo@@QEAA at H@Z"(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 1)
-// MSVC-NEXT: [[CALL1:%.*]] = call noundef i32 @"?function_defined_inline at Foo@@QEBAHH at Z"(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2)
-// MSVC-NEXT: [[CALL2:%.*]] = call noundef i32 @"?function_defined_out_of_line at Foo@@QEBAHH at Z"(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3)
-// MSVC-NEXT: [[CALL3:%.*]] = call noundef i32 @"?static_noinline_fn@@YAHH at Z"(i32 noundef 0)
+// MSVC-NEXT: [[CALL1:%.*]] = call noundef i32 @"?function_defined_inline at Foo@@QEBAHH at Z"(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2), !srcloc [[META6:![0-9]+]]
+// MSVC-NEXT: [[CALL2:%.*]] = call noundef i32 @"?function_defined_out_of_line at Foo@@QEBAHH at Z"(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3), !srcloc [[META7:![0-9]+]]
+// MSVC-NEXT: [[CALL3:%.*]] = call noundef i32 @"?static_noinline_fn@@YAHH at Z"(i32 noundef 0), !srcloc [[META8:![0-9]+]]
// MSVC-NEXT: store i32 [[CALL3]], ptr [[RETVAL]], align 4
// MSVC-NEXT: call void @"??1Foo@@QEAA at XZ"(ptr noundef nonnull align 4 dereferenceable(4) [[F]]) #[[ATTR2:[0-9]+]]
// MSVC-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4
@@ -301,9 +301,9 @@ int main() {
// MINGW-NEXT: [[F:%.*]] = alloca [[CLASS_FOO:%.*]], align 4
// MINGW-NEXT: store i32 0, ptr [[RETVAL]], align 4
// MINGW-NEXT: call void @_ZN3FooC1Ei(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 1)
-// MINGW-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2)
-// MINGW-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3)
-// MINGW-NEXT: [[CALL2:%.*]] = call noundef i32 @_ZL18static_noinline_fni(i32 noundef 0)
+// MINGW-NEXT: [[CALL:%.*]] = call noundef i32 @_ZNK3Foo23function_defined_inlineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 2), !srcloc [[META6:![0-9]+]]
+// MINGW-NEXT: [[CALL1:%.*]] = call noundef i32 @_ZNK3Foo28function_defined_out_of_lineEi(ptr noundef nonnull align 4 dereferenceable(4) [[F]], i32 noundef 3), !srcloc [[META7:![0-9]+]]
+// MINGW-NEXT: [[CALL2:%.*]] = call noundef i32 @_ZL18static_noinline_fni(i32 noundef 0), !srcloc [[META8:![0-9]+]]
// MINGW-NEXT: store i32 [[CALL2]], ptr [[RETVAL]], align 4
// MINGW-NEXT: call void @_ZN3FooD1Ev(ptr noundef nonnull align 4 dereferenceable(4) [[F]]) #[[ATTR2]]
// MINGW-NEXT: [[TMP0:%.*]] = load i32, ptr [[RETVAL]], align 4
@@ -348,3 +348,20 @@ int main() {
// MINGW-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARG_ADDR]], align 4
// MINGW-NEXT: ret i32 [[TMP0]]
//
+//.
+// CHECK: [[META2]] = !{i64 1048}
+// CHECK: [[META3]] = !{i64 1080}
+// CHECK: [[META4]] = !{i64 1122}
+//.
+// MACHO: [[META2]] = !{i64 1048}
+// MACHO: [[META3]] = !{i64 1080}
+// MACHO: [[META4]] = !{i64 1122}
+//.
+// MSVC: [[META6]] = !{i64 1048}
+// MSVC: [[META7]] = !{i64 1080}
+// MSVC: [[META8]] = !{i64 1122}
+//.
+// MINGW: [[META6]] = !{i64 1048}
+// MINGW: [[META7]] = !{i64 1080}
+// MINGW: [[META8]] = !{i64 1122}
+//.
diff --git a/clang/test/utils/update_cc_test_checks/Inputs/explicit-template-instantiation.cpp.expected b/clang/test/utils/update_cc_test_checks/Inputs/explicit-template-instantiation.cpp.expected
index 2ed8693d181d7..8c0aaa0fa672a 100644
--- a/clang/test/utils/update_cc_test_checks/Inputs/explicit-template-instantiation.cpp.expected
+++ b/clang/test/utils/update_cc_test_checks/Inputs/explicit-template-instantiation.cpp.expected
@@ -44,7 +44,7 @@ public:
// CHECK-NEXT: store i8 [[X:%.*]], ptr [[X_ADDR]], align 1
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[X_ADDR]], align 1
-// CHECK-NEXT: call void @_ZN3FooIcEC2Ec(ptr noundef nonnull align 1 dereferenceable(1) [[THIS1]], i8 noundef signext [[TMP0]])
+// CHECK-NEXT: call void @_ZN3FooIcEC2Ec(ptr noundef nonnull align 1 dereferenceable(1) [[THIS1]], i8 noundef signext [[TMP0]]), !srcloc [[META2:![0-9]+]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3FooIcED1Ev(
@@ -52,7 +52,7 @@ public:
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
-// CHECK-NEXT: call void @_ZN3FooIcED2Ev(ptr noundef nonnull align 1 dereferenceable(1) [[THIS1]]) #[[ATTR1:[0-9]+]]
+// CHECK-NEXT: call void @_ZN3FooIcED2Ev(ptr noundef nonnull align 1 dereferenceable(1) [[THIS1]]) #[[ATTR1:[0-9]+]], !srcloc [[META3:![0-9]+]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3FooIcE3getEv(
@@ -86,7 +86,7 @@ template struct Foo<char>;
// CHECK-NEXT: store i16 [[X:%.*]], ptr [[X_ADDR]], align 2
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[X_ADDR]], align 2
-// CHECK-NEXT: call void @_ZN3FooIsEC2Es(ptr noundef nonnull align 2 dereferenceable(2) [[THIS1]], i16 noundef signext [[TMP0]])
+// CHECK-NEXT: call void @_ZN3FooIsEC2Es(ptr noundef nonnull align 2 dereferenceable(2) [[THIS1]], i16 noundef signext [[TMP0]]), !srcloc [[META2]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3FooIsED1Ev(
@@ -94,7 +94,7 @@ template struct Foo<char>;
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
-// CHECK-NEXT: call void @_ZN3FooIsED2Ev(ptr noundef nonnull align 2 dereferenceable(2) [[THIS1]]) #[[ATTR1]]
+// CHECK-NEXT: call void @_ZN3FooIsED2Ev(ptr noundef nonnull align 2 dereferenceable(2) [[THIS1]]) #[[ATTR1]], !srcloc [[META3]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3FooIsE3getEv(
@@ -131,7 +131,7 @@ template struct Foo<short>;
// CHECK-NEXT: store i32 [[X:%.*]], ptr [[X_ADDR]], align 4
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[X_ADDR]], align 4
-// CHECK-NEXT: call void @_ZN3BarIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]])
+// CHECK-NEXT: call void @_ZN3BarIiEC2Ei(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]], i32 noundef [[TMP0]]), !srcloc [[META5:![0-9]+]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3BarIiED1Ev(
@@ -139,7 +139,7 @@ template struct Foo<short>;
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
-// CHECK-NEXT: call void @_ZN3BarIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR1]]
+// CHECK-NEXT: call void @_ZN3BarIiED2Ev(ptr noundef nonnull align 4 dereferenceable(4) [[THIS1]]) #[[ATTR1]], !srcloc [[META3]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3BarIiE3getEv(
@@ -148,7 +148,7 @@ template struct Foo<short>;
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[FOO:%.*]] = getelementptr inbounds nuw [[STRUCT_BAR:%.*]], ptr [[THIS1]], i32 0, i32 0
-// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN3FooIiE3getEv(ptr noundef nonnull align 4 dereferenceable(4) [[FOO]])
+// CHECK-NEXT: [[CALL:%.*]] = call noundef i32 @_ZN3FooIiE3getEv(ptr noundef nonnull align 4 dereferenceable(4) [[FOO]]), !srcloc [[META6:![0-9]+]]
// CHECK-NEXT: ret i32 [[CALL]]
//
// CHECK-LABEL: @_ZN3BarIiE3setEi(
@@ -160,7 +160,7 @@ template struct Foo<short>;
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[FOO:%.*]] = getelementptr inbounds nuw [[STRUCT_BAR:%.*]], ptr [[THIS1]], i32 0, i32 0
// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[_X_ADDR]], align 4
-// CHECK-NEXT: call void @_ZN3FooIiE3setEi(ptr noundef nonnull align 4 dereferenceable(4) [[FOO]], i32 noundef [[TMP0]])
+// CHECK-NEXT: call void @_ZN3FooIiE3setEi(ptr noundef nonnull align 4 dereferenceable(4) [[FOO]], i32 noundef [[TMP0]]), !srcloc [[META7:![0-9]+]]
// CHECK-NEXT: ret void
//
template struct Bar<int>;
@@ -176,7 +176,7 @@ template struct Bar<int>;
// CHECK-NEXT: store i64 [[X:%.*]], ptr [[X_ADDR]], align 8
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[X_ADDR]], align 8
-// CHECK-NEXT: call void @_ZN3BazIlEC2El(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]], i64 noundef [[TMP0]])
+// CHECK-NEXT: call void @_ZN3BazIlEC2El(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]], i64 noundef [[TMP0]]), !srcloc [[META9:![0-9]+]]
// CHECK-NEXT: ret void
//
// CHECK-LABEL: @_ZN3BazIlED1Ev(
@@ -184,7 +184,7 @@ template struct Bar<int>;
// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
// CHECK-NEXT: store ptr [[THIS:%.*]], ptr [[THIS_ADDR]], align 8
// CHECK-NEXT: [[THIS1:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
-// CHECK-NEXT: call void @_ZN3BazIlED2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]]) #[[ATTR1]]
+// CHECK-NEXT: call void @_ZN3BazIlED2Ev(ptr noundef nonnull align 8 dereferenceable(8) [[THIS1]]) #[[ATTR1]], !srcloc [[META3]]
// CHECK-NEXT: ret void
//
template struct Baz<long>;
More information about the cfe-commits
mailing list