]> granicus.if.org Git - llvm/commitdiff
[Bash-autocompletion] Add support for static analyzer flags
authorYuka Takahashi <yukatkh@gmail.com>
Wed, 23 Aug 2017 13:39:47 +0000 (13:39 +0000)
committerYuka Takahashi <yukatkh@gmail.com>
Wed, 23 Aug 2017 13:39:47 +0000 (13:39 +0000)
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
include/llvm/Option/OptTable.h
lib/Option/OptTable.cpp
utils/TableGen/OptParserEmitter.cpp

index 481223698719b2aa90687908d4c0da5f5a8c5a56..9c373741770b0268d5e3a15e9c6ac4a656e8cf51 100644 (file)
@@ -93,6 +93,7 @@ class Option<list<string> prefixes, string name, OptionKind kind> {
   string HelpText = ?;
   string MetaVarName = ?;
   string Values = ?;
+  code ValuesCode = ?;
   list<OptionFlag> Flags = [];
   OptionGroup Group = ?;
   Option Alias = ?;
@@ -128,6 +129,7 @@ class Group<OptionGroup group> { OptionGroup Group = group; }
 class HelpText<string text> { string HelpText = text; }
 class MetaVarName<string name> { string MetaVarName = name; }
 class Values<string value> { string Values = value; }
+class ValuesCode<code valuecode> { code ValuesCode = valuecode; }
 
 // Predefined options.
 
index 6acece967038c31f27bfffcce7a3043fa6c967b4..57a6954f4878d934069eeb1f4d804e2e92a640e8 100644 (file)
@@ -57,8 +57,8 @@ public:
   };
 
 private:
-  /// \brief The static option information table.
-  ArrayRef<Info> OptionInfos;
+  /// \brief The option information table.
+  std::vector<Info> OptionInfos;
   bool IgnoreCase;
 
   unsigned TheInputOptionID = 0;
@@ -143,6 +143,17 @@ public:
   std::vector<std::string> 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 7910bea0dcc2ecb97a03e31387814439a11fc8fa..d4486c6e8fd43ec274c877188cf71d51fe2828dd 100644 (file)
@@ -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<std::string>
 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<StringRef, 8> Candidates;
@@ -228,7 +229,8 @@ OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const {
 std::vector<std::string>
 OptTable::findByPrefix(StringRef Cur, unsigned short DisableFlags) const {
   std::vector<std::string> 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.
index e3777d036a23e77446f41379e117a5156637ca7c..ce0541d97943d2c07bb55a19d71988802645de6e 100644 (file)
@@ -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<UnsetInit>(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