Index: clang/include/clang/Driver/CC1Options.td =================================================================== --- clang/include/clang/Driver/CC1Options.td +++ clang/include/clang/Driver/CC1Options.td @@ -99,7 +99,18 @@ HelpText<"Print internal analyzer statistics.">; def analyzer_checker : Separate<["-"], "analyzer-checker">, - HelpText<"Choose analyzer checkers to enable">; + HelpText<"Choose analyzer checkers to enable">, ValuesCode<[{ +const char* Values = +#define GET_CHECKERS +#define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME "," +#include "clang/StaticAnalyzer/Checkers/Checkers.inc" +#undef GET_CHECKERS +#define GET_PACKAGES +#define PACKAGE(FULLNAME, G, D) FULLNAME "," +#include "clang/StaticAnalyzer/Checkers/Checkers.inc" +#undef GET_PACKAGES +; +}]>; def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">, Alias; Index: clang/lib/Driver/DriverOptions.cpp =================================================================== --- clang/lib/Driver/DriverOptions.cpp +++ clang/lib/Driver/DriverOptions.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include using namespace clang::driver; using namespace clang::driver::options; @@ -40,5 +41,13 @@ } std::unique_ptr clang::driver::createDriverOptTable() { - return llvm::make_unique(); + auto Result = llvm::make_unique(); + // Options.inc is included in DriverOptions.cpp, and calls OptTable's + // addValues function. + // Opt is a variable used in the code fragment in Options.inc. + OptTable &Opt = *Result; +#define OPTTABLE_ARG_INIT +#include "clang/Driver/Options.inc" +#undef OPTTABLE_ARG_INIT + return std::move(Result); } Index: clang/test/Driver/autocomplete.c =================================================================== --- clang/test/Driver/autocomplete.c +++ clang/test/Driver/autocomplete.c @@ -93,3 +93,5 @@ // WARNING-NEXT: -Wmax-unsigned-zero // RUN: %clang --autocomplete=-Wno-invalid-pp- | FileCheck %s -check-prefix=NOWARNING // NOWARNING: -Wno-invalid-pp-token +// RUN: %clang --autocomplete=-analyzer-checker, | FileCheck %s -check-prefix=ANALYZER +// ANALYZER: unix.Malloc Index: llvm/include/llvm/Option/OptParser.td =================================================================== --- llvm/include/llvm/Option/OptParser.td +++ llvm/include/llvm/Option/OptParser.td @@ -93,6 +93,7 @@ string HelpText = ?; string MetaVarName = ?; string Values = ?; + code ValuesCode = ?; list Flags = []; OptionGroup Group = ?; Option Alias = ?; @@ -128,6 +129,7 @@ class HelpText { string HelpText = text; } class MetaVarName { string MetaVarName = name; } class Values { string Values = value; } +class ValuesCode { code ValuesCode = valuecode; } // Predefined options. Index: llvm/include/llvm/Option/OptTable.h =================================================================== --- llvm/include/llvm/Option/OptTable.h +++ llvm/include/llvm/Option/OptTable.h @@ -57,8 +57,8 @@ }; private: - /// \brief The static option information table. - ArrayRef OptionInfos; + /// \brief The option information table. + std::vector OptionInfos; bool IgnoreCase; unsigned TheInputOptionID = 0; @@ -143,6 +143,17 @@ std::vector findByPrefix(StringRef Cur, unsigned short DisableFlags) const; + /// Add Values to Option's Values class + /// + /// \param [in] Option - Prefix + Name of the flag which Values will be + /// changed. For example, "-analyzer-checker". + /// \param [in] Values - String of Values seperated by ",", such as + /// "foo, bar..", where foo and bar is the argument which the Option flag + // takes + /// + /// \return true in success, and false in fail. + bool addValues(const char *Option, const char *Values); + /// \brief Parse a single argument; returning the new argument and /// updating Index. /// Index: llvm/lib/Option/OptTable.cpp =================================================================== --- llvm/lib/Option/OptTable.cpp +++ llvm/lib/Option/OptTable.cpp @@ -196,7 +196,7 @@ // Returns true if one of the Prefixes + In.Names matches Option static bool optionMatches(const OptTable::Info &In, StringRef Option) { - if (In.Values && In.Prefixes) + if (In.Prefixes) for (size_t I = 0; In.Prefixes[I]; I++) if (Option == std::string(In.Prefixes[I]) + In.Name) return true; @@ -209,8 +209,9 @@ std::vector OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const { // Search all options and return possible values. - for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) { - if (!optionMatches(In, Option)) + for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) { + const Info &In = OptionInfos[I]; + if (!In.Values || !optionMatches(In, Option)) continue; SmallVector Candidates; @@ -228,7 +229,8 @@ std::vector OptTable::findByPrefix(StringRef Cur, unsigned short DisableFlags) const { std::vector Ret; - for (const Info &In : OptionInfos.slice(FirstSearchableIndex)) { + for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) { + const Info &In = OptionInfos[I]; if (!In.Prefixes || (!In.HelpText && !In.GroupID)) continue; if (In.Flags & DisableFlags) @@ -245,6 +247,17 @@ return Ret; } +bool OptTable::addValues(const char *Option, const char *Values) { + for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) { + Info &In = OptionInfos[I]; + if (optionMatches(In, Option)) { + In.Values = Values; + return true; + } + } + return false; +} + Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index, unsigned FlagsToInclude, unsigned FlagsToExclude) const { @@ -256,8 +269,8 @@ if (isInput(PrefixesUnion, Str)) return new Arg(getOption(TheInputOptionID), Str, Index++, Str); - const Info *Start = OptionInfos.begin() + FirstSearchableIndex; - const Info *End = OptionInfos.end(); + const Info *Start = OptionInfos.data() + FirstSearchableIndex; + const Info *End = OptionInfos.data() + OptionInfos.size(); StringRef Name = StringRef(Str).ltrim(PrefixChars); // Search for the first next option which could be a prefix. Index: llvm/utils/TableGen/OptParserEmitter.cpp =================================================================== --- llvm/utils/TableGen/OptParserEmitter.cpp +++ llvm/utils/TableGen/OptParserEmitter.cpp @@ -298,5 +298,30 @@ OS << ")\n"; } OS << "#endif // OPTION\n"; + + OS << "\n"; + OS << "#ifdef OPTTABLE_ARG_INIT\n"; + OS << "//////////\n"; + OS << "// Option Values\n\n"; + for (unsigned I = 0, E = Opts.size(); I != E; ++I) { + const Record &R = *Opts[I]; + if (!isa(R.getValueInit("ValuesCode"))) { + OS << "{\n"; + OS << R.getValueAsString("ValuesCode"); + OS << "\n"; + for (const std::string &Pref : R.getValueAsListOfStrings("Prefixes")) { + OS << "bool ValuesWereAdded = "; + OS << "Opt.addValues("; + std::string S = (Pref + R.getValueAsString("Name")).str(); + write_cstring(OS, S); + OS << ", Values);\n"; + OS << "(void)ValuesWereAdded;\nassert(ValuesWereAdded &&"; + OS << " \"Couldn't add values to OptTable!\");\n"; + } + OS << "}\n"; + } + } + OS << "\n"; + OS << "#endif // OPTTABLE_ARG_INIT\n"; } } // end namespace llvm