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 \
- -fmodule-format=obj -g -dwarf-ext-refs -fmodules-cache-path=. \
- -fdisable-module-hash modules.m -o 1.o
+ clang -D ODR_VIOLATION_C -E -o odr_violation.c modules.m
+ clang -c -fmodules -fmodule-map-file=modules.modulemap \
+ -g -gmodules -fmodules-cache-path=. \
+ -Xclang -fdisable-module-hash modules.m -o 1.o
+ clang -c -g odr_violation.c -o 2.o
*/
// RUN: llvm-dsymutil -f -oso-prepend-path=%p/../Inputs/modules \
// CHECK: 0x0[[FOO:.*]]: DW_TAG_module
// CHECK-NEXT: DW_AT_name{{.*}}"Foo"
// CHECK-NOT: DW_TAG
-// CHECK: DW_TAG_typedef
+// CHECK: 0x0[[BARTD:.*]]: DW_TAG_typedef
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BAR]])
// CHECK: DW_TAG_structure_type
}
@end
+#else
+// ---------------------------------------------------------------------
+#ifdef ODR_VIOLATION_C
+// ---------------------------------------------------------------------
+
+struct Bar {
+ int i;
+};
+typedef struct Bar Bar;
+Bar odr_violation = { 42 };
+
// ---------------------------------------------------------------------
#else
// ---------------------------------------------------------------------
// CHECK: DW_TAG_compile_unit
// CHECK: DW_AT_low_pc
-// CHECK-NOT:DW_TAG
-// CHECK: DW_TAG_module
-// CHECK-NEXT: DW_AT_name{{.*}}"Foo"
-// CHECK-NOT: DW_TAG
-// CHECK: DW_TAG_typedef
-// CHECK-NOT: DW_TAG
-// CHECK: NULL
+// CHECK-NOT: DW_TAG_module
+// CHECK-NOT: DW_TAG_typedef
//
// CHECK: DW_TAG_imported_declaration
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_name {{.*}}"main"
//
// CHECK: DW_TAG_variable
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_name{{.*}}"bar"
+// CHECK-NOT: DW_TAG
+// CHECK: DW_AT_type [DW_FORM_ref_addr] (0x{{0*}}[[BARTD]]
// CHECK: DW_TAG_variable
// CHECK-NOT: DW_TAG
// CHECK: DW_AT_name{{.*}}"foo"
//
// CHECK: 0x{{0*}}[[PTR]]: DW_TAG_pointer_type
// CHECK-NEXT DW_AT_type [DW_FORM_ref_addr] {0x{{0*}}[[INTERFACE]])
+extern int odr_violation;
@import Foo;
int main(int argc, char **argv) {
Bar bar;
Foo *foo = 0;
- bar.value = 42;
+ bar.value = odr_violation;
return bar.value;
}
#endif
#endif
+#endif
+
+// CHECK: DW_TAG_compile_unit
+// CHECK: DW_AT_name {{.*}}"odr_violation.c"
+// CHECK: DW_TAG_variable
+// CHECK: DW_AT_name {{.*}}"odr_violation"
+// CHECK: DW_AT_type [DW_FORM_ref4] ({{.*}}{0x{{0*}}[[BAR2:.*]]})
+// CHECK: 0x{{0*}}[[BAR2]]: DW_TAG_typedef
+// CHECK: DW_AT_type [DW_FORM_ref4] ({{.*}}{0x{{0*}}[[BAR3:.*]]})
+// CHECK: DW_AT_name {{.*}}"Bar"
+// CHECK: 0x{{0*}}[[BAR3]]: DW_TAG_structure_type
+// CHECK-NEXT: DW_AT_name {{.*}}"Bar"
uint32_t Line;
uint32_t ByteSize;
uint16_t Tag;
+ unsigned DefinedInClangModule : 1;
StringRef Name;
StringRef File;
const DeclContext &Parent;
DeclContext()
: QualifiedNameHash(0), Line(0), ByteSize(0),
- Tag(dwarf::DW_TAG_compile_unit), Name(), File(), Parent(*this),
- LastSeenDIE(), LastSeenCompileUnitID(0), CanonicalDIEOffset(0) {}
+ Tag(dwarf::DW_TAG_compile_unit), DefinedInClangModule(0), Name(),
+ File(), Parent(*this), LastSeenDIE(), LastSeenCompileUnitID(0),
+ CanonicalDIEOffset(0) {}
DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t Tag,
StringRef Name, StringRef File, const DeclContext &Parent,
DWARFDie LastSeenDIE = DWARFDie(), unsigned CUId = 0)
: QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
- Name(Name), File(File), Parent(Parent), LastSeenDIE(LastSeenDIE),
- LastSeenCompileUnitID(CUId), CanonicalDIEOffset(0) {}
+ DefinedInClangModule(0), Name(Name), File(File), Parent(Parent),
+ LastSeenDIE(LastSeenDIE), LastSeenCompileUnitID(CUId),
+ CanonicalDIEOffset(0) {}
uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset = Offset; }
+ bool isDefinedInClangModule() const { return DefinedInClangModule; }
+ void setDefinedInClangModule(bool Val) { DefinedInClangModule = Val; }
+
uint16_t getTag() const { return Tag; }
StringRef getName() const { return Name; }
};
CurrentDeclContext = PtrInvalidPair.getPointer();
Info.Ctxt =
PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
+ if (Info.Ctxt)
+ Info.Ctxt->setDefinedInClangModule(InClangModule);
} else
Info.Ctxt = CurrentDeclContext = nullptr;
}
return shouldKeepVariableDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
case dwarf::DW_TAG_subprogram:
return shouldKeepSubprogramDIE(RelocMgr, DIE, Unit, MyInfo, Flags);
- case dwarf::DW_TAG_module:
case dwarf::DW_TAG_imported_module:
case dwarf::DW_TAG_imported_declaration:
case dwarf::DW_TAG_imported_unit:
resolveDIEReference(*this, Units, Val, Unit, Die, ReferencedCU)) {
uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE);
CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx);
+ bool IsModuleRef = Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset() &&
+ Info.Ctxt->isDefinedInClangModule();
// If the referenced DIE has a DeclContext that has already been
// emitted, then do not keep the one in this CU. We'll link to
// the canonical DIE in cloneDieReferenceAttribute.
// ReferencedCU->hasODR() && CU.hasODR().
// FIXME: compatibility with dsymutil-classic. There is no
// reason not to unique ref_addr references.
- if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && UseODR && Info.Ctxt &&
+ if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && (UseODR || IsModuleRef) &&
+ Info.Ctxt &&
Info.Ctxt != ReferencedCU->getInfo(Info.ParentIdx).Ctxt &&
Info.Ctxt->getCanonicalDIEOffset() && isODRAttribute(AttrSpec.Attr))
continue;