[clang] [clang-tools-extra] [clang] Do not cache variable linkage before type deduction (PR #221474)
Vedran Miletić via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 5 11:17:14 PDT 2026
https://github.com/vedranmiletic updated https://github.com/llvm/llvm-project/pull/221474
>From a5a5dd45ba810c8fb30ca56b8f11bf59146253ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vedran=20Mileti=C4=87?= <vedran at miletic.net>
Date: Sun, 2 Aug 2026 20:15:23 +0200
Subject: [PATCH] [clang] Do not cache variable linkage before type deduction
The linkage of a variable can depend on its deduced type. Avoid caching
linkage while the type is still undeduced so early queries cannot leave
a stale result.
Fixes #22203
Fixes #200597
Assisted-by: Codex (OpenAI ChatGPT)
---
.../clangd/test/crash-auto-lambda-linkage.test | 12 ++++++++++++
clang/lib/AST/Decl.cpp | 6 ++++++
clang/test/SemaCXX/crash-auto-lambda-linkage.cpp | 4 ++++
clang/test/SemaCXX/reserved-identifier.cpp | 2 ++
.../SemaCXX/warn-missing-variable-declarations.cpp | 5 +++++
5 files changed, 29 insertions(+)
create mode 100644 clang-tools-extra/clangd/test/crash-auto-lambda-linkage.test
create mode 100644 clang/test/SemaCXX/crash-auto-lambda-linkage.cpp
diff --git a/clang-tools-extra/clangd/test/crash-auto-lambda-linkage.test b/clang-tools-extra/clangd/test/crash-auto-lambda-linkage.test
new file mode 100644
index 0000000000000..f8a3d63800f8b
--- /dev/null
+++ b/clang-tools-extra/clangd/test/crash-auto-lambda-linkage.test
@@ -0,0 +1,12 @@
+# RUN: clangd -lit-test < %s
+# https://github.com/llvm/llvm-project/issues/200597
+
+{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{},"trace":"off"}}
+---
+{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"uri":"test:///main.cpp","languageId":"cpp","version":1,"text":"auto a = [] {\n\n"}}}
+---
+{"jsonrpc":"2.0","id":1,"method":"textDocument/completion","params":{"textDocument":{"uri":"test:///main.cpp"},"position":{"line":1,"character":0}}}
+---
+{"jsonrpc":"2.0","id":2,"method":"shutdown"}
+---
+{"jsonrpc":"2.0","method":"exit"}
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a620e9f211ca6..5514a90689050 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1591,6 +1591,12 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
return *LI;
LinkageInfo LV = computeLVForDecl(D, computation);
+
+ // A variable's linkage may depend on its deduced type.
+ if (const auto *VD = dyn_cast<VarDecl>(D);
+ VD && VD->getType()->isUndeducedType())
+ return LV;
+
if (D->hasCachedLinkage())
assert(D->getCachedLinkage() == LV.getLinkage());
diff --git a/clang/test/SemaCXX/crash-auto-lambda-linkage.cpp b/clang/test/SemaCXX/crash-auto-lambda-linkage.cpp
new file mode 100644
index 0000000000000..def91d820e558
--- /dev/null
+++ b/clang/test/SemaCXX/crash-auto-lambda-linkage.cpp
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// https://github.com/llvm/llvm-project/issues/22203
+auto g = [] { virtual g() // expected-error {{a type specifier is required for all declarations}} expected-warning {{empty parentheses interpreted as a function declaration}} expected-note {{replace parentheses with an initializer to declare a variable}} expected-error {{expected ';' at end of declaration}} expected-error {{expected '}'}} expected-note {{to match this '{'}} expected-error {{expected ';' after top level declarator}}
diff --git a/clang/test/SemaCXX/reserved-identifier.cpp b/clang/test/SemaCXX/reserved-identifier.cpp
index a3e6d8ead61fd..b1ac3653a088d 100644
--- a/clang/test/SemaCXX/reserved-identifier.cpp
+++ b/clang/test/SemaCXX/reserved-identifier.cpp
@@ -113,4 +113,6 @@ namespace N {
extern "C" int _namespace_b; // expected-warning {{identifier '_namespace_b' is reserved because it starts with '_' and has C language linkage}}
void _namespace_c();
extern "C" void _namespace_d(); // expected-warning {{identifier '_namespace_d' is reserved because it starts with '_' and has C language linkage}}
+ auto _namespace_e = []{}; // no-warning
+ auto _namespace_f = 0; // no-warning
}
diff --git a/clang/test/SemaCXX/warn-missing-variable-declarations.cpp b/clang/test/SemaCXX/warn-missing-variable-declarations.cpp
index b50eeed30e7ae..b2183aaa8243a 100644
--- a/clang/test/SemaCXX/warn-missing-variable-declarations.cpp
+++ b/clang/test/SemaCXX/warn-missing-variable-declarations.cpp
@@ -83,3 +83,8 @@ template<> int var_template<int[5]>; // expected-warning {{no previous extern de
// the linkage from the template! We should not warn here.
template<> int static_var_template<int[5]>; // expected-warning {{no previous extern declaration}}
// expected-note at -1{{declare 'static' if the variable is not intended to be used outside of this translation unit}}
+
+namespace deduced {
+ auto lambda_a = []{}; // no-warning
+ auto _lambda_b = []{}; // no-warning
+}
More information about the cfe-commits
mailing list