Files
clang-p2996/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h
Sean Callanan b494578afb [DWARF] Fix lookup in the abstract origins of inlined blocks/functions
LLDB uses clang::DeclContexts for lookups, and variables get put into
the DeclContext for their abstract origin. (The abstract origin is a 
DWARF pointer that indicates the unique definition of inlined code.) 
When the expression parser is looking for variables, it locates the 
DeclContext for the current context. This needs to be done carefully, 
though, e.g.:

__attribute__ ((always_inline)) void f(int a) {
  {
    int b = a * 2;
  }
}

void g() {
  f(3);
}
Here, if we're stopped in the inlined copy of f, we have to find the 
DeclContext corresponding to the definition of f – its abstract 
origin. Clang doesn't allow multiple functions with the same name and 
arguments to exist. It also means that any variables we see must be 
placed in the appropriate DeclContext.

[Bug 1]: When stopped in an inline block, the function 
GetDeclContextDIEContainingDIE for that block doesn't properly
construct a DeclContext for the abstract origin for inlined
subroutines. That means we get duplicated function DeclContexts, but
function arguments only get put in the abstract origin's DeclContext, 
and as a result when we try to look for them in nested contexts they 
aren't found.

[Bug 2]: When stopped in an inline block, the DWARF (for space 
reasons) doesn't explicitly point to the abstract origin for that 
block. This means that the function GetClangDeclContextForDIE returns
a different DeclContext for each place the block is inlined. However, 
any variables defined in the block have abstract origins, so they 
will only get placed in the DeclContext for their abstract origin.

In this fix, I've introduced a test covering both of these issues,
and fixed them.

Bug 1 could be resolved simply by making sure we look up the abstract
origin for inlined functions when looking up their DeclContexts on 
behalf of nested blocks.

For Bug 2, I've implemented an algorithm that makes the DeclContext 
for a block be the containing DeclContext for the closest entity we
would find during lookup that has an abstract origin pointer. That
means that in the following situation:

{ // block 1
  int a;
  { // block 2
    int b;
  }
}
if we looked up the DeclContext for block 2, we'd find the block 
containing the abstract origin of b, and lookup would proceed 
correctly because we'd see b and a. However, in the situation

{ // block 1
  int a;
  { // block 2
  }
}
since there isn't anything to look up in block 2, we can't determine 
its abstract origin (and there is no such pointer in the DWARF for 
blocks). However, we can walk up the parent chain and find a, and its 
abstract origin lives in the abstract origin of block 1. So we simply 
say that the DeclContext for block 2 is the same as the DeclContext 
for block 1, which contains a. Lookups will return the same results.

Thanks to Jim Ingham for review and suggestions.

Differential revision: https://reviews.llvm.org/D32375

llvm-svn: 301263
2017-04-24 22:11:10 +00:00

162 lines
6.4 KiB
C++

