Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1952,6 +1952,7 @@ Flags<[CC1Option]>, HelpText<"Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF">; def fno_split_dwarf_inlining: Flag<["-"], "fno-split-dwarf-inlining">, Group, Flags<[CC1Option]>; +def fdebug_default_version: Joined<["-"], "fdebug-default-version=">, Group, HelpText<"Default DWARF version to use, if a -g option caused DWARF debug info to be produced">; def fdebug_prefix_map_EQ : Joined<["-"], "fdebug-prefix-map=">, Group, Flags<[CC1Option,CC1AsOption]>, Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -3145,7 +3145,6 @@ // This avoids having to monkey around further in cc1 other than to disable // codeview if not running in a Windows environment. Perhaps even that // decision should be made in the driver as well though. - unsigned DWARFVersion = 0; llvm::DebuggerKind DebuggerTuning = TC.getDefaultDebuggerTuning(); bool SplitDWARFInlining = @@ -3228,11 +3227,18 @@ } } + unsigned DWARFVersion = 0; + unsigned DefaultDWARFVersion = ParseDebugDefaultVersion(TC, Args); if (EmitDwarf) { // Start with the platform default DWARF version DWARFVersion = TC.GetDefaultDwarfVersion(); assert(DWARFVersion && "toolchain default DWARF version must be nonzero"); + // If the user specified a default DWARF version, that takes precedence + // over the platform default. + if (DefaultDWARFVersion) + DWARFVersion = DefaultDWARFVersion; + // Override with a user-specified DWARF version if (GDwarfN) if (auto ExplicitVersion = DwarfVersionNum(GDwarfN->getSpelling())) @@ -6161,6 +6167,12 @@ if (WantDebug) DwarfVersion = DwarfVersionNum(A->getSpelling()); } + + unsigned DefaultDwarfVersion = ParseDebugDefaultVersion(getToolChain(), + Args); + if (DwarfVersion == 0) + DwarfVersion = DefaultDwarfVersion; + if (DwarfVersion == 0) DwarfVersion = getToolChain().GetDefaultDwarfVersion(); Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ clang/lib/Driver/ToolChains/CommonArgs.h @@ -68,6 +68,9 @@ unsigned ParseFunctionAlignment(const ToolChain &TC, const llvm::opt::ArgList &Args); +unsigned ParseDebugDefaultVersion(const ToolChain &TC, + const llvm::opt::ArgList &Args); + void AddAssemblerKPIC(const ToolChain &ToolChain, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs); Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1138,6 +1138,22 @@ return Value ? llvm::Log2_32_Ceil(std::min(Value, 65536u)) : Value; } +unsigned tools::ParseDebugDefaultVersion(const ToolChain &TC, + const ArgList &Args) { + const Arg *A = Args.getLastArg(options::OPT_fdebug_default_version); + + if (!A) + return 0; + + unsigned Value = 0; + if (StringRef(A->getValue()).getAsInteger(10, Value) + || Value > 5 + || Value < 2) + TC.getDriver().Diag(diag::err_drv_invalid_int_value) + << A->getAsString(Args) << A->getValue(); + return Value; +} + void tools::AddAssemblerKPIC(const ToolChain &ToolChain, const ArgList &Args, ArgStringList &CmdArgs) { llvm::Reloc::Model RelocationModel; Index: clang/test/Driver/debug-default-version.c =================================================================== --- /dev/null +++ clang/test/Driver/debug-default-version.c @@ -0,0 +1,45 @@ +// RUN: %clang -### -Werror -target x86_64-linux-gnu -fdebug-default-version=4 -gdwarf-2 -S -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF2 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf-3 -fdebug-default-version=4 -S -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF3 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf-4 -fdebug-default-version=2 -S -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF4 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf-5 -S -fdebug-default-version=2 -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF5 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -fdebug-default-version=5 -g -S -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF5 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf -fdebug-default-version=2 -S -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF2 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -fdebug-default-version=4 -S -o - %s 2>&1 | FileCheck %s --check-prefixes=NODEBUGINFO,NODWARF4 + +// Check which debug info formats we use on Windows. By default, in an MSVC +// environment, we should use codeview. You can enable dwarf, which implicitly +// disables codeview, of you can explicitly ask for both if you don't know how +// the app will be debugged. +// RUN: %clang -### -Werror -target i686-pc-windows-msvc -fdebug-default-version=2 -gdwarf -S -o - %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=DWARF2,NOCODEVIEW +// Explicitly request both. +// RUN: %clang -### -Werror -target i686-pc-windows-msvc -fdebug-default-version=4 -gdwarf -gcodeview -S -o - %s 2>&1 \ +// RUN: | FileCheck %s --check-prefixes=DWARF4,CODEVIEW + + +// Do Assembler testing most of the same test cases as those above. + +// RUN: %clang -### -Werror -target x86_64-linux-gnu -fdebug-default-version=5 -g -x assembler -c -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF5 + +// RUN: %clang -### -Werror -target x86_64-linux-gnu -fdebug-default-version=4 -gdwarf-2 -x assembler -c -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF2 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf-3 -fdebug-default-version=4 -x assembler -c -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF3 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf-4 -fdebug-default-version=2 -x assembler -c -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF4 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -gdwarf-5 -x assembler -c -fdebug-default-version=2 -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF5 +// RUN: %clang -### -Werror -target x86_64-linux-gnu -fdebug-default-version=5 -g -x assembler -c -o - %s 2>&1 | FileCheck %s --check-prefix=DWARF5 + +int main (void) { + return 0; +} + +// NOCODEVIEW-NOT: "-gcodeview" +// CODEVIEW: "-gcodeview" + +// NODEBUGINFO-NOT: -debug-info-kind= + +// DWARF2: "-dwarf-version=2" +// DWARF3: "-dwarf-version=3" +// DWARF4: "-dwarf-version=4" +// DWARF5: "-dwarf-version=5" + +// NOCODEVIEW-NOT: "-gcodeview" +// NODWARF4-NOT: "-dwarf-version=4"