[Lldb-commits] [clang] [lldb] [lldb][clang][NFC] Remove DeclContext's UseQualifiedLookup bit (PR #229005)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Oct 5 01:20:44 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-modules
Author: Raphael Isemann (Teemperor)
<details>
<summary>Changes</summary>
LLDB's expression parser needs to know whether Sema is performing a qualified name lookup (e.g. '::A') so that it only considers root namespaces in that case. This was done by checking the UseQualifiedLookup bit in DeclContext, which Sema::LookupQualifiedName sets for the duration of the lookup.
This patch gets removes bit by moving the tracking into LLDB. Sema now reports whether we a qualified lookup started/stopped via a callback to the ExternalSemaSource, and LLDB tracks this state in a small set.
---
Full diff: https://github.com/llvm/llvm-project/pull/229005.diff
10 Files Affected:
- (modified) clang/include/clang/AST/DeclBase.h (+1-15)
- (modified) clang/include/clang/Sema/ExternalSemaSource.h (+9)
- (modified) clang/include/clang/Sema/MultiplexExternalSemaSource.h (+4)
- (modified) clang/lib/AST/DeclBase.cpp (-1)
- (modified) clang/lib/Sema/MultiplexExternalSemaSource.cpp (+12)
- (modified) clang/lib/Sema/SemaLookup.cpp (+10-8)
- (modified) clang/lib/Serialization/ASTWriterDecl.cpp (+9-9)
- (modified) lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h (+22)
- (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp (+1-2)
- (modified) lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h (+33-1)
``````````diff
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 8ea2533825dd9..3ca8603b73d21 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1520,16 +1520,10 @@ class DeclContext {
/// that are missing from the lookup table.
LLVM_PREFERRED_TYPE(bool)
mutable uint64_t HasLazyExternalLexicalLookups : 1;
-
- /// If \c true, lookups should only return identifier from
- /// DeclContext scope (for example TranslationUnit). Used in
- /// LookupQualifiedName()
- LLVM_PREFERRED_TYPE(bool)
- mutable uint64_t UseQualifiedLookup : 1;
};
/// Number of bits in DeclContextBitfields.
- enum { NumDeclContextBits = 13 };
+ enum { NumDeclContextBits = 12 };
/// Stores the bits used by NamespaceDecl.
/// If modified NumNamespaceDeclBits and the accessor
@@ -2766,14 +2760,6 @@ class DeclContext {
D == LastDecl);
}
- void setUseQualifiedLookup(bool use = true) const {
- DeclContextBits.UseQualifiedLookup = use;
- }
-
- bool shouldUseQualifiedLookup() const {
- return DeclContextBits.UseQualifiedLookup;
- }
-
static bool classof(const Decl *D);
static bool classof(const DeclContext *D) { return true; }
diff --git a/clang/include/clang/Sema/ExternalSemaSource.h b/clang/include/clang/Sema/ExternalSemaSource.h
index 0122beff53df9..022294e9dbee3 100644
--- a/clang/include/clang/Sema/ExternalSemaSource.h
+++ b/clang/include/clang/Sema/ExternalSemaSource.h
@@ -240,6 +240,15 @@ class ExternalSemaSource : public ExternalASTSource {
return false;
}
+ /// Notify the external source that Sema started a qualified name lookup
+ /// into \p DC (e.g. the lookup of \c B in \c A::B or of \c A in \c ::A).
+ virtual void StartedQualifiedLookup(const DeclContext *DC) {}
+
+ /// Notify the external source that Sema finished the qualified name lookup
+ /// into \p DC that was started by the last call to
+ /// \c StartedQualifiedLookup.
+ virtual void FinishedQualifiedLookup(const DeclContext *DC) {}
+
/// LLVM-style RTTI.
/// \{
bool isA(const void *ClassID) const override {
diff --git a/clang/include/clang/Sema/MultiplexExternalSemaSource.h b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
index 8e25b6266d9ad..ad75a1d97d418 100644
--- a/clang/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/clang/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -392,6 +392,10 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
bool MaybeDiagnoseMissingCompleteType(SourceLocation Loc,
QualType T) override;
+ void StartedQualifiedLookup(const DeclContext *DC) override;
+
+ void FinishedQualifiedLookup(const DeclContext *DC) override;
+
/// LLVM-style RTTI.
/// \{
bool isA(const void *ClassID) const override {
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 548643cea2cce..226229bcb622f 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1315,7 +1315,6 @@ DeclContext::DeclContext(Decl::Kind K) {
setNeedToReconcileExternalVisibleStorage(false);
setHasLazyLocalLexicalLookups(false);
setHasLazyExternalLexicalLookups(false);
- setUseQualifiedLookup(false);
}
bool DeclContext::classof(const Decl *D) {
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 6f6ea9f0df261..bf2b19e143a4d 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -370,3 +370,15 @@ bool MultiplexExternalSemaSource::MaybeDiagnoseMissingCompleteType(
}
return false;
}
+
+void MultiplexExternalSemaSource::StartedQualifiedLookup(
+ const DeclContext *DC) {
+ for (size_t I = 0, E = Sources.size(); I < E; ++I)
+ Sources[I]->StartedQualifiedLookup(DC);
+}
+
+void MultiplexExternalSemaSource::FinishedQualifiedLookup(
+ const DeclContext *DC) {
+ for (size_t I = 0, E = Sources.size(); I < E; ++I)
+ Sources[I]->FinishedQualifiedLookup(DC);
+}
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index bc8a30d4e9dad..75cad0bb433f8 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -2445,18 +2445,20 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx,
llvm_unreachable("Declaration context must already be complete!");
#endif
+ // Inform the external source that we're looking for a qualified name.
struct QualifiedLookupInScope {
- bool oldVal;
- DeclContext *Context;
- // Set flag in DeclContext informing debugger that we're looking for qualified name
- QualifiedLookupInScope(DeclContext *ctx)
- : oldVal(ctx->shouldUseQualifiedLookup()), Context(ctx) {
- ctx->setUseQualifiedLookup();
+ ExternalSemaSource *Source;
+ const DeclContext *Context;
+ QualifiedLookupInScope(ExternalSemaSource *Source, const DeclContext *Ctx)
+ : Source(Source), Context(Ctx) {
+ if (Source)
+ Source->StartedQualifiedLookup(Context);
}
~QualifiedLookupInScope() {
- Context->setUseQualifiedLookup(oldVal);
+ if (Source)
+ Source->FinishedQualifiedLookup(Context);
}
- } QL(LookupCtx);
+ } QL(ExternalSource.get(), LookupCtx);
CXXRecordDecl *LookupRec = dyn_cast<CXXRecordDecl>(LookupCtx);
// FIXME: Per [temp.dep.general]p2, an unqualified name is also dependent
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 2f5b9ed925097..75be3ea7ee390 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -626,7 +626,7 @@ void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) {
}
void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
- static_assert(DeclContext::NumTagDeclBits == 23,
+ static_assert(DeclContext::NumTagDeclBits == 22,
"You need to update the serializer after you change the "
"TagDeclBits");
@@ -656,7 +656,7 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) {
}
void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
- static_assert(DeclContext::NumEnumDeclBits == 43,
+ static_assert(DeclContext::NumEnumDeclBits == 42,
"You need to update the serializer after you change the "
"EnumDeclBits");
@@ -699,7 +699,7 @@ void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) {
}
void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) {
- static_assert(DeclContext::NumRecordDeclBits == 64,
+ static_assert(DeclContext::NumRecordDeclBits == 63,
"You need to update the serializer after you change the "
"RecordDeclBits");
@@ -771,7 +771,7 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {
}
void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
- static_assert(DeclContext::NumFunctionDeclBits == 45,
+ static_assert(DeclContext::NumFunctionDeclBits == 44,
"You need to update the serializer after you change the "
"FunctionDeclBits");
@@ -954,7 +954,7 @@ void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) {
}
void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) {
- static_assert(DeclContext::NumObjCMethodDeclBits == 37,
+ static_assert(DeclContext::NumObjCMethodDeclBits == 36,
"You need to update the serializer after you change the "
"ObjCMethodDeclBits");
@@ -1509,7 +1509,7 @@ void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) {
}
void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) {
- static_assert(DeclContext::NumLinkageSpecDeclBits == 17,
+ static_assert(DeclContext::NumLinkageSpecDeclBits == 16,
"You need to update the serializer after you change the"
"LinkageSpecDeclBits");
@@ -1767,7 +1767,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
}
void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) {
- static_assert(DeclContext::NumCXXConstructorDeclBits == 64,
+ static_assert(DeclContext::NumCXXConstructorDeclBits == 63,
"You need to update the serializer after you change the "
"CXXConstructorDeclBits");
@@ -2252,7 +2252,7 @@ void ASTDeclWriter::VisitCXXExpansionStmtDecl(CXXExpansionStmtDecl *D) {
/// Emit the DeclContext part of a declaration context decl.
void ASTDeclWriter::VisitDeclContext(DeclContext *DC) {
- static_assert(DeclContext::NumDeclContextBits == 13,
+ static_assert(DeclContext::NumDeclContextBits == 12,
"You need to update the serializer after you change the "
"DeclContextBits");
LookupBlockOffsets Offsets;
@@ -2378,7 +2378,7 @@ void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
}
void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) {
- static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 15,
+ static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 14,
"You need to update the serializer after you change the "
"NumOMPDeclareReductionDeclBits");
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
index fb4e2331a5cb9..3529bb03b5d89 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTUtils.h
@@ -153,6 +153,18 @@ class ExternalASTSourceWrapper : public clang::ExternalSemaSource {
BaseOffsets, VirtualBaseOffsets);
}
+ void StartedQualifiedLookup(const clang::DeclContext *DC) override {
+ if (auto *sema_source =
+ llvm::dyn_cast<clang::ExternalSemaSource>(m_Source.get()))
+ sema_source->StartedQualifiedLookup(DC);
+ }
+
+ void FinishedQualifiedLookup(const clang::DeclContext *DC) override {
+ if (auto *sema_source =
+ llvm::dyn_cast<clang::ExternalSemaSource>(m_Source.get()))
+ sema_source->FinishedQualifiedLookup(DC);
+ }
+
/// This gets called when Sema is reconciling undefined but used decls.
/// For LLDB's use-case, we never provide Clang with function definitions,
/// instead we rely on linkage names and symbol resolution to call the
@@ -634,6 +646,16 @@ class SemaSourceWithPriorities : public clang::ExternalSemaSource {
}
return false;
}
+
+ void StartedQualifiedLookup(const clang::DeclContext *DC) override {
+ for (auto &Source : Sources)
+ Source->StartedQualifiedLookup(DC);
+ }
+
+ void FinishedQualifiedLookup(const clang::DeclContext *DC) override {
+ for (auto &Source : Sources)
+ Source->FinishedQualifiedLookup(DC);
+ }
};
} // namespace lldb_private
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
index 2361e4923943e..a96f22bff93d1 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp
@@ -686,8 +686,7 @@ void ClangASTSource::FillNamespaceMap(
// disambiguation for function calls are handled separately in
// SearchFunctionsInSymbolContexts.
const bool find_root_namespaces =
- context.m_decl_context &&
- context.m_decl_context->shouldUseQualifiedLookup();
+ context.m_decl_context && IsInQualifiedLookup(context.m_decl_context);
found_namespace_decl = symbol_file->FindNamespace(
name, namespace_decl, /* only root namespaces */ find_root_namespaces);
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
index 33edc2d1eecc7..cdae1cc524e6d 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.h
@@ -17,8 +17,11 @@
#include "lldb/Target/Target.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/IdentifierTable.h"
+#include "clang/Sema/ExternalSemaSource.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
namespace lldb_private {
@@ -202,12 +205,31 @@ class ClangASTSource : public clang::ExternalASTSource,
}
bool GetLookupsEnabled() { return m_lookups_enabled; }
+ /// Called by Sema when it starts a qualified name lookup into \p DC.
+ void StartedQualifiedLookup(const clang::DeclContext *DC) {
+ m_qualified_lookup_contexts.push_back(DC);
+ }
+
+ /// Called by Sema when it finishes a qualified name lookup into \p DC.
+ void FinishedQualifiedLookup(const clang::DeclContext *DC) {
+ assert(!m_qualified_lookup_contexts.empty() &&
+ m_qualified_lookup_contexts.back() == DC &&
+ "Unbalanced qualified lookup notifications");
+ m_qualified_lookup_contexts.pop_back();
+ }
+
+ /// Returns true if Sema is currently performing a qualified name lookup
+ /// into \p DC.
+ bool IsInQualifiedLookup(const clang::DeclContext *DC) const {
+ return llvm::is_contained(m_qualified_lookup_contexts, DC);
+ }
+
/// \class ClangASTSourceProxy ClangASTSource.h
/// "lldb/Expression/ClangASTSource.h" Proxy for ClangASTSource
///
/// Clang AST contexts like to own their AST sources, so this is a state-
/// free proxy object.
- class ClangASTSourceProxy : public clang::ExternalASTSource {
+ class ClangASTSourceProxy : public clang::ExternalSemaSource {
public:
ClangASTSourceProxy(ClangASTSource &original) : m_original(original) {}
@@ -247,6 +269,14 @@ class ClangASTSource : public clang::ExternalASTSource,
return m_original.StartTranslationUnit(Consumer);
}
+ void StartedQualifiedLookup(const clang::DeclContext *DC) override {
+ m_original.StartedQualifiedLookup(DC);
+ }
+
+ void FinishedQualifiedLookup(const clang::DeclContext *DC) override {
+ m_original.FinishedQualifiedLookup(DC);
+ }
+
private:
ClangASTSource &m_original;
};
@@ -393,6 +423,8 @@ class ClangASTSource : public clang::ExternalASTSource,
std::shared_ptr<ClangASTImporter> m_ast_importer_sp;
std::set<const clang::Decl *> m_active_lexical_decls;
std::set<const char *> m_active_lookups;
+ /// The DeclContexts Sema is currently performing a qualified lookup into.
+ llvm::SmallVector<const clang::DeclContext *, 2> m_qualified_lookup_contexts;
};
} // namespace lldb_private
``````````
</details>
https://github.com/llvm/llvm-project/pull/229005
More information about the lldb-commits
mailing list