Index: cfe/trunk/docs/ClangCommandLineReference.rst =================================================================== --- cfe/trunk/docs/ClangCommandLineReference.rst +++ cfe/trunk/docs/ClangCommandLineReference.rst @@ -792,6 +792,16 @@ .. option:: -fparse-all-comments +.. option:: -frecord-command-line, -frecord-gcc-switches, -fno-record-command-line, -fno-record-gcc-switches + +Generate a section named ".GCC.command.line" containing the clang driver +command-line. After linking, the section may contain multiple command lines, +which will be individually terminated by null bytes. Separate arguments within +a command line are combined with spaces; spaces and backslashes within an +argument are escaped with backslashes. This format differs from the format of +the equivalent section produced by GCC with the -frecord-gcc-switches flag. +This option is currently only supported on ELF targets. + .. option:: -fsanitize-address-field-padding= Level of field padding for AddressSanitizer @@ -2831,7 +2841,7 @@ .. option:: -gpubnames, -gno-pubnames -.. option:: -grecord-gcc-switches, -gno-record-gcc-switches +.. option:: -grecord-command-line, -grecord-gcc-switches, -gno-record-command-line, -gno-record-gcc-switches .. option:: -gsplit-dwarf Index: cfe/trunk/include/clang/Basic/CodeGenOptions.h =================================================================== --- cfe/trunk/include/clang/Basic/CodeGenOptions.h +++ cfe/trunk/include/clang/Basic/CodeGenOptions.h @@ -148,6 +148,10 @@ /// non-empty. std::string DwarfDebugFlags; + /// The string containing the commandline for the llvm.commandline metadata, + /// if non-empty. + std::string RecordCommandLine; + std::map DebugPrefixMap; /// The ABI to use for passing floating point arguments. Index: cfe/trunk/include/clang/Driver/CC1Options.td =================================================================== --- cfe/trunk/include/clang/Driver/CC1Options.td +++ cfe/trunk/include/clang/Driver/CC1Options.td @@ -167,6 +167,8 @@ HelpText<"The compilation directory to embed in the debug info.">; def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; +def record_command_line : Separate<["-"], "record-command-line">, + HelpText<"The string to embed in the .LLVM.command.line section.">; def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">, HelpText<"DWARF debug sections compression">; def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">, Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/include/clang/Driver/Options.td @@ -799,6 +799,12 @@ HelpText<"Treat each comma separated argument in as a documentation comment block command">, MetaVarName<"">; def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group, Flags<[CC1Option]>; +def frecord_command_line : Flag<["-"], "frecord-command-line">, + Group; +def fno_record_command_line : Flag<["-"], "fno-record-command-line">, + Group; +def : Flag<["-"], "frecord-gcc-switches">, Alias; +def : Flag<["-"], "fno-record-gcc-switches">, Alias; def fcommon : Flag<["-"], "fcommon">, Group; def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group; def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group, @@ -1854,9 +1860,12 @@ def gxcoff : Joined<["-"], "gxcoff">, Group, Flags<[Unsupported]>; def gvms : Joined<["-"], "gvms">, Group, Flags<[Unsupported]>; def gtoggle : Flag<["-"], "gtoggle">, Group, Flags<[Unsupported]>; -def grecord_gcc_switches : Flag<["-"], "grecord-gcc-switches">, Group; -def gno_record_gcc_switches : Flag<["-"], "gno-record-gcc-switches">, +def grecord_command_line : Flag<["-"], "grecord-command-line">, Group; +def gno_record_command_line : Flag<["-"], "gno-record-command-line">, + Group; +def : Flag<["-"], "grecord-gcc-switches">, Alias; +def : Flag<["-"], "gno-record-gcc-switches">, Alias; def gstrict_dwarf : Flag<["-"], "gstrict-dwarf">, Group; def gno_strict_dwarf : Flag<["-"], "gno-strict-dwarf">, Group; def gcolumn_info : Flag<["-"], "gcolumn-info">, Group, Flags<[CoreOption]>; Index: cfe/trunk/lib/CodeGen/CodeGenModule.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.h +++ cfe/trunk/lib/CodeGen/CodeGenModule.h @@ -1408,6 +1408,9 @@ /// Emit the Clang version as llvm.ident metadata. void EmitVersionIdentMetadata(); + /// Emit the Clang commandline as llvm.commandline metadata. + void EmitCommandLineMetadata(); + /// Emits target specific Metadata for global declarations. void EmitTargetMetadata(); Index: cfe/trunk/lib/CodeGen/CodeGenModule.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp @@ -590,6 +590,9 @@ if (getCodeGenOpts().EmitVersionIdentMetadata) EmitVersionIdentMetadata(); + if (!getCodeGenOpts().RecordCommandLine.empty()) + EmitCommandLineMetadata(); + EmitTargetMetadata(); } @@ -5217,6 +5220,16 @@ IdentMetadata->addOperand(llvm::MDNode::get(Ctx, IdentNode)); } +void CodeGenModule::EmitCommandLineMetadata() { + llvm::NamedMDNode *CommandLineMetadata = + TheModule.getOrInsertNamedMetadata("llvm.commandline"); + std::string CommandLine = getCodeGenOpts().RecordCommandLine; + llvm::LLVMContext &Ctx = TheModule.getContext(); + + llvm::Metadata *CommandLineNode[] = {llvm::MDString::get(Ctx, CommandLine)}; + CommandLineMetadata->addOperand(llvm::MDNode::get(Ctx, CommandLineNode)); +} + void CodeGenModule::EmitTargetMetadata() { // Warning, new MangledDeclNames may be appended within this loop. // We rely on MapVector insertions adding new elements to the end Index: cfe/trunk/lib/Driver/ToolChains/Clang.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains/Clang.cpp +++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp @@ -5063,14 +5063,22 @@ const char *Exec = D.getClangProgramPath(); - // Optionally embed the -cc1 level arguments into the debug info, for build - // analysis. + // Optionally embed the -cc1 level arguments into the debug info or a + // section, for build analysis. // Also record command line arguments into the debug info if // -grecord-gcc-switches options is set on. // By default, -gno-record-gcc-switches is set on and no recording. - if (TC.UseDwarfDebugFlags() || - Args.hasFlag(options::OPT_grecord_gcc_switches, - options::OPT_gno_record_gcc_switches, false)) { + auto GRecordSwitches = + Args.hasFlag(options::OPT_grecord_command_line, + options::OPT_gno_record_command_line, false); + auto FRecordSwitches = + Args.hasFlag(options::OPT_frecord_command_line, + options::OPT_fno_record_command_line, false); + if (FRecordSwitches && !Triple.isOSBinFormatELF()) + D.Diag(diag::err_drv_unsupported_opt_for_target) + << Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args) + << TripleStr; + if (TC.UseDwarfDebugFlags() || GRecordSwitches || FRecordSwitches) { ArgStringList OriginalArgs; for (const auto &Arg : Args) Arg->render(Args, OriginalArgs); @@ -5083,8 +5091,15 @@ Flags += " "; Flags += EscapedArg; } - CmdArgs.push_back("-dwarf-debug-flags"); - CmdArgs.push_back(Args.MakeArgString(Flags)); + auto FlagsArgString = Args.MakeArgString(Flags); + if (TC.UseDwarfDebugFlags() || GRecordSwitches) { + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(FlagsArgString); + } + if (FRecordSwitches) { + CmdArgs.push_back("-record-command-line"); + CmdArgs.push_back(FlagsArgString); + } } // Host-side cuda compilation receives all device-side outputs in a single Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp =================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp +++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp @@ -755,6 +755,7 @@ Args.hasFlag(OPT_ffine_grained_bitfield_accesses, OPT_fno_fine_grained_bitfield_accesses, false); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); + Opts.RecordCommandLine = Args.getLastArgValue(OPT_record_command_line); Opts.MergeAllConstants = Args.hasArg(OPT_fmerge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float); Index: cfe/trunk/test/Driver/clang_f_opts.c =================================================================== --- cfe/trunk/test/Driver/clang_f_opts.c +++ cfe/trunk/test/Driver/clang_f_opts.c @@ -542,3 +542,18 @@ // RUN: %clang -### -S -fomit-frame-pointer -fno-omit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-MIX-NO-OMIT-FP-PG %s // CHECK-NO-MIX-OMIT-FP-PG: '-fomit-frame-pointer' not allowed with '-pg' // CHECK-MIX-NO-OMIT-FP-PG-NOT: '-fomit-frame-pointer' not allowed with '-pg' + +// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s +// RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line -fno-record-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s +// Test with a couple examples of non-ELF object file formats +// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s +// RUN: %clang -### -S -target x86_64-unknown-windows -frecord-command-line %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s +// CHECK-RECORD-GCC-SWITCHES: "-record-command-line" +// CHECK-NO-RECORD-GCC-SWITCHES-NOT: "-record-command-line" +// CHECK-RECORD-GCC-SWITCHES-ERROR: error: unsupported option '-frecord-command-line' for target Index: cfe/trunk/test/Driver/debug-options.c =================================================================== --- cfe/trunk/test/Driver/debug-options.c +++ cfe/trunk/test/Driver/debug-options.c @@ -157,6 +157,17 @@ // RUN: %clang -### -c -O3 -ffunction-sections -grecord-gcc-switches %s 2>&1 \ // | FileCheck -check-prefix=GRECORD_OPT %s // +// RUN: %clang -### -c -grecord-command-line %s 2>&1 \ +// | FileCheck -check-prefix=GRECORD %s +// RUN: %clang -### -c -gno-record-command-line %s 2>&1 \ +// | FileCheck -check-prefix=GNO_RECORD %s +// RUN: %clang -### -c -grecord-command-line -gno-record-command-line %s 2>&1 \ +// | FileCheck -check-prefix=GNO_RECORD %s/ +// RUN: %clang -### -c -grecord-command-line -o - %s 2>&1 \ +// | FileCheck -check-prefix=GRECORD_O %s +// RUN: %clang -### -c -O3 -ffunction-sections -grecord-command-line %s 2>&1 \ +// | FileCheck -check-prefix=GRECORD_OPT %s +// // RUN: %clang -### -c -gstrict-dwarf -gno-strict-dwarf %s 2>&1 \ // RUN: | FileCheck -check-prefix=GIGNORE %s // Index: llvm/trunk/include/llvm/CodeGen/AsmPrinter.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/AsmPrinter.h +++ llvm/trunk/include/llvm/CodeGen/AsmPrinter.h @@ -656,6 +656,8 @@ void EmitLLVMUsedList(const ConstantArray *InitList); /// Emit llvm.ident metadata in an '.ident' directive. void EmitModuleIdents(Module &M); + /// Emit bytes for llvm.commandline metadata. + void EmitModuleCommandLines(Module &M); void EmitXXStructorList(const DataLayout &DL, const Constant *List, bool isCtor); Index: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -90,6 +90,8 @@ const MCExpr *lowerRelativeReference(const GlobalValue *LHS, const GlobalValue *RHS, const TargetMachine &TM) const override; + + MCSection *getSectionForCommandLines() const override; }; class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { Index: llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h +++ llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h @@ -201,6 +201,12 @@ virtual void emitLinkerFlagsForUsed(raw_ostream &OS, const GlobalValue *GV) const {} + /// If supported, return the section to use for the llvm.commandline + /// metadata. Otherwise, return nullptr. + virtual MCSection *getSectionForCommandLines() const { + return nullptr; + } + protected: virtual MCSection *SelectSectionForGlobal(const GlobalObject *GO, SectionKind Kind, Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1499,6 +1499,9 @@ // Emit llvm.ident metadata in an '.ident' directive. EmitModuleIdents(M); + // Emit bytes for llvm.commandline metadata. + EmitModuleCommandLines(M); + // Emit __morestack address if needed for indirect calls. if (MMI->usesMorestackAddr()) { unsigned Align = 1; @@ -2008,6 +2011,29 @@ } } +void AsmPrinter::EmitModuleCommandLines(Module &M) { + MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines(); + if (!CommandLine) + return; + + const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline"); + if (!NMD || !NMD->getNumOperands()) + return; + + OutStreamer->PushSection(); + OutStreamer->SwitchSection(CommandLine); + OutStreamer->EmitZeros(1); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + const MDNode *N = NMD->getOperand(i); + assert(N->getNumOperands() == 1 && + "llvm.commandline metadata entry can have only one operand"); + const MDString *S = cast(N->getOperand(0)); + OutStreamer->EmitBytes(S->getString()); + OutStreamer->EmitZeros(1); + } + OutStreamer->PopSection(); +} + //===--------------------------------------------------------------------===// // Emission and print routines // Index: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -795,6 +795,14 @@ MCSymbolRefExpr::create(TM.getSymbol(RHS), getContext()), getContext()); } +MCSection *TargetLoweringObjectFileELF::getSectionForCommandLines() const { + // Use ".GCC.command.line" since this feature is to support clang's + // -frecord-gcc-switches which in turn attempts to mimic GCC's switch of the + // same name. + return getContext().getELFSection(".GCC.command.line", ELF::SHT_PROGBITS, + ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, ""); +} + void TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) { UseInitArray = UseInitArray_; Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -386,6 +386,7 @@ visitModuleFlags(M); visitModuleIdents(M); + visitModuleCommandLines(M); verifyCompileUnits(); @@ -408,6 +409,7 @@ void visitValueAsMetadata(const ValueAsMetadata &MD, Function *F); void visitComdat(const Comdat &C); void visitModuleIdents(const Module &M); + void visitModuleCommandLines(const Module &M); void visitModuleFlags(const Module &M); void visitModuleFlag(const MDNode *Op, DenseMap &SeenIDs, @@ -1313,6 +1315,24 @@ } } +void Verifier::visitModuleCommandLines(const Module &M) { + const NamedMDNode *CommandLines = M.getNamedMetadata("llvm.commandline"); + if (!CommandLines) + return; + + // llvm.commandline takes a list of metadata entry. Each entry has only one + // string. Scan each llvm.commandline entry and make sure that this + // requirement is met. + for (const MDNode *N : CommandLines->operands()) { + Assert(N->getNumOperands() == 1, + "incorrect number of operands in llvm.commandline metadata", N); + Assert(dyn_cast_or_null(N->getOperand(0)), + ("invalid value for llvm.commandline metadata entry operand" + "(the operand should be a string)"), + N->getOperand(0)); + } +} + void Verifier::visitModuleFlags(const Module &M) { const NamedMDNode *Flags = M.getModuleFlagsMetadata(); if (!Flags) return; Index: llvm/trunk/test/CodeGen/X86/commandline-metadata.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/commandline-metadata.ll +++ llvm/trunk/test/CodeGen/X86/commandline-metadata.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s +; Verify that llvm.commandline metadata is emitted to a section named +; .GCC.command.line with each line separated with null bytes. + +; CHECK: .section .GCC.command.line,"MS",@progbits,1 +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .ascii "clang -command -line" +; CHECK-NEXT: .zero 1 +; CHECK-NEXT: .ascii "something else" +; CHECK-NEXT: .zero 1 +!llvm.commandline = !{!0, !1} +!0 = !{!"clang -command -line"} +!1 = !{!"something else"} Index: llvm/trunk/test/Linker/Inputs/commandline.a.ll =================================================================== --- llvm/trunk/test/Linker/Inputs/commandline.a.ll +++ llvm/trunk/test/Linker/Inputs/commandline.a.ll @@ -0,0 +1,3 @@ +!llvm.commandline = !{!0, !1} +!0 = !{!"compiler -v1"} +!1 = !{!"compiler -v2"} Index: llvm/trunk/test/Linker/Inputs/commandline.b.ll =================================================================== --- llvm/trunk/test/Linker/Inputs/commandline.b.ll +++ llvm/trunk/test/Linker/Inputs/commandline.b.ll @@ -0,0 +1,2 @@ +!llvm.commandline = !{!0} +!0 = !{!"compiler -v3"} Index: llvm/trunk/test/Linker/commandline.ll =================================================================== --- llvm/trunk/test/Linker/commandline.ll +++ llvm/trunk/test/Linker/commandline.ll @@ -0,0 +1,8 @@ +; RUN: llvm-link %S/Inputs/commandline.a.ll %S/Inputs/commandline.b.ll -S | FileCheck %s + +; Verify that multiple input llvm.commandline metadata are linked together. + +; CHECK-DAG: !llvm.commandline = !{!0, !1, !2} +; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v1"} +; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v2"} +; CHECK-DAG: !{{[0-2]}} = !{!"compiler -v3"} Index: llvm/trunk/test/Verifier/commandline-meta1.ll =================================================================== --- llvm/trunk/test/Verifier/commandline-meta1.ll +++ llvm/trunk/test/Verifier/commandline-meta1.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can have only one string. + +!llvm.commandline = !{!0} +!0 = !{!"string1", !"string2"} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: incorrect number of operands in llvm.commandline metadata +; CHECK-NEXT: !0 Index: llvm/trunk/test/Verifier/commandline-meta2.ll =================================================================== --- llvm/trunk/test/Verifier/commandline-meta2.ll +++ llvm/trunk/test/Verifier/commandline-meta2.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can contain one string only. + +!llvm.commandline = !{!0} +!0 = !{i32 1} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string) +; CHECK-NEXT: i32 1 Index: llvm/trunk/test/Verifier/commandline-meta3.ll =================================================================== --- llvm/trunk/test/Verifier/commandline-meta3.ll +++ llvm/trunk/test/Verifier/commandline-meta3.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can contain one string only. + +!llvm.commandline = !{!0} +!0 = !{!{!"nested metadata"}} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string) +; CHECK-NEXT: !1 Index: llvm/trunk/test/Verifier/commandline-meta4.ll =================================================================== --- llvm/trunk/test/Verifier/commandline-meta4.ll +++ llvm/trunk/test/Verifier/commandline-meta4.ll @@ -0,0 +1,9 @@ +; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s +; Verify that llvm.commandline is properly structured. +; llvm.commandline takes a list of metadata entries. +; Each metadata entry can contain one string only. + +!llvm.commandline = !{!0} +!0 = !{null} +; CHECK: assembly parsed, but does not verify as correct! +; CHECK-NEXT: invalid value for llvm.commandline metadata entry operand(the operand should be a string)