yamaguchi created this revision.
Herald added a subscriber: hiraditya.

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.


https://reviews.llvm.org/D36782

Files:
  clang/include/clang/Driver/CC1Options.td
  clang/lib/Driver/DriverOptions.cpp
  clang/test/Driver/autocomplete.c
  llvm/include/llvm/Option/OptParser.td
  llvm/include/llvm/Option/OptTable.h
  llvm/lib/Option/OptTable.cpp
  llvm/utils/TableGen/OptParserEmitter.cpp

Index: llvm/utils/TableGen/OptParserEmitter.cpp
===================================================================
--- llvm/utils/TableGen/OptParserEmitter.cpp
+++ llvm/utils/TableGen/OptParserEmitter.cpp
@@ -298,5 +298,25 @@
     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"))) {
+      OS << R.getValueAsString("ValuesCode");
+      OS << "\n";
+      for (const std::string &Pref : R.getValueAsListOfStrings("Prefixes")) {
+        OS << "Opt.addValues(";
+        std::string S = (Pref + R.getValueAsString("Name")).str();
+        write_cstring(OS, S);
+        OS << ", Values);";
+      }
+    }
+  }
+  OS << "\n";
+  OS << "#endif // OPTTABLE_ARG_INIT\n";
 }
 } // end namespace llvm
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<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 @@
 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,14 @@
   return Ret;
 }
 
+void 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;
+  }
+}
+
 Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
                            unsigned FlagsToInclude,
                            unsigned FlagsToExclude) const {
@@ -256,8 +266,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/include/llvm/Option/OptTable.h
===================================================================
--- llvm/include/llvm/Option/OptTable.h
+++ llvm/include/llvm/Option/OptTable.h
@@ -58,7 +58,7 @@
 
 private:
   /// \brief The static option information table.
-  ArrayRef<Info> OptionInfos;
+  std::vector<Info> OptionInfos;
   bool IgnoreCase;
 
   unsigned TheInputOptionID = 0;
@@ -143,6 +143,15 @@
   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
+  /// \param [in] Values - String of Values seperated by ",", such as
+  //  "foo, bar..", where foo and bar is the argument which the Option flag
+  //  takes
+  void addValues(const char *Option, const char *Values);
+
   /// \brief Parse a single argument; returning the new argument and
   /// updating Index.
   ///
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<OptionFlag> Flags = [];
   OptionGroup Group = ?;
   Option Alias = ?;
@@ -128,6 +129,7 @@
 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: 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: alpha.clone.CloneChecker
Index: clang/lib/Driver/DriverOptions.cpp
===================================================================
--- clang/lib/Driver/DriverOptions.cpp
+++ clang/lib/Driver/DriverOptions.cpp
@@ -40,5 +40,13 @@
 }
 
 std::unique_ptr<OptTable> clang::driver::createDriverOptTable() {
-  return llvm::make_unique<DriverOptTable>();
+  auto Result = llvm::make_unique<DriverOptTable>();
+  // 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/include/clang/Driver/CC1Options.td
===================================================================
--- clang/include/clang/Driver/CC1Options.td
+++ clang/include/clang/Driver/CC1Options.td
@@ -99,7 +99,14 @@
   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
+;
+}]>;
 def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">,
   Alias<analyzer_checker>;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to