Skip to content

Instantly share code, notes, and snippets.

@yamaguchi1024
Created May 13, 2017 07:39
Show Gist options
  • Save yamaguchi1024/c7b6b07b631b883d0349954d544ad6fb to your computer and use it in GitHub Desktop.
Save yamaguchi1024/c7b6b07b631b883d0349954d544ad6fb to your computer and use it in GitHub Desktop.
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 1009754..4fb92fb 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -398,6 +398,10 @@ public:
/// PrintActions - Print the list of actions.
void PrintActions(const Compilation &C) const;
+ std::vector<std::string> findOptions(StringRef Prefix) const;
+ /// PrintAutocomplete - Print the autocompletion for clang.
+ void PrintAutocomplete(StringRef Cur) const;
+
/// PrintHelp - Print the help text.
///
/// \param ShowHidden - Show hidden options.
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index deec33b..3000d90 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -469,6 +469,8 @@ def arch__errors__fatal : Flag<["-"], "arch_errors_fatal">;
def arch : Separate<["-"], "arch">, Flags<[DriverOption]>;
def arch__only : Separate<["-"], "arch_only">;
def a : Joined<["-"], "a">;
+def autocomplete : Joined<["-","--"], "autocomplete=">, Flags<[DriverOption]>, Group<Action_Group>,
+ HelpText<"This is a flag for clang-autocompletion">;
def bind__at__load : Flag<["-"], "bind_at_load">;
def bundle__loader : Separate<["-"], "bundle_loader">;
def bundle : Flag<["-"], "bundle">;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index f36deff..c62fbdc 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -76,6 +76,7 @@
#endif
using namespace clang::driver;
+using namespace clang::driver::options;
using namespace clang;
using namespace llvm::opt;
@@ -1081,6 +1082,45 @@ int Driver::ExecuteCompilation(
return 0;
}
+std::vector<std::string> Driver::findOptions(StringRef Cur) const {
+#define PREFIX(PRE, VALUE) const char *const PRE[] = VALUE;
+#include "clang/Driver/Options.inc"
+#undef PREFIX
+
+ static const OptTable::Info OptInfo[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ {PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, \
+ PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS},
+#include "clang/Driver/Options.inc"
+#undef OPTION
+ };
+
+ class FlagOptTable : public OptTable {
+ public:
+ FlagOptTable() : OptTable(OptInfo) {}
+ };
+
+ FlagOptTable Table;
+
+ std::vector<std::string> Ret;
+ Ret = Table.matchFlags(Cur);
+
+ return Ret;
+}
+
+void Driver::PrintAutocomplete(StringRef Cur) const {
+ // Call function in OptTable with argument Cur. This function is supposed to
+ // return all flags with start with Cur, in InputArglist.
+ std::vector<std::string> Opts = findOptions(Cur);
+ for (std::vector<std::string>::iterator i = Opts.begin(); i != Opts.end();
+ ++i) {
+ llvm::outs() << *i << " ";
+ }
+
+ return;
+}
+
void Driver::PrintHelp(bool ShowHidden) const {
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
@@ -1216,6 +1256,11 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
return false;
}
+ if (Arg *A = C.getArgs().getLastArg(options::OPT_autocomplete)) {
+ PrintAutocomplete(A->getValue());
+ return false;
+ }
+
if (C.getArgs().hasArg(options::OPT_print_libgcc_file_name)) {
ToolChain::RuntimeLibType RLT = TC.GetRuntimeLibType(C.getArgs());
switch (RLT) {
diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c
new file mode 100644
index 0000000..1acc55f
--- /dev/null
+++ b/clang/test/Driver/autocomplete.c
@@ -0,0 +1,4 @@
+// RUN: %clang -autocomplete=-fsyn > %t
+// grep "-fsyntax-only" %t
+// RUN: %clang -autocomplete=-fno-sanitize-t > %t
+// grep "-fno-sanitize-thread-atomics -fno-sanitize-thread-func-entry-exit -fno-sanitize-thread-memory-access -fno-sanitize-trap=" %t
diff --git a/llvm/include/llvm/Option/OptTable.h b/llvm/include/llvm/Option/OptTable.h
index 390e527..945e5fb 100644
--- a/llvm/include/llvm/Option/OptTable.h
+++ b/llvm/include/llvm/Option/OptTable.h
@@ -113,6 +113,8 @@ public:
return getInfo(id).MetaVar;
}
+ std::vector<std::string> matchFlags(StringRef Cur) const;
+
/// \brief Parse a single argument; returning the new argument and
/// updating Index.
///
@@ -153,6 +155,8 @@ public:
unsigned &MissingArgCount, unsigned FlagsToInclude = 0,
unsigned FlagsToExclude = 0) const;
+ InputArgList MatchFlags(StringRef Cur) const;
+
/// \brief Render the help text for an option table.
///
/// \param OS - The stream to write the help text to.
diff --git a/llvm/lib/Option/OptTable.cpp b/llvm/lib/Option/OptTable.cpp
index 7eafb00..6b1b2f3 100644
--- a/llvm/lib/Option/OptTable.cpp
+++ b/llvm/lib/Option/OptTable.cpp
@@ -186,6 +186,25 @@ static unsigned matchOption(const OptTable::Info *I, StringRef Str,
return 0;
}
+std::vector<std::string> OptTable::matchFlags(StringRef Cur) const {
+ std::vector<std::string> Ret;
+ const Info *Start = OptionInfos.begin() + FirstSearchableIndex;
+ const Info *End = OptionInfos.end();
+ for (; Start != End; ++Start) {
+ // for (OptTable::Info Opt : *this::Info) {
+ if (Start->Prefixes) {
+ for (int i = 0; Start->Prefixes[i]; i++) {
+ std::string s =
+ (std::string(Start->Prefixes[i]) + std::string(Start->Name));
+ StringRef CurFlag = s;
+ if (CurFlag.startswith(Cur))
+ Ret.push_back(s);
+ }
+ }
+ }
+ return Ret;
+}
+
Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
unsigned FlagsToInclude,
unsigned FlagsToExclude) const {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment