Index: llvm/trunk/include/llvm/MC/MCContext.h =================================================================== --- llvm/trunk/include/llvm/MC/MCContext.h +++ llvm/trunk/include/llvm/MC/MCContext.h @@ -550,6 +550,11 @@ Source); } + /// Reports whether MD5 checksum usage is consistent (all-or-none). + bool isDwarfMD5UsageConsistent(unsigned CUID) const { + return getMCDwarfLineTable(CUID).isMD5UsageConsistent(); + } + /// Saves the information from the currently parsed dwarf .loc directive /// and sets DwarfLocSeen. When the next instruction is assembled an entry /// in the line number table with this information and the address of the Index: llvm/trunk/include/llvm/MC/MCDwarf.h =================================================================== --- llvm/trunk/include/llvm/MC/MCDwarf.h +++ llvm/trunk/include/llvm/MC/MCDwarf.h @@ -215,9 +215,12 @@ StringMap SourceIdMap; StringRef CompilationDir; MCDwarfFile RootFile; - bool HasMD5 = false; bool HasSource = false; +private: + bool HasAllMD5 = true; + bool HasAnyMD5 = false; +public: MCDwarfLineTableHeader() = default; Expected tryGetFile(StringRef &Directory, StringRef &FileName, @@ -231,6 +234,17 @@ Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params, ArrayRef SpecialOpcodeLengths, Optional &LineStr) const; + void resetMD5Usage() { + HasAllMD5 = true; + HasAnyMD5 = false; + } + void trackMD5Usage(bool MD5Used) { + HasAllMD5 &= MD5Used; + HasAnyMD5 |= MD5Used; + } + bool isMD5UsageConsistent() const { + return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5); + } private: void emitV2FileDirTables(MCStreamer *MCOS) const; @@ -251,7 +265,7 @@ Header.RootFile.DirIndex = 0; Header.RootFile.Checksum = Checksum; Header.RootFile.Source = Source; - Header.HasMD5 = (Checksum != nullptr); + Header.trackMD5Usage(Checksum); Header.HasSource = Source.hasValue(); } @@ -294,10 +308,19 @@ Header.RootFile.DirIndex = 0; Header.RootFile.Checksum = Checksum; Header.RootFile.Source = Source; - Header.HasMD5 = (Checksum != nullptr); + Header.trackMD5Usage(Checksum); Header.HasSource = Source.hasValue(); } + void resetRootFile() { + assert(Header.MCDwarfFiles.empty()); + Header.resetMD5Usage(); + Header.HasSource = false; + } + + // Report whether MD5 usage has been consistent (all-or-none). + bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); } + MCSymbol *getLabel() const { return Header.Label; } Index: llvm/trunk/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCAsmStreamer.cpp +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp @@ -1171,6 +1171,9 @@ // .file 0 is new for DWARF v5. if (getContext().getDwarfVersion() < 5) return; + // Inform MCDwarf about the root file. + getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, + Source); SmallString<128> Str; raw_svector_ostream OS1(Str); Index: llvm/trunk/lib/MC/MCDwarf.cpp =================================================================== --- llvm/trunk/lib/MC/MCDwarf.cpp +++ llvm/trunk/lib/MC/MCDwarf.cpp @@ -350,7 +350,7 @@ } static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile, - bool HasMD5, bool HasSource, + bool EmitMD5, bool HasSource, Optional &LineStr) { assert(!DwarfFile.Name.empty()); if (LineStr) @@ -360,7 +360,7 @@ MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. } MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number. - if (HasMD5) { + if (EmitMD5) { MD5::MD5Result *Cksum = DwarfFile.Checksum; MCOS->EmitBinaryData( StringRef(reinterpret_cast(Cksum->Bytes.data()), @@ -410,7 +410,7 @@ // directory index. We don't track file size/timestamp so don't emit them // in the v5 table. Emit MD5 checksums and source if we have them. uint64_t Entries = 2; - if (HasMD5) + if (HasAllMD5) Entries += 1; if (HasSource) Entries += 1; @@ -420,7 +420,7 @@ : dwarf::DW_FORM_string); MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index); MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata); - if (HasMD5) { + if (HasAllMD5) { MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5); MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16); } @@ -435,9 +435,9 @@ // explicitly, replicate file #1. MCOS->EmitULEB128IntValue(MCDwarfFiles.size()); emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile, - HasMD5, HasSource, LineStr); + HasAllMD5, HasSource, LineStr); for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) - emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasMD5, HasSource, LineStr); + emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr); } std::pair @@ -554,9 +554,10 @@ Directory = ""; } assert(!FileName.empty()); - // If any files have an MD5 checksum or embedded source, they all must. + // Keep track of whether any or all files have an MD5 checksum. + // If any files have embedded source, they all must. if (MCDwarfFiles.empty()) { - HasMD5 = (Checksum != nullptr); + trackMD5Usage(Checksum); HasSource = (Source != None); } if (FileNumber == 0) { @@ -582,10 +583,6 @@ return make_error("file number already allocated", inconvertibleErrorCode()); - // If any files have an MD5 checksum, they all must. - if (HasMD5 != (Checksum != nullptr)) - return make_error("inconsistent use of MD5 checksums", - inconvertibleErrorCode()); // If any files have embedded source, they all must. if (HasSource != (Source != None)) return make_error("inconsistent use of embedded source", @@ -625,8 +622,7 @@ File.Name = FileName; File.DirIndex = DirIndex; File.Checksum = Checksum; - if (Checksum) - HasMD5 = true; + trackMD5Usage(Checksum); File.Source = Source; if (Source) HasSource = true; Index: llvm/trunk/lib/MC/MCParser/AsmParser.cpp =================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp @@ -177,6 +177,9 @@ /// Are we parsing ms-style inline assembly? bool ParsingInlineAsm = false; + /// Did we already inform the user about inconsistent MD5 usage? + bool ReportedInconsistentMD5 = false; + public: AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out, const MCAsmInfo &MAI, unsigned CB); @@ -3337,7 +3340,11 @@ // In case there is a -g option as well as debug info from directive .file, // we turn off the -g option, directly use the existing debug info instead. - getContext().setGenDwarfForAssembly(false); + // Also reset any implicit ".file 0" for the assembler source. + if (Ctx.getGenDwarfForAssembly()) { + Ctx.getMCDwarfLineTable(0).resetRootFile(); + Ctx.setGenDwarfForAssembly(false); + } if (FileNumber == -1) getStreamer().EmitFileDirective(Filename); @@ -3364,6 +3371,12 @@ return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); FileNumber = FileNumOrErr.get(); } + // Alert the user if there are some .file directives with MD5 and some not. + // But only do that once. + if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) { + ReportedInconsistentMD5 = true; + return Warning(DirectiveLoc, "inconsistent use of MD5 checksums"); + } } return false; Index: llvm/trunk/test/CodeGen/Generic/dwarf-md5.ll =================================================================== --- llvm/trunk/test/CodeGen/Generic/dwarf-md5.ll +++ llvm/trunk/test/CodeGen/Generic/dwarf-md5.ll @@ -5,21 +5,21 @@ ; XFAIL: darwin ; REQUIRES: object-emission -; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefixes=ASM,ASM-4 -; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefixes=ASM,ASM-5 +; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM-4 +; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM-5 ; RUN: %llc_dwarf -dwarf-version 4 -filetype=obj -o %t4.o %s ; RUN: llvm-dwarfdump -debug-line %t4.o | FileCheck %s --check-prefix=OBJ ; RUN: %llc_dwarf -dwarf-version 5 -filetype=obj -o %t5.o %s ; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefixes=OBJ,OBJ-5 ; ASM-4-NOT: .file 0 -; ASM-5: .file 0 "/scratch{{.*[/\\]}}t.c" md5 0x00000000000000000000000000000000 -; ASM: .file 1 "/scratch{{.*[/\\]}}t1.h" +; ASM-4: .file 1 "/scratch{{.*[/\\]}}t1.h" ; ASM-4-NOT: md5 -; ASM-5-SAME: md5 0x11111111111111111111111111111111 -; ASM: .file 2 "/scratch{{.*[/\\]}}t2.h" +; ASM-4: .file 2 "/scratch{{.*[/\\]}}t2.h" ; ASM-4-NOT: md5 -; ASM-5-SAME: md5 0x22222222222222222222222222222222 +; ASM-5: .file 0 "/scratch{{.*[/\\]}}t.c" md5 0x00000000000000000000000000000000 +; ASM-5: .file 1 "t1.h" md5 0x11111111111111111111111111111111 +; ASM-5: .file 2 "t2.h" md5 0x22222222222222222222222222222222 ; OBJ-5: file_names[ 0]: ; OBJ-5-NEXT: name: "t.c" Index: llvm/trunk/test/CodeGen/Generic/dwarf-source.ll =================================================================== --- llvm/trunk/test/CodeGen/Generic/dwarf-source.ll +++ llvm/trunk/test/CodeGen/Generic/dwarf-source.ll @@ -5,16 +5,18 @@ ; XFAIL: darwin ; REQUIRES: object-emission -; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM -; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefixes=ASM,ASM-5 +; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM-4 +; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM-5 ; RUN: %llc_dwarf -dwarf-version 4 -filetype=obj -o %t4.o %s ; RUN: llvm-dwarfdump -debug-line %t4.o | FileCheck %s --check-prefixes=OBJ,OBJ-4 ; RUN: %llc_dwarf -dwarf-version 5 -filetype=obj -o %t5.o %s ; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefixes=OBJ,OBJ-5 +; ASM-4: .file 1 "/test{{.*[/\\]}}t1.h" source "11111111111111111111111111111111" +; ASM-4: .file 2 "/test{{.*[/\\]}}t2.h" source "22222222222222222222222222222222" ; ASM-5: .file 0 "/test{{.*[/\\]}}t.c" source "00000000000000000000000000000000" -; ASM: .file 1 "/test{{.*[/\\]}}t1.h" source "11111111111111111111111111111111" -; ASM: .file 2 "/test{{.*[/\\]}}t2.h" source "22222222222222222222222222222222" +; ASM-5: .file 1 "t1.h" source "11111111111111111111111111111111" +; ASM-5: .file 2 "t2.h" source "22222222222222222222222222222222" ; OBJ-5: file_names[ 0]: ; OBJ-5-NEXT: name: "t.c" Index: llvm/trunk/test/MC/ELF/debug-md5-err.s =================================================================== --- llvm/trunk/test/MC/ELF/debug-md5-err.s +++ llvm/trunk/test/MC/ELF/debug-md5-err.s @@ -22,5 +22,5 @@ .file "baz" md5 0xffeeddccbbaa99887766554433221100 # Inconsistent use of MD5 option. Note: .file 1 did not supply one. -# CHECK: [[@LINE+1]]:{{[0-9]+}}: error: inconsistent use of MD5 checksums +# CHECK: [[@LINE+1]]:{{[0-9]+}}: warning: inconsistent use of MD5 checksums .file 5 "bax" md5 0xffeeddccbbaa99887766554433221100 Index: llvm/trunk/test/MC/ELF/debug-mixed-md5.ll =================================================================== --- llvm/trunk/test/MC/ELF/debug-mixed-md5.ll +++ llvm/trunk/test/MC/ELF/debug-mixed-md5.ll @@ -0,0 +1,44 @@ +; RUN: %llc_dwarf -filetype=asm -dwarf-version=5 %s -o - | FileCheck %s -check-prefix=ASM +; RUN: %llc_dwarf -filetype=obj -dwarf-version=5 %s -o - | llvm-dwarfdump -debug-line - | FileCheck %s -check-prefix=OBJ +; ASM: .file 0 "{{.+}}" md5 +; ASM: .file 1 "{{.+}}" md5 +; ASM: .file 2 "t1.cpp" +; ASM-NOT: md5 +; OBJ: file_names[ 0]: +; OBJ-NOT: md5 +; +; Generated from this source (see PR37623): +; +; #define a(...) template __VA_ARGS__; +; template class b {}; +; a(class b) +; # 1 "" +; int c; + +; ModuleID = 't1.cpp' +source_filename = "t1.cpp" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@c = global i32 0, align 4, !dbg !0 + +!llvm.dbg.cu = !{!2} +!llvm.module.flags = !{!12, !13, !14} +!llvm.ident = !{!15} + +!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) +!1 = distinct !DIGlobalVariable(name: "c", scope: !2, file: !3, line: 1, type: !10, isLocal: false, isDefinition: true) +!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !11) +!3 = !DIFile(filename: "", directory: "/home/probinson/projects/scratch", checksumkind: CSK_MD5, checksum: "9252ff18ee25a08c2b4216b21b5d66d4") +!4 = !{} +!5 = !{!6} +!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "b", file: !7, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !4, templateParams: !8, identifier: "_ZTS1bIiE") +!7 = !DIFile(filename: "t1.cpp", directory: "/home/probinson/projects/scratch") +!8 = !{!9} +!9 = !DITemplateTypeParameter(type: !10) +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!0} +!12 = !{i32 2, !"Dwarf Version", i32 5} +!13 = !{i32 2, !"Debug Info Version", i32 3} +!14 = !{i32 1, !"wchar_size", i32 4} +!15 = !{!"clang version 7.0.0 "}