From c2ae4dbfbe624074ec17687fabc27a4bf2137db8 Mon Sep 17 00:00:00 2001 From: Yuka Takahashi Date: Wed, 23 Aug 2017 13:39:47 +0000 Subject: [PATCH] [Bash-autocompletion] Add support for static analyzer flags Summary: This is a patch for clang autocomplete feature. It will collect values which -analyzer-checker takes, which is defined in clang/StaticAnalyzer/Checkers/Checkers.inc, dynamically. First, from ValuesCode class in Options.td, TableGen will generate C++ code in Options.inc. Options.inc will be included in DriverOptions.cpp, and calls OptTable's addValues function. addValues function will add second argument to Option's Values class. Values contains string like "foo,bar,.." which is handed to Values class in OptTable. Reviewers: v.g.vassilev, teemperor, ruiu Subscribers: hiraditya, cfe-commits Differential Revision: https://reviews.llvm.org/D36782 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311552 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Option/OptParser.td | 2 ++ include/llvm/Option/OptTable.h | 15 +++++++++++++-- lib/Option/OptTable.cpp | 25 +++++++++++++++++++------ utils/TableGen/OptParserEmitter.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 8 deletions(-) diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index 48122369871..9c373741770 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -93,6 +93,7 @@ class Option prefixes, string name, OptionKind kind> { string HelpText = ?; string MetaVarName = ?; string Values = ?; + code ValuesCode = ?; list Flags = []; OptionGroup Group = ?; Option Alias = ?; @@ -128,6 +129,7 @@ class Group { OptionGroup Group = group; } class HelpText { string HelpText = text; } class MetaVarName { string MetaVarName = name; } class Values { string Values = value; } +class ValuesCode { code ValuesCode = valuecode; } // Predefined options. diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index 6acece96703..57a6954f487 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -57,8 +57,8 @@ public: }; 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 @@ public: 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. /// diff --git a/lib/Option/OptTable.cpp b/lib/Option/OptTable.cpp index 7910bea0dcc..d4486c6e8fd 100644 --- a/lib/Option/OptTable.cpp +++ b/lib/Option/OptTable.cpp @@ -196,7 +196,7 @@ static unsigned matchOption(const OptTable::Info *I, StringRef Str, // 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 @@ static bool optionMatches(const OptTable::Info &In, StringRef Option) { 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 @@ OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const { 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 @@ OptTable::findByPrefix(StringRef Cur, unsigned short DisableFlags) const { 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 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index, 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. diff --git a/utils/TableGen/OptParserEmitter.cpp b/utils/TableGen/OptParserEmitter.cpp index e3777d036a2..ce0541d9794 100644 --- a/utils/TableGen/OptParserEmitter.cpp +++ b/utils/TableGen/OptParserEmitter.cpp @@ -298,5 +298,31 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) { 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"))) + continue; + 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;\n"; + OS << "assert(ValuesWereAdded && \"Couldn't add values to " + "OptTable!\");\n"; + } + OS << "}\n"; + } + OS << "\n"; + OS << "#endif // OPTTABLE_ARG_INIT\n"; } } // end namespace llvm -- 2.11.0