summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h9
-rw-r--r--lldb/include/lldb/Symbol/CompilerDeclContext.h15
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h3
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/Makefile5
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/TestInlineNamespace.py26
-rw-r--r--lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/main.cpp10
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp7
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp2
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp29
-rw-r--r--lldb/source/Symbol/CompilerDeclContext.cpp13
10 files changed, 108 insertions, 11 deletions
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index efa369bcfc0..23a0cffb0cf 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -354,11 +354,13 @@ public:
//------------------------------------------------------------------
clang::NamespaceDecl *
- GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx);
+ GetUniqueNamespaceDeclaration(const char *name, clang::DeclContext *decl_ctx,
+ bool is_inline = false);
static clang::NamespaceDecl *
GetUniqueNamespaceDeclaration(clang::ASTContext *ast, const char *name,
- clang::DeclContext *decl_ctx);
+ clang::DeclContext *decl_ctx,
+ bool is_inline = false);
//------------------------------------------------------------------
// Function Types
@@ -506,6 +508,9 @@ public:
bool *is_instance_method_ptr,
ConstString *language_object_name_ptr) override;
+ bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
+ void *other_opaque_decl_ctx) override;
+
//----------------------------------------------------------------------
// Clang specific clang::DeclContext functions
//----------------------------------------------------------------------
diff --git a/lldb/include/lldb/Symbol/CompilerDeclContext.h b/lldb/include/lldb/Symbol/CompilerDeclContext.h
index 92c5d3ce127..e26d373a5ba 100644
--- a/lldb/include/lldb/Symbol/CompilerDeclContext.h
+++ b/lldb/include/lldb/Symbol/CompilerDeclContext.h
@@ -76,6 +76,21 @@ public:
ConstString *language_object_name_ptr);
//----------------------------------------------------------------------
+ /// Check if the given other decl context is contained in the lookup
+ /// of this decl context (for example because the other context is a nested
+ /// inline namespace).
+ ///
+ /// @param[in] other
+ /// The other decl context for which we should check if it is contained
+ /// in the lookoup of this context.
+ ///
+ /// @return
+ /// Returns true iff the other decl context is contained in the lookup
+ /// of this decl context.
+ //----------------------------------------------------------------------
+ bool IsContainedInLookup(CompilerDeclContext other) const;
+
+ //----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index 29b943eff6f..a24e350cfc7 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -132,6 +132,9 @@ public:
void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
bool *is_instance_method_ptr, ConstString *language_object_name_ptr) = 0;
+ virtual bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
+ void *other_opaque_decl_ctx) = 0;
+
//----------------------------------------------------------------------
// Tests
//----------------------------------------------------------------------
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/Makefile
new file mode 100644
index 00000000000..8a7102e347a
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/Makefile
@@ -0,0 +1,5 @@
+LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/TestInlineNamespace.py b/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/TestInlineNamespace.py
new file mode 100644
index 00000000000..b17115be292
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/TestInlineNamespace.py
@@ -0,0 +1,26 @@
+"""
+Test that we correctly handle inline namespaces.
+"""
+
+import lldb
+
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestInlineNamespace(TestBase):
+ mydir = TestBase.compute_mydir(__file__)
+
+ def test(self):
+ self.build()
+
+ lldbutil.run_to_source_breakpoint(self,
+ "// Set break point at this line.", lldb.SBFileSpec("main.cpp"))
+
+ # The 'A::B::f' function must be found via 'A::f' as 'B' is an inline
+ # namespace.
+ self.expect("expr A::f()", substrs=['$0 = 3'])
+ # But we should still find the function when we pretend the inline
+ # namespace is not inline.
+ self.expect("expr A::B::f()", substrs=['$1 = 3'])
diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/main.cpp b/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/main.cpp
new file mode 100644
index 00000000000..c10b361a0cd
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/expression_command/inline-namespace/main.cpp
@@ -0,0 +1,10 @@
+namespace A {
+ inline namespace B {
+ int f() { return 3; }
+ };
+}
+
+int main(int argc, char **argv) {
+ // Set break point at this line.
+ return A::f();
+}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index aa759c4533d..1d2398ccc0b 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -3798,8 +3798,11 @@ DWARFASTParserClang::ResolveNamespaceDIE(const DWARFDIE &die) {
const char *namespace_name = die.GetName();
clang::DeclContext *containing_decl_ctx =
GetClangDeclContextContainingDIE(die, nullptr);
- namespace_decl = m_ast.GetUniqueNamespaceDeclaration(namespace_name,
- containing_decl_ctx);
+ bool is_inline =
+ die.GetAttributeValueAsUnsigned(DW_AT_export_symbols, 0) != 0;
+
+ namespace_decl = m_ast.GetUniqueNamespaceDeclaration(
+ namespace_name, containing_decl_ctx, is_inline);
Log *log =
nullptr; // (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO));
if (log) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 61c270fa2fa..0b789fd0c7c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -2239,7 +2239,7 @@ bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext *decl_ctx,
CompilerDeclContext actual_decl_ctx =
dwarf_ast->GetDeclContextContainingUIDFromDWARF(die);
if (actual_decl_ctx)
- return actual_decl_ctx == *decl_ctx;
+ return decl_ctx->IsContainedInLookup(actual_decl_ctx);
}
}
return false;
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index 089f67115f3..28b5a184b42 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -1893,9 +1893,8 @@ ClangASTContext::GetNumBaseClasses(const CXXRecordDecl *cxx_record_decl,
#pragma mark Namespace Declarations
-NamespaceDecl *
-ClangASTContext::GetUniqueNamespaceDeclaration(const char *name,
- DeclContext *decl_ctx) {
+NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
+ const char *name, DeclContext *decl_ctx, bool is_inline) {
NamespaceDecl *namespace_decl = nullptr;
ASTContext *ast = getASTContext();
TranslationUnitDecl *translation_unit_decl = ast->getTranslationUnitDecl();
@@ -1913,7 +1912,7 @@ ClangASTContext::GetUniqueNamespaceDeclaration(const char *name,
}
namespace_decl =
- NamespaceDecl::Create(*ast, decl_ctx, false, SourceLocation(),
+ NamespaceDecl::Create(*ast, decl_ctx, is_inline, SourceLocation(),
SourceLocation(), &identifier_info, nullptr);
decl_ctx->addDecl(namespace_decl);
@@ -1954,12 +1953,13 @@ ClangASTContext::GetUniqueNamespaceDeclaration(const char *name,
}
NamespaceDecl *ClangASTContext::GetUniqueNamespaceDeclaration(
- clang::ASTContext *ast, const char *name, clang::DeclContext *decl_ctx) {
+ clang::ASTContext *ast, const char *name, clang::DeclContext *decl_ctx,
+ bool is_inline) {
ClangASTContext *ast_ctx = ClangASTContext::GetASTContext(ast);
if (ast_ctx == nullptr)
return nullptr;
- return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx);
+ return ast_ctx->GetUniqueNamespaceDeclaration(name, decl_ctx, is_inline);
}
clang::BlockDecl *
@@ -10264,6 +10264,23 @@ bool ClangASTContext::DeclContextIsClassMethod(
return false;
}
+bool ClangASTContext::DeclContextIsContainedInLookup(
+ void *opaque_decl_ctx, void *other_opaque_decl_ctx) {
+ auto *decl_ctx = (clang::DeclContext *)opaque_decl_ctx;
+ auto *other = (clang::DeclContext *)other_opaque_decl_ctx;
+
+ do {
+ // A decl context always includes its own contents in its lookup.
+ if (decl_ctx == other)
+ return true;
+
+ // If we have an inline namespace, then the lookup of the parent context
+ // also includes the inline namespace contents.
+ } while (other->isInlineNamespace() && (other = other->getParent()));
+
+ return false;
+}
+
clang::DeclContext *
ClangASTContext::DeclContextGetAsDeclContext(const CompilerDeclContext &dc) {
if (dc.IsClang())
diff --git a/lldb/source/Symbol/CompilerDeclContext.cpp b/lldb/source/Symbol/CompilerDeclContext.cpp
index a8fa7e2d339..a6f046c4eb2 100644
--- a/lldb/source/Symbol/CompilerDeclContext.cpp
+++ b/lldb/source/Symbol/CompilerDeclContext.cpp
@@ -59,6 +59,19 @@ bool CompilerDeclContext::IsClassMethod(lldb::LanguageType *language_ptr,
return false;
}
+bool CompilerDeclContext::IsContainedInLookup(CompilerDeclContext other) const {
+ if (!IsValid())
+ return false;
+
+ // If the other context is just the current context, we don't need to go
+ // over the type system to know that the lookup is identical.
+ if (this == &other)
+ return true;
+
+ return m_type_system->DeclContextIsContainedInLookup(m_opaque_decl_ctx,
+ other.m_opaque_decl_ctx);
+}
+
bool lldb_private::operator==(const lldb_private::CompilerDeclContext &lhs,
const lldb_private::CompilerDeclContext &rhs) {
return lhs.GetTypeSystem() == rhs.GetTypeSystem() &&
OpenPOWER on IntegriCloud