diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_BASIC_LANGOPTIONS_H #include "clang/Basic/CommentOptions.h" +#include "clang/Basic/LangStandard.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" @@ -257,6 +258,9 @@ }; public: + /// The used language standard. + LangStandard::Kind LangStd; + /// Set of enabled sanitizers. SanitizerSet Sanitize; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -434,8 +434,11 @@ AutoNormalizeEnum {} // Key paths that are constant during parsing of options with the same key path prefix. +defvar lang_std = LangOpts<"LangStd">; defvar open_cl = LangOpts<"OpenCL">; +defvar std = !strconcat("LangStandard::getLangStandardForKind(", lang_std.KeyPath, ")"); + ///////// // Options @@ -1952,10 +1955,11 @@ HelpText<"Compile common globals like normal definitions">; def fno_cxx_modules : Flag <["-"], "fno-cxx-modules">, Group, Flags<[NoXarchOption]>; -def fdigraphs : Flag<["-"], "fdigraphs">, Group, Flags<[CC1Option]>, - HelpText<"Enable alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:' (default)">; -def fno_digraphs : Flag<["-"], "fno-digraphs">, Group, Flags<[CC1Option]>, - HelpText<"Disallow alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:'">; +defm digraphs : BoolFOption<"digraphs", + LangOpts<"Digraphs">, Default, + PosFlag', '<%', '%>', '%:', '%:%:' (default)">, + NegFlag', '<%', '%>', '%:', '%:%:'">, + BothFlags<[CC1Option]>>; def fno_declspec : Flag<["-"], "fno-declspec">, Group, HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>; def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group, diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -14,7 +14,7 @@ using namespace clang; -LangOptions::LangOptions() { +LangOptions::LangOptions() : LangStd(LangStandard::lang_unspecified) { #define LANGOPT(Name, Bits, Default, Description) Name = Default; #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) set##Name(Default); #include "clang/Basic/LangOptions.def" diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1965,6 +1965,7 @@ } const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); + Opts.LangStd = LangStd; Opts.LineComment = Std.hasLineComments(); Opts.C99 = Std.isC99(); Opts.C11 = Std.isC11(); @@ -1976,7 +1977,6 @@ Opts.CPlusPlus17 = Std.isCPlusPlus17(); Opts.CPlusPlus20 = Std.isCPlusPlus20(); Opts.CPlusPlus2b = Std.isCPlusPlus2b(); - Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); Opts.GNUInline = !Opts.C99 && !Opts.CPlusPlus; Opts.GNUCVersion = 0; @@ -2256,8 +2256,6 @@ Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords, Opts.GNUKeywords); - Opts.Digraphs = Args.hasFlag(OPT_fdigraphs, OPT_fno_digraphs, Opts.Digraphs); - if (Args.hasArg(OPT_fno_operator_names)) Opts.CXXOperatorNames = 0; diff --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp b/clang/unittests/Frontend/CompilerInvocationTest.cpp --- a/clang/unittests/Frontend/CompilerInvocationTest.cpp +++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp @@ -695,4 +695,49 @@ ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-verify=xyz"), 1)); } + +// Option default depends on language standard. + +TEST_F(CommandLineTest, DigraphsImplied) { + const char *Args[] = {""}; + + ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); + ASSERT_TRUE(Invocation.getLangOpts()->Digraphs); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs")))); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs")))); +} + +TEST_F(CommandLineTest, DigraphsDisabled) { + const char *Args[] = {"-fno-digraphs"}; + + ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); + ASSERT_FALSE(Invocation.getLangOpts()->Digraphs); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-digraphs"))); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs")))); +} + +TEST_F(CommandLineTest, DigraphsNotImplied) { + const char *Args[] = {"-std=c89"}; + + ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); + ASSERT_FALSE(Invocation.getLangOpts()->Digraphs); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs")))); + ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs")))); +} + +TEST_F(CommandLineTest, DigraphsEnabled) { + const char *Args[] = {"-std=c89", "-fdigraphs"}; + + ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); + ASSERT_TRUE(Invocation.getLangOpts()->Digraphs); + + Invocation.generateCC1CommandLine(GeneratedArgs, *this); + ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdigraphs"))); +} } // anonymous namespace