dsymutil: Also ignore the ByteSize when building the DeclContext cache for

clang modules.

Forward decls of ObjC interfaces don't have a bytesize.

llvm-svn: 249110
This commit is contained in:
Adrian Prantl 2015-10-02 00:27:08 +00:00
parent 0ed0740c7e
commit 42562c38f5
5 changed files with 75 additions and 58 deletions

View File

@ -8,7 +8,7 @@
header "Bar.h"
export *
}
EOF
EOF
clang -D BAR_H -E -o Bar.h modules.m
clang -D FOO_H -E -o Foo.h modules.m
clang -cc1 -emit-obj -fmodules -fmodule-map-file=modules.modulemap \
@ -58,10 +58,16 @@ struct PruneMeNot;
// CHECK-NEXT: DW_AT_name{{.*}}"Foo"
// CHECK-NOT: DW_TAG
// CHECK: DW_TAG_typedef
@import Bar;
typedef struct Bar Bar;
struct S {};
@interface Foo {
int ivar;
}
@end
// ---------------------------------------------------------------------
#else
// ---------------------------------------------------------------------
@ -75,6 +81,10 @@ struct S {};
// CHECK: DW_TAG_typedef
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BAR]])
// CHECK: 0x0[[INTERFACE:.*]]: DW_TAG_structure_type
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_name{{.*}}"Foo"
//
// CHECK: DW_TAG_imported_declaration
// CHECK-NOT: DW_TAG
@ -82,9 +92,21 @@ struct S {};
//
// CHECK: DW_TAG_subprogram
// CHECK: DW_AT_name {{.*}}"main"
//
// CHECK: DW_TAG_variable
// CHECK: DW_TAG_variable
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_name{{.*}}"foo"
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_type {{.*}}{0x{{0*}}[[PTR:.*]]}
//
// CHECK: 0x{{0*}}[[PTR]]: DW_TAG_pointer_type
// CHECK-NEXT DW_AT_type [DW_FORM_ref_addr] {0x{{0*}}[[INTERFACE]])
@import Foo;
int main(int argc, char **argv) {
Bar bar;
Foo *foo = 0;
bar.value = 42;
return bar.value;
}

View File