//===-- DWARFASTParserClang.h -----------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef SymbolFileDWARF_DWARFASTParserClang_h_
#define SymbolFileDWARF_DWARFASTParserClang_h_
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "clang/AST/CharUnits.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
// Project includes
#include "DWARFASTParser.h"
#include "DWARFDefines.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangASTImporter.h"
class DWARFDebugInfoEntry;
class DWARFDIECollection;
class DWARFASTParserClang : public DWARFASTParser {
public:
DWARFASTParserClang(lldb_private::ClangASTContext &ast);
~DWARFASTParserClang() override;
// DWARFASTParser interface.
lldb::TypeSP ParseTypeFromDWARF(const lldb_private::SymbolContext &sc,
const DWARFDIE &die, lldb_private::Log *log,
bool *type_is_new_ptr) override;
lldb_private::Function *
ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc,
const DWARFDIE &die) override;
bool
CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type,
lldb_private::CompilerType &compiler_type) override;
lldb_private::CompilerDecl
GetDeclForUIDFromDWARF(const DWARFDIE &die) override;
std::vector<DWARFDIE>
GetDIEForDeclContext(lldb_private::CompilerDeclContext decl_context) override;
lldb_private::CompilerDeclContext
GetDeclContextForUIDFromDWARF(const DWARFDIE &die) override;
lldb_private::CompilerDeclContext
GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) override;
lldb_private::ClangASTImporter &GetClangASTImporter();
protected:
class DelayedAddObjCClassProperty;
typedef std::vector<DelayedAddObjCClassProperty> DelayedPropertyList;
clang::DeclContext *GetDeclContextForBlock(const DWARFDIE &die);
clang::BlockDecl *ResolveBlockDIE(const DWARFDIE &die);
clang::NamespaceDecl *ResolveNamespaceDIE(const DWARFDIE &die);
bool ParseTemplateDIE(const DWARFDIE &die,
lldb_private::ClangASTContext::TemplateParameterInfos
&template_param_infos);
bool ParseTemplateParameterInfos(
const DWARFDIE &parent_die,
lldb_private::ClangASTContext::TemplateParameterInfos
&template_param_infos);
bool
ParseChildMembers(const lldb_private::SymbolContext &sc, const DWARFDIE &die,
lldb_private::CompilerType &class_compiler_type,
const lldb::LanguageType class_language,
std::vector<clang::CXXBaseSpecifier *> &base_classes,
std::vector<int> &member_accessibilities,
DWARFDIECollection &member_function_dies,
DelayedPropertyList &delayed_properties,
lldb::AccessType &default_accessibility, bool &is_a_class,
lldb_private::ClangASTImporter::LayoutInfo &layout_info);
size_t
ParseChildParameters(const lldb_private::SymbolContext &sc,
clang::DeclContext *containing_decl_ctx,
const DWARFDIE &parent_die, bool skip_artificial,
bool &is_static, bool &is_variadic,
bool &has_template_params,
std::vector<lldb_private::CompilerType> &function_args,
std::vector<clang::ParmVarDecl *> &function_param_decls,
unsigned &type_quals);
void ParseChildArrayInfo(const lldb_private::SymbolContext &sc,
const DWARFDIE &parent_die, int64_t &first_index,
std::vector<uint64_t> &element_orders,
uint32_t &byte_stride, uint32_t &bit_stride);
size_t ParseChildEnumerators(const lldb_private::SymbolContext &sc,
lldb_private::CompilerType &compiler_type,
bool is_signed, uint32_t enumerator_byte_size,
const DWARFDIE &parent_die);
lldb_private::Type *GetTypeForDIE(const DWARFDIE &die);
clang::Decl *GetClangDeclForDIE(const DWARFDIE &die);
clang::DeclContext *GetClangDeclContextForDIE(const DWARFDIE &die);
clang::DeclContext *GetClangDeclContextContainingDIE(const DWARFDIE &die,
DWARFDIE *decl_ctx_die);
bool CopyUniqueClassMethodTypes(const DWARFDIE &src_class_die,
const DWARFDIE &dst_class_die,
lldb_private::Type *class_type,
DWARFDIECollection &failures);
clang::DeclContext *GetCachedClangDeclContextForDIE(const DWARFDIE &die);
void LinkDeclContextToDIE(clang::DeclContext *decl_ctx, const DWARFDIE &die);
void LinkDeclToDIE(clang::Decl *decl, const DWARFDIE &die);
lldb::TypeSP ParseTypeFromDWO(const DWARFDIE &die, lldb_private::Log *log);
//----------------------------------------------------------------------
// Return true if this type is a declaration to a type in an external
// module.
//----------------------------------------------------------------------
lldb::ModuleSP GetModuleForType(const DWARFDIE &die);
typedef llvm::SmallPtrSet<const DWARFDebugInfoEntry *, 4> DIEPointerSet;
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::DeclContext *>
DIEToDeclContextMap;
// typedef llvm::DenseMap<const clang::DeclContext *, DIEPointerSet>
// DeclContextToDIEMap;
typedef std::multimap<const clang::DeclContext *, const DWARFDIE>
DeclContextToDIEMap;
typedef llvm::DenseMap<const DWARFDebugInfoEntry *, clang::Decl *>
DIEToDeclMap;
typedef llvm::DenseMap<const clang::Decl *, DIEPointerSet> DeclToDIEMap;
lldb_private::ClangASTContext &m_ast;
DIEToDeclMap m_die_to_decl;
DeclToDIEMap m_decl_to_die;
DIEToDeclContextMap m_die_to_decl_ctx;
DeclContextToDIEMap m_decl_ctx_to_die;
std::unique_ptr<lldb_private::ClangASTImporter> m_clang_ast_importer_ap;
};
#endif // SymbolFileDWARF_DWARFASTParserClang_h_