forked from OSchip/llvm-project
dsymutil: Avoid pruning non-type forward declarations inside DW_TAG_module
forward declarations. Especially with template instantiations, there are legitimate reasons why for declarations might be emitted into a DW_TAG_module skeleton / forward-declaration sub-tree, that are not forward declarations in the sense of that there is a more complete definition over in a .pcm file. The example in the testcase is a constant DW_TAG_member of a DW_TAG_class template instatiation. rdar://problem/43623196 llvm-svn: 341123
This commit is contained in:
parent
a1f57030c6
commit
bdffea12d0
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,59 @@
|
|||
// RUN: dsymutil -f -oso-prepend-path=%p/../Inputs/modules-pruning \
|
||||
// RUN: -y %p/dummy-debug-map.map -o - \
|
||||
// RUN: | llvm-dwarfdump --name isRef -p - | FileCheck %s
|
||||
|
||||
/* Compile with:
|
||||
cat >modules.modulemap <<EOF
|
||||
module Outer {
|
||||
module Template {
|
||||
header "template.h"
|
||||
export *
|
||||
}
|
||||
}
|
||||
EOF
|
||||
clang++ -D TEMPLATE_H -E -o template.h modules-pruning.cpp
|
||||
clang++ -c -fcxx-modules -fmodules -fmodule-map-file=modules.modulemap \
|
||||
-g -gmodules -fmodules-cache-path=. \
|
||||
-Xclang -fdisable-module-hash modules-pruning.cpp -o 1.o
|
||||
*/
|
||||
|
||||
// CHECK: DW_TAG_compile_unit
|
||||
// CHECK: DW_TAG_module
|
||||
// CHECK: DW_TAG_module
|
||||
// CHECK: DW_TAG_class
|
||||
// CHECK: DW_TAG_member
|
||||
// CHECK: DW_AT_name ("isRef")
|
||||
// CHECK: DW_AT_declaration (true)
|
||||
// CHECK: DW_AT_const_value (1)
|
||||
// CHECK-NOT: DW_TAG
|
||||
|
||||
#ifdef TEMPLATE_H
|
||||
|
||||
namespace M {
|
||||
struct false_type {
|
||||
static const bool value = false;
|
||||
};
|
||||
struct true_type {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template <class T> struct is_reference : false_type {};
|
||||
template <class T> struct is_reference<T&> : true_type {};
|
||||
|
||||
template<class T>
|
||||
class Template {
|
||||
public:
|
||||
static const bool isRef = is_reference<T>::value;
|
||||
Template() {}
|
||||
};
|
||||
}
|
||||
#else
|
||||
|
||||
#include "template.h"
|
||||
|
||||
void foo() {
|
||||
M::Template<bool&> TB1;
|
||||
TB1.isRef;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -155,6 +155,40 @@ static bool isODRAttribute(uint16_t Attr) {
|
|||
llvm_unreachable("Improper attribute.");
|
||||
}
|
||||
|
||||
static bool isTypeTag(uint16_t Tag) {
|
||||
switch (Tag) {
|
||||
case dwarf::DW_TAG_array_type:
|
||||
case dwarf::DW_TAG_class_type:
|
||||
case dwarf::DW_TAG_enumeration_type:
|
||||
case dwarf::DW_TAG_pointer_type:
|
||||
case dwarf::DW_TAG_reference_type:
|
||||
case dwarf::DW_TAG_string_type:
|
||||
case dwarf::DW_TAG_structure_type:
|
||||
case dwarf::DW_TAG_subroutine_type:
|
||||
case dwarf::DW_TAG_typedef:
|
||||
case dwarf::DW_TAG_union_type:
|
||||
case dwarf::DW_TAG_ptr_to_member_type:
|
||||
case dwarf::DW_TAG_set_type:
|
||||
case dwarf::DW_TAG_subrange_type:
|
||||
case dwarf::DW_TAG_base_type:
|
||||
case dwarf::DW_TAG_const_type:
|
||||
case dwarf::DW_TAG_constant:
|
||||
case dwarf::DW_TAG_file_type:
|
||||
case dwarf::DW_TAG_namelist:
|
||||
case dwarf::DW_TAG_packed_type:
|
||||
case dwarf::DW_TAG_volatile_type:
|
||||
case dwarf::DW_TAG_restrict_type:
|
||||
case dwarf::DW_TAG_atomic_type:
|
||||
case dwarf::DW_TAG_interface_type:
|
||||
case dwarf::DW_TAG_unspecified_type:
|
||||
case dwarf::DW_TAG_shared_type:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DwarfLinker::DIECloner::getDIENames(const DWARFDie &Die,
|
||||
AttributesInfo &Info,
|
||||
OffsetsStringPool &StringPool,
|
||||
|
@ -269,7 +303,8 @@ static bool analyzeContextInfo(const DWARFDie &DIE, unsigned ParentIdx,
|
|||
// DW_TAG_module or a DW_TAG_module that contains nothing but
|
||||
// forward declarations.
|
||||
Info.Prune &= (DIE.getTag() == dwarf::DW_TAG_module) ||
|
||||
dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0);
|
||||
(isTypeTag(DIE.getTag()) &&
|
||||
dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0));
|
||||
|
||||
// Don't prune it if there is no definition for the DIE.
|
||||
Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
|
||||
|
@ -1258,40 +1293,6 @@ bool DwarfLinker::RelocationManager::applyValidRelocs(
|
|||
return Applied;
|
||||
}
|
||||
|
||||
static bool isTypeTag(uint16_t Tag) {
|
||||
switch (Tag) {
|
||||
case dwarf::DW_TAG_array_type:
|
||||
case dwarf::DW_TAG_class_type:
|
||||
case dwarf::DW_TAG_enumeration_type:
|
||||
case dwarf::DW_TAG_pointer_type:
|
||||
case dwarf::DW_TAG_reference_type:
|
||||
case dwarf::DW_TAG_string_type:
|
||||
case dwarf::DW_TAG_structure_type:
|
||||
case dwarf::DW_TAG_subroutine_type:
|
||||
case dwarf::DW_TAG_typedef:
|
||||
case dwarf::DW_TAG_union_type:
|
||||
case dwarf::DW_TAG_ptr_to_member_type:
|
||||
case dwarf::DW_TAG_set_type:
|
||||
case dwarf::DW_TAG_subrange_type:
|
||||
case dwarf::DW_TAG_base_type:
|
||||
case dwarf::DW_TAG_const_type:
|
||||
case dwarf::DW_TAG_constant:
|
||||
case dwarf::DW_TAG_file_type:
|
||||
case dwarf::DW_TAG_namelist:
|
||||
case dwarf::DW_TAG_packed_type:
|
||||
case dwarf::DW_TAG_volatile_type:
|
||||
case dwarf::DW_TAG_restrict_type:
|
||||
case dwarf::DW_TAG_atomic_type:
|
||||
case dwarf::DW_TAG_interface_type:
|
||||
case dwarf::DW_TAG_unspecified_type:
|
||||
case dwarf::DW_TAG_shared_type:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool isObjCSelector(StringRef Name) {
|
||||
return Name.size() > 2 && (Name[0] == '-' || Name[0] == '+') &&
|
||||
(Name[1] == '[');
|
||||
|
|
Loading…
Reference in New Issue