@ -166,13 +166,14 @@ public:
/// required strings will be interned in \a StringPool.
/// \returns The child DeclContext along with one bit that is set if
/// this context is invalid.
/// FIXME: the invalid bit along the return value is to emulate some
/// dsymutil-classic functionality. See the fucntion definition for
/// a more thorough discussion of its use.
/// An invalid context means it shouldn't be considered for uniquing, but its
/// not returning null, because some children of that context might be
/// uniquing candidates. FIXME: The invalid bit along the return value is to
/// emulate some dsymutil-classic functionality.
PointerIntPair<DeclContext *, 1>
getChildDeclContext(DeclContext &Context,
const DWARFDebugInfoEntryMinimal *DIE, CompileUnit &Unit,
NonRelocatableStringpool &StringPool);
NonRelocatableStringpool &StringPool, bool InClangModule);
DeclContext &getRoot() { return Root; }
};
@ -1535,18 +1536,9 @@ bool DeclContext::setLastSeenDIE(CompileUnit &U,
return true;
}
/// Get the child context of \a Context corresponding to \a DIE.
///
/// \returns the child context or null if we shouldn't track children
/// contexts. It also returns an additional bit meaning 'invalid'. An
/// invalid context means it shouldn't be considered for uniquing, but
/// its not returning null, because some children of that context
/// might be uniquing candidates.
/// FIXME: this is for dsymutil-classic compatibility, I don't think
/// it buys us much.
PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
DeclContext &Context, const DWARFDebugInfoEntryMinimal *DIE, CompileUnit &U,
NonRelocatableStringpool &StringPool) {
NonRelocatableStringpool &StringPool, bool InClangModule) {
unsigned Tag = DIE->getTag();
// FIXME: dsymutil-classic compat: We should bail out here if we
@ -1612,50 +1604,52 @@ PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
std::string File;
unsigned Line = 0;
unsigned ByteSize = 0;
unsigned ByteSize = UINT32_MAX;
// Gather some discriminating data about the DeclContext we will be
// creating: File, line number and byte size. This shouldn't be
// necessary, because the ODR is just about names, but given that we
// do some approximations with overloaded functions and anonymous
// namespaces, use these additional data points to make the process
// safer. This is disabled for clang modules, because forward
// declarations of module-defined types do not have a file and line.
ByteSize = DIE->getAttributeValueAsUnsignedConstant(
&U.getOrigUnit(), dwarf::DW_AT_byte_size, UINT64_MAX);
if (!U.isClangModule() && (Tag != dwarf::DW_TAG_namespace || !Name)) {
if (unsigned FileNum = DIE->getAttributeValueAsUnsignedConstant(
&U.getOrigUnit(), dwarf::DW_AT_decl_file, 0)) {
if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
&U.getOrigUnit())) {
// FIXME: dsymutil-classic compatibility. I'd rather not
// unique anything in anonymous namespaces, but if we do, then
// verify that the file and line correspond.
if (!Name && Tag == dwarf::DW_TAG_namespace)
FileNum = 1;
if (!InClangModule) {
// Gather some discriminating data about the DeclContext we will be
// creating: File, line number and byte size. This shouldn't be
// necessary, because the ODR is just about names, but given that we
// do some approximations with overloaded functions and anonymous
// namespaces, use these additional data points to make the process
// safer. This is disabled for clang modules, because forward
// declarations of module-defined types do not have a file and line.
ByteSize = DIE->getAttributeValueAsUnsignedConstant(
&U.getOrigUnit(), dwarf::DW_AT_byte_size, UINT64_MAX);
if (Tag != dwarf::DW_TAG_namespace || !Name) {
if (unsigned FileNum = DIE->getAttributeValueAsUnsignedConstant(
&U.getOrigUnit(), dwarf::DW_AT_decl_file, 0)) {
if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
&U.getOrigUnit())) {
// FIXME: dsymutil-classic compatibility. I'd rather not
// unique anything in anonymous namespaces, but if we do, then
// verify that the file and line correspond.
if (!Name && Tag == dwarf::DW_TAG_namespace)
FileNum = 1;
// FIXME: Passing U.getOrigUnit().getCompilationDir()
// instead of "" would allow more uniquing, but for now, do
// it this way to match dsymutil-classic.
if (LT->getFileNameByIndex(
FileNum, "",
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
File)) {
Line = DIE->getAttributeValueAsUnsignedConstant(
&U.getOrigUnit(), dwarf::DW_AT_decl_line, 0);
// FIXME: Passing U.getOrigUnit().getCompilationDir()
// instead of "" would allow more uniquing, but for now, do
// it this way to match dsymutil-classic.
if (LT->getFileNameByIndex(
FileNum, "",
DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
File)) {
Line = DIE->getAttributeValueAsUnsignedConstant(
&U.getOrigUnit(), dwarf::DW_AT_decl_line, 0);
#ifdef HAVE_REALPATH
// Cache the resolved paths, because calling realpath is expansive.
if (const char *ResolvedPath = U.getResolvedPath(FileNum)) {
File = ResolvedPath;
} else {
char RealPath[PATH_MAX + 1];
RealPath[PATH_MAX] = 0;
if (::realpath(File.c_str(), RealPath))
File = RealPath;
U.setResolvedPath(FileNum, File);
}
// Cache the resolved paths, because calling realpath is expansive.
if (const char *ResolvedPath = U.getResolvedPath(FileNum)) {
File = ResolvedPath;
} else {
char RealPath[PATH_MAX + 1];
RealPath[PATH_MAX] = 0;
if (::realpath(File.c_str(), RealPath))
File = RealPath;
U.setResolvedPath(FileNum, File);
}
#endif
FileRef = StringPool.internString(File);
FileRef = StringPool.internString(File);
}
}
}
}
@ -1787,10 +1781,11 @@ static bool analyzeContextInfo(const DWARFDebugInfoEntryMinimal *DIE,
}
Info.ParentIdx = ParentIdx;
if (CU.hasODR() || CU.isClangModule() || InImportedModule) {
bool InClangModule = CU.isClangModule() || InImportedModule;
if (CU.hasODR() || InClangModule) {
if (CurrentDeclContext) {
auto PtrInvalidPair = Contexts.getChildDeclContext(*CurrentDeclContext,
DIE, CU, StringPool);
auto PtrInvalidPair = Contexts.getChildDeclContext(
*CurrentDeclContext, DIE, CU, StringPool, InClangModule);
CurrentDeclContext = PtrInvalidPair.getPointer();
Info.Ctxt =
PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();