forked from OSchip/llvm-project
Correctly look up declarations in inline namespaces
Summary: This patch marks the inline namespaces from DWARF as inline and also ensures that looking up declarations now follows the lookup rules for inline namespaces. Reviewers: aprantl, shafik, serge-sans-paille Reviewed By: aprantl Subscribers: eraman, jdoerfert, lldb-commits Tags: #c_modules_in_lldb, #lldb Differential Revision: https://reviews.llvm.org/D59198 llvm-svn: 355897
This commit is contained in:
parent
21347b2901
commit
a946997c24
|
@ -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
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -75,6 +75,21 @@ public:
|
|||
bool *is_instance_method_ptr,
|
||||
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
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
LEVEL = ../../make
|
||||
|
||||
CXX_SOURCES := main.cpp
|
||||
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -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'])
|
|
@ -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();
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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() &&
|
||||
|
|
Loading…
Reference in New Issue