summaryrefslogtreecommitdiffstats
path: root/lib/Driver
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver')
-rw-r--r--lib/Driver/ArgList.cpp59
-rw-r--r--lib/Driver/CC1Options.cpp43
-rw-r--r--lib/Driver/CMakeLists.txt4
-rw-r--r--lib/Driver/Compilation.cpp1
-rw-r--r--lib/Driver/Driver.cpp54
-rw-r--r--lib/Driver/DriverOptions.cpp42
-rw-r--r--lib/Driver/HostInfo.cpp10
-rw-r--r--lib/Driver/OptTable.cpp220
-rw-r--r--lib/Driver/Option.cpp53
-rw-r--r--lib/Driver/ToolChains.cpp11
-rw-r--r--lib/Driver/Tools.cpp30
-rw-r--r--lib/Driver/Types.cpp6
12 files changed, 289 insertions, 244 deletions
diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp
index 8d2138d..ea75c34 100644
--- a/lib/Driver/ArgList.cpp
+++ b/lib/Driver/ArgList.cpp
@@ -27,38 +27,41 @@ void ArgList::append(Arg *A) {
Args.push_back(A);
}
-Arg *ArgList::getLastArg(options::ID Id, bool Claim) const {
+Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const {
// FIXME: Make search efficient?
- for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) {
- if ((*it)->getOption().matches(Id)) {
- if (Claim) (*it)->claim();
+ for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it)
+ if ((*it)->getOption().matches(Id))
return *it;
- }
- }
-
return 0;
}
-Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const {
- Arg *Res, *A0 = getLastArg(Id0, false), *A1 = getLastArg(Id1, false);
+Arg *ArgList::getLastArg(OptSpecifier Id) const {
+ Arg *A = getLastArgNoClaim(Id);
+ if (A)
+ A->claim();
+ return A;
+}
+
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1) const {
+ Arg *Res, *A0 = getLastArgNoClaim(Id0), *A1 = getLastArgNoClaim(Id1);
if (A0 && A1)
Res = A0->getIndex() > A1->getIndex() ? A0 : A1;
else
Res = A0 ? A0 : A1;
- if (Claim && Res)
+ if (Res)
Res->claim();
return Res;
}
-Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
- bool Claim) const {
+Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1,
+ OptSpecifier Id2) const {
Arg *Res = 0;
- Arg *A0 = getLastArg(Id0, false);
- Arg *A1 = getLastArg(Id1, false);
- Arg *A2 = getLastArg(Id2, false);
+ Arg *A0 = getLastArgNoClaim(Id0);
+ Arg *A1 = getLastArgNoClaim(Id1);
+ Arg *A2 = getLastArgNoClaim(Id2);
int A0Idx = A0 ? A0->getIndex() : -1;
int A1Idx = A1 ? A1->getIndex() : -1;
@@ -76,26 +79,26 @@ Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2,
Res = A2;
}
- if (Claim && Res)
+ if (Res)
Res->claim();
return Res;
}
-bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const {
+bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const {
if (Arg *A = getLastArg(Pos, Neg))
return A->getOption().matches(Pos);
return Default;
}
-void ArgList::AddLastArg(ArgStringList &Output, options::ID Id) const {
+void ArgList::AddLastArg(ArgStringList &Output, OptSpecifier Id) const {
if (Arg *A = getLastArg(Id)) {
A->claim();
A->render(*this, Output);
}
}
-void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const {
+void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
@@ -106,8 +109,8 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0) const {
}
}
-void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
- options::ID Id1) const {
+void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
@@ -118,8 +121,8 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
}
}
-void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
- options::ID Id1, options::ID Id2) const {
+void ArgList::AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1, OptSpecifier Id2) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
@@ -131,7 +134,7 @@ void ArgList::AddAllArgs(ArgStringList &Output, options::ID Id0,
}
}
-void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const {
+void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
@@ -143,8 +146,8 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0) const {
}
}
-void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0,
- options::ID Id1) const {
+void ArgList::AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
+ OptSpecifier Id1) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
@@ -156,7 +159,7 @@ void ArgList::AddAllArgValues(ArgStringList &Output, options::ID Id0,
}
}
-void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0,
+void ArgList::AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
const char *Translation,
bool Joined) const {
// FIXME: Make fast.
@@ -177,7 +180,7 @@ void ArgList::AddAllArgsTranslated(ArgStringList &Output, options::ID Id0,
}
}
-void ArgList::ClaimAllArgs(options::ID Id0) const {
+void ArgList::ClaimAllArgs(OptSpecifier Id0) const {
// FIXME: Make fast.
for (const_iterator it = begin(), ie = end(); it != ie; ++it) {
const Arg *A = *it;
diff --git a/lib/Driver/CC1Options.cpp b/lib/Driver/CC1Options.cpp
new file mode 100644
index 0000000..672fe04
--- /dev/null
+++ b/lib/Driver/CC1Options.cpp
@@ -0,0 +1,43 @@
+//===--- CC1Options.cpp - Clang CC1 Options Table -----------------------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+
+using namespace clang::driver;
+using namespace clang::driver::options;
+using namespace clang::driver::cc1options;
+
+static OptTable::Info CC1InfoTable[] = {
+ // The InputOption info
+ { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID },
+ // The UnknownOption info
+ { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID },
+
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+ OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/CC1Options.inc"
+};
+
+namespace {
+
+class CC1OptTable : public OptTable {
+public:
+ CC1OptTable()
+ : OptTable(CC1InfoTable, sizeof(CC1InfoTable) / sizeof(CC1InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createCC1OptTable() {
+ return new CC1OptTable();
+}
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index b6998ab..60d8e9c 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -4,8 +4,10 @@ add_clang_library(clangDriver
Action.cpp
Arg.cpp
ArgList.cpp
+ CC1Options.cpp
Compilation.cpp
Driver.cpp
+ DriverOptions.cpp
HostInfo.cpp
Job.cpp
OptTable.cpp
@@ -18,4 +20,4 @@ add_clang_library(clangDriver
Types.cpp
)
-add_dependencies(clangDriver ClangDiagnosticDriver)
+add_dependencies(clangDriver ClangDiagnosticDriver ClangDriverOptions ClangCC1Options)
diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp
index c12f5aa..ffa627a 100644
--- a/lib/Driver/Compilation.cpp
+++ b/lib/Driver/Compilation.cpp
@@ -13,6 +13,7 @@
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index b4693f2..b40dc27 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -16,6 +16,7 @@
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/HostInfo.h"
#include "clang/Driver/Job.h"
+#include "clang/Driver/OptTable.h"
#include "clang/Driver/Option.h"
#include "clang/Driver/Options.h"
#include "clang/Driver/Tool.h"
@@ -44,7 +45,7 @@ Driver::Driver(const char *_Name, const char *_Dir,
const char *_DefaultHostTriple,
const char *_DefaultImageName,
bool IsProduction, Diagnostic &_Diags)
- : Opts(new OptTable()), Diags(_Diags),
+ : Opts(createDriverOptTable()), Diags(_Diags),
Name(_Name), Dir(_Dir), DefaultHostTriple(_DefaultHostTriple),
DefaultImageName(_DefaultImageName),
Host(0),
@@ -75,40 +76,23 @@ Driver::~Driver() {
InputArgList *Driver::ParseArgStrings(const char **ArgBegin,
const char **ArgEnd) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
- InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
+ unsigned MissingArgIndex, MissingArgCount;
+ InputArgList *Args = getOpts().ParseArgs(ArgBegin, ArgEnd,
+ MissingArgIndex, MissingArgCount);
- // FIXME: Handle '@' args (or at least error on them).
-
- unsigned Index = 0, End = ArgEnd - ArgBegin;
- while (Index < End) {
- // gcc's handling of empty arguments doesn't make sense, but this is not a
- // common use case. :)
- //
- // We just ignore them here (note that other things may still take them as
- // arguments).
- if (Args->getArgString(Index)[0] == '\0') {
- ++Index;
- continue;
- }
-
- unsigned Prev = Index;
- Arg *A = getOpts().ParseOneArg(*Args, Index);
- assert(Index > Prev && "Parser failed to consume argument.");
-
- // Check for missing argument error.
- if (!A) {
- assert(Index >= End && "Unexpected parser error.");
- Diag(clang::diag::err_drv_missing_argument)
- << Args->getArgString(Prev)
- << (Index - Prev - 1);
- break;
- }
+ // Check for missing argument error.
+ if (MissingArgCount)
+ Diag(clang::diag::err_drv_missing_argument)
+ << Args->getArgString(MissingArgIndex) << MissingArgCount;
+ // Check for unsupported options.
+ for (ArgList::const_iterator it = Args->begin(), ie = Args->end();
+ it != ie; ++it) {
+ Arg *A = *it;
if (A->getOption().isUnsupported()) {
Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args);
continue;
}
- Args->append(A);
}
return Args;
@@ -340,8 +324,8 @@ void Driver::PrintHelp(bool ShowHidden) const {
// Render help text into (option, help) pairs.
std::vector< std::pair<std::string, const char*> > OptionHelp;
- for (unsigned i = options::OPT_INPUT, e = options::LastOption; i != e; ++i) {
- options::ID Id = (options::ID) i;
+ for (unsigned i = 0, e = getOpts().getNumOptions(); i != e; ++i) {
+ options::ID Id = (options::ID) (i + 1);
if (const char *Text = getOpts().getOptionHelpText(Id))
OptionHelp.push_back(std::make_pair(getOptionHelpName(getOpts(), Id),
Text));
@@ -591,7 +575,7 @@ void Driver::BuildUniversalActions(const ArgList &Args,
it != ie; ++it) {
Arg *A = *it;
- if (A->getOption().getId() == options::OPT_arch) {
+ if (A->getOption().matches(options::OPT_arch)) {
// Validate the option here; we don't save the type here because its
// particular spelling may participate in other driver choices.
llvm::Triple::ArchType Arch =
@@ -686,7 +670,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
//
// Otherwise emit an error but still use a valid type to avoid
// spurious errors (e.g., no inputs).
- if (!Args.hasArg(options::OPT_E, false))
+ if (!Args.hasArgNoClaim(options::OPT_E))
Diag(clang::diag::err_drv_unknown_stdin_type);
Ty = types::TY_C;
} else {
@@ -730,7 +714,7 @@ void Driver::BuildActions(const ArgList &Args, ActionList &Actions) const {
// necessary.
Inputs.push_back(std::make_pair(types::TY_Object, A));
- } else if (A->getOption().getId() == options::OPT_x) {
+ } else if (A->getOption().matches(options::OPT_x)) {
InputTypeArg = A;
InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args));
@@ -984,7 +968,7 @@ void Driver::BuildJobs(Compilation &C) const {
// FIXME: Use iterator.
for (ArgList::const_iterator it = C.getArgs().begin(),
ie = C.getArgs().end(); it != ie; ++it) {
- if ((*it)->isClaimed() && (*it)->getOption().matches(Opt.getId())) {
+ if ((*it)->isClaimed() && (*it)->getOption().matches(&Opt)) {
DuplicateClaimed = true;
break;
}
diff --git a/lib/Driver/DriverOptions.cpp b/lib/Driver/DriverOptions.cpp
new file mode 100644
index 0000000..eddaee0
--- /dev/null
+++ b/lib/Driver/DriverOptions.cpp
@@ -0,0 +1,42 @@
+//===--- DriverOptions.cpp - Driver Options Table -----------------------*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Driver/Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Driver/Option.h"
+
+using namespace clang::driver;
+using namespace clang::driver::options;
+
+static OptTable::Info InfoTable[] = {
+ // The InputOption info
+ { "<input>", 0, 0, Option::InputClass, DriverOption, 0, OPT_INVALID, OPT_INVALID },
+ // The UnknownOption info
+ { "<unknown>", 0, 0, Option::UnknownClass, 0, 0, OPT_INVALID, OPT_INVALID },
+
+#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \
+ OPT_##GROUP, OPT_##ALIAS },
+#include "clang/Driver/Options.inc"
+};
+
+namespace {
+
+class DriverOptTable : public OptTable {
+public:
+ DriverOptTable()
+ : OptTable(InfoTable, sizeof(InfoTable) / sizeof(InfoTable[0])) {}
+};
+
+}
+
+OptTable *clang::driver::createDriverOptTable() {
+ return new DriverOptTable();
+}
diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp
index 08c4ef4..ed73b17 100644
--- a/lib/Driver/HostInfo.cpp
+++ b/lib/Driver/HostInfo.cpp
@@ -122,7 +122,7 @@ ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args,
//
// FIXME: Should this information be in llvm::Triple?
if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
- if (A->getOption().getId() == options::OPT_m32) {
+ if (A->getOption().matches(options::OPT_m32)) {
if (Arch == llvm::Triple::x86_64)
Arch = llvm::Triple::x86;
if (Arch == llvm::Triple::ppc64)
@@ -205,11 +205,11 @@ ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args,
if (Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::x86_64) {
ArchName =
- (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
} else if (Triple.getArch() == llvm::Triple::ppc ||
Triple.getArch() == llvm::Triple::ppc64) {
ArchName =
- (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64";
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
}
}
@@ -478,11 +478,11 @@ ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args,
if (Triple.getArch() == llvm::Triple::x86 ||
Triple.getArch() == llvm::Triple::x86_64) {
ArchName =
- (A->getOption().getId() == options::OPT_m32) ? "i386" : "x86_64";
+ (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64";
} else if (Triple.getArch() == llvm::Triple::ppc ||
Triple.getArch() == llvm::Triple::ppc64) {
ArchName =
- (A->getOption().getId() == options::OPT_m32) ? "powerpc" : "powerpc64";
+ (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64";
}
}
diff --git a/lib/Driver/OptTable.cpp b/lib/Driver/OptTable.cpp
index affd1c5..f68a1d8 100644
--- a/lib/Driver/OptTable.cpp
+++ b/lib/Driver/OptTable.cpp
@@ -1,4 +1,4 @@
-//===--- Options.cpp - Option info table --------------------------------*-===//
+//===--- OptTable.cpp - Option Table Implementation ---------------------*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/Driver/Options.h"
-
+#include "clang/Driver/OptTable.h"
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Option.h"
@@ -18,18 +17,6 @@
using namespace clang::driver;
using namespace clang::driver::options;
-struct Info {
- const char *Name;
- const char *Flags;
- const char *HelpText;
- const char *MetaVar;
-
- Option::OptionClass Kind;
- unsigned GroupID;
- unsigned AliasID;
- unsigned Param;
-};
-
// Ordering on Info. The ordering is *almost* lexicographic, with two
// exceptions. First, '\0' comes at the end of the alphabet instead of
// the beginning (thus options preceed any other options which prefix
@@ -56,7 +43,9 @@ static int StrCmpOptionName(const char *A, const char *B) {
return (a < b) ? -1 : 1;
}
-static inline bool operator<(const Info &A, const Info &B) {
+namespace clang {
+namespace driver {
+static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
if (&A == &B)
return false;
@@ -70,57 +59,62 @@ static inline bool operator<(const Info &A, const Info &B) {
return B.Kind == Option::JoinedClass;
}
+// Support lower_bound between info and an option name.
+static inline bool operator<(const OptTable::Info &I, const char *Name) {
+ return StrCmpOptionName(I.Name, Name) == -1;
+}
+static inline bool operator<(const char *Name, const OptTable::Info &I) {
+ return StrCmpOptionName(Name, I.Name) == -1;
+}
+}
+}
+
//
-static Info OptionInfos[] = {
- // The InputOption info
- { "<input>", "d", 0, 0, Option::InputClass, OPT_INVALID, OPT_INVALID, 0 },
- // The UnknownOption info
- { "<unknown>", "", 0, 0, Option::UnknownClass, OPT_INVALID, OPT_INVALID, 0 },
-
-#define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
- HELPTEXT, METAVAR) \
- { NAME, FLAGS, HELPTEXT, METAVAR, \
- Option::KIND##Class, OPT_##GROUP, OPT_##ALIAS, PARAM },
-#include "clang/Driver/Options.def"
-};
-static const unsigned numOptions = sizeof(OptionInfos) / sizeof(OptionInfos[0]);
-
-static Info &getInfo(unsigned id) {
- assert(id > 0 && id - 1 < numOptions && "Invalid Option ID.");
- return OptionInfos[id - 1];
-}
+OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
-OptTable::OptTable() : Options(new Option*[numOptions]) {
+//
+
+OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
+ : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
+ Options(new Option*[NumOptionInfos]),
+ TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
+{
// Explicitly zero initialize the error to work around a bug in array
// value-initialization on MinGW with gcc 4.3.5.
- memset(Options, 0, sizeof(*Options) * numOptions);
+ memset(Options, 0, sizeof(*Options) * NumOptionInfos);
// Find start of normal options.
- FirstSearchableOption = 0;
- for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) {
- if (getInfo(i).Kind != Option::GroupClass) {
- FirstSearchableOption = i;
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
+ unsigned Kind = getInfo(i + 1).Kind;
+ if (Kind == Option::InputClass) {
+ assert(!TheInputOption && "Cannot have multiple input options!");
+ TheInputOption = getOption(i + 1);
+ } else if (Kind == Option::UnknownClass) {
+ assert(!TheUnknownOption && "Cannot have multiple input options!");
+ TheUnknownOption = getOption(i + 1);
+ } else if (Kind != Option::GroupClass) {
+ FirstSearchableIndex = i;
break;
}
}
- assert(FirstSearchableOption != 0 && "No searchable options?");
+ assert(FirstSearchableIndex != 0 && "No searchable options?");
#ifndef NDEBUG
// Check that everything after the first searchable option is a
// regular option class.
- for (unsigned i = FirstSearchableOption; i < LastOption; ++i) {
- Option::OptionClass Kind = getInfo(i).Kind;
+ for (unsigned i = FirstSearchableIndex, e = getNumOptions(); i != e; ++i) {
+ Option::OptionClass Kind = (Option::OptionClass) getInfo(i + 1).Kind;
assert((Kind != Option::InputClass && Kind != Option::UnknownClass &&
Kind != Option::GroupClass) &&
"Special options should be defined first!");
}
// Check that options are in order.
- for (unsigned i = FirstSearchableOption + 1; i < LastOption; ++i) {
- if (!(getInfo(i - 1) < getInfo(i))) {
- getOption((options::ID) (i - 1))->dump();
- getOption((options::ID) i)->dump();
+ for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
+ if (!(getInfo(i) < getInfo(i + 1))) {
+ getOption(i)->dump();
+ getOption(i + 1)->dump();
assert(0 && "Options are not in order!");
}
}
@@ -128,56 +122,23 @@ OptTable::OptTable() : Options(new Option*[numOptions]) {
}
OptTable::~OptTable() {
- for (unsigned i = 0; i < numOptions; ++i)
+ for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
delete Options[i];
delete[] Options;
}
-unsigned OptTable::getNumOptions() const {
- return numOptions;
-}
-
-const char *OptTable::getOptionName(options::ID id) const {
- return getInfo(id).Name;
-}
-
-unsigned OptTable::getOptionKind(options::ID id) const {
- return getInfo(id).Kind;
-}
-
-const char *OptTable::getOptionHelpText(options::ID id) const {
- return getInfo(id).HelpText;
-}
-
-const char *OptTable::getOptionMetaVar(options::ID id) const {
- return getInfo(id).MetaVar;
-}
-
-const Option *OptTable::getOption(options::ID id) const {
- if (id == OPT_INVALID)
- return 0;
-
- assert((unsigned) (id - 1) < numOptions && "Invalid ID.");
-
- Option *&Entry = Options[id - 1];
- if (!Entry)
- Entry = constructOption(id);
-
- return Entry;
-}
-
-Option *OptTable::constructOption(options::ID id) const {
- Info &info = getInfo(id);
+Option *OptTable::CreateOption(unsigned id) const {
+ const Info &info = getInfo(id);
const OptionGroup *Group =
- cast_or_null<OptionGroup>(getOption((options::ID) info.GroupID));
- const Option *Alias = getOption((options::ID) info.AliasID);
+ cast_or_null<OptionGroup>(getOption(info.GroupID));
+ const Option *Alias = getOption(info.AliasID);
Option *Opt = 0;
switch (info.Kind) {
case Option::InputClass:
- Opt = new InputOption(); break;
+ Opt = new InputOption(id); break;
case Option::UnknownClass:
- Opt = new UnknownOption(); break;
+ Opt = new UnknownOption(id); break;
case Option::GroupClass:
Opt = new OptionGroup(id, info.Name, Group); break;
case Option::FlagClass:
@@ -196,44 +157,38 @@ Option *OptTable::constructOption(options::ID id) const {
Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
}
- for (const char *s = info.Flags; *s; ++s) {
- switch (*s) {
- default: assert(0 && "Invalid option flag.");
- case 'J':
- assert(info.Kind == Option::SeparateClass && "Invalid option.");
- Opt->setForceJoinedRender(true); break;
- case 'S':
- assert(info.Kind == Option::JoinedClass && "Invalid option.");
- Opt->setForceSeparateRender(true); break;
- case 'd': Opt->setDriverOption(true); break;
- case 'i': Opt->setNoOptAsInput(true); break;
- case 'l': Opt->setLinkerInput(true); break;
- case 'q': Opt->setNoArgumentUnused(true); break;
- case 'u': Opt->setUnsupported(true); break;
- }
+ if (info.Flags & DriverOption)
+ Opt->setDriverOption(true);
+ if (info.Flags & LinkerInput)
+ Opt->setLinkerInput(true);
+ if (info.Flags & NoArgumentUnused)
+ Opt->setNoArgumentUnused(true);
+ if (info.Flags & RenderAsInput)
+ Opt->setNoOptAsInput(true);
+ if (info.Flags & RenderJoined) {
+ assert(info.Kind == Option::SeparateClass && "Invalid option.");
+ Opt->setForceJoinedRender(true);
}
+ if (info.Flags & RenderSeparate) {
+ assert(info.Kind == Option::JoinedClass && "Invalid option.");
+ Opt->setForceSeparateRender(true);
+ }
+ if (info.Flags & Unsupported)
+ Opt->setUnsupported(true);
return Opt;
}
-// Support lower_bound between info and an option name.
-static inline bool operator<(struct Info &I, const char *Name) {
- return StrCmpOptionName(I.Name, Name) == -1;
-}
-static inline bool operator<(const char *Name, struct Info &I) {
- return StrCmpOptionName(Name, I.Name) == -1;
-}
-
Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
unsigned Prev = Index;
const char *Str = Args.getArgString(Index);
// Anything that doesn't start with '-' is an input, as is '-' itself.
if (Str[0] != '-' || Str[1] == '\0')
- return new PositionalArg(getOption(OPT_INPUT), Index++);
+ return new PositionalArg(TheInputOption, Index++);
- struct Info *Start = OptionInfos + FirstSearchableOption - 1;
- struct Info *End = OptionInfos + LastOption - 1;
+ const Info *Start = OptionInfos + FirstSearchableIndex;
+ const Info *End = OptionInfos + getNumOptions();
// Search for the first next option which could be a prefix.
Start = std::lower_bound(Start, End, Str);
@@ -255,8 +210,7 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
break;
// See if this option matches.
- options::ID id = (options::ID) (Start - OptionInfos + 1);
- if (Arg *A = getOption(id)->accept(Args, Index))
+ if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index))
return A;
// Otherwise, see if this argument was missing values.
@@ -264,6 +218,40 @@ Arg *OptTable::ParseOneArg(const InputArgList &Args, unsigned &Index) const {
return 0;
}
- return new PositionalArg(getOption(OPT_UNKNOWN), Index++);
+ return new PositionalArg(TheUnknownOption, Index++);
}
+InputArgList *OptTable::ParseArgs(const char **ArgBegin, const char **ArgEnd,
+ unsigned &MissingArgIndex,
+ unsigned &MissingArgCount) const {
+ InputArgList *Args = new InputArgList(ArgBegin, ArgEnd);
+
+ // FIXME: Handle '@' args (or at least error on them).
+
+ MissingArgIndex = MissingArgCount = 0;
+ unsigned Index = 0, End = ArgEnd - ArgBegin;
+ while (Index < End) {
+ // Ignore empty arguments (other things may still take them as arguments).
+ if (Args->getArgString(Index)[0] == '\0') {
+ ++Index;
+ continue;
+ }
+
+ unsigned Prev = Index;
+ Arg *A = ParseOneArg(*Args, Index);
+ assert(Index > Prev && "Parser failed to consume argument.");
+
+ // Check for missing argument error.
+ if (!A) {
+ assert(Index >= End && "Unexpected parser error.");
+ assert(Index - Prev - 1 && "No missing arguments!");
+ MissingArgIndex = Prev;
+ MissingArgCount = Index - Prev - 1;
+ break;
+ }
+
+ Args->append(A);
+ }
+
+ return Args;
+}
diff --git a/lib/Driver/Option.cpp b/lib/Driver/Option.cpp
index c2ace05..17d00f5 100644
--- a/lib/Driver/Option.cpp
+++ b/lib/Driver/Option.cpp
@@ -16,9 +16,9 @@
#include <algorithm>
using namespace clang::driver;
-Option::Option(OptionClass _Kind, options::ID _ID, const char *_Name,
+Option::Option(OptionClass _Kind, OptSpecifier _ID, const char *_Name,
const OptionGroup *_Group, const Option *_Alias)
- : Kind(_Kind), ID(_ID), Name(_Name), Group(_Group), Alias(_Alias),
+ : Kind(_Kind), ID(_ID.getID()), Name(_Name), Group(_Group), Alias(_Alias),
Unsupported(false), LinkerInput(false), NoOptAsInput(false),
ForceSeparateRender(false), ForceJoinedRender(false),
DriverOption(false), NoArgumentUnused(false) {
@@ -70,14 +70,13 @@ void Option::dump() const {
llvm::errs() << ">\n";
}
-bool Option::matches(const Option *Opt) const {
- // Aliases are never considered in matching.
- if (Opt->getAlias())
- return matches(Opt->getAlias());
+bool Option::matches(OptSpecifier Opt) const {
+ // Aliases are never considered in matching, look through them.
if (Alias)
return Alias->matches(Opt);
- if (this == Opt)
+ // Check exact match.
+ if (ID == Opt)
return true;
if (Group)
@@ -85,23 +84,7 @@ bool Option::matches(const Option *Opt) const {
return false;
}
-bool Option::matches(options::ID Id) const {
- // FIXME: Decide what to do here; we should either pull out the
- // handling of alias on the option for Id from the other matches, or
- // find some other solution (which hopefully doesn't require using
- // the option table).
- if (Alias)
- return Alias->matches(Id);
-
- if (ID == Id)
- return true;
-
- if (Group)
- return Group->matches(Id);
- return false;
-}
-
-OptionGroup::OptionGroup(options::ID ID, const char *Name,
+OptionGroup::OptionGroup(OptSpecifier ID, const char *Name,
const OptionGroup *Group)
: Option(Option::GroupClass, ID, Name, Group, 0) {
}
@@ -111,8 +94,8 @@ Arg *OptionGroup::accept(const InputArgList &Args, unsigned &Index) const {
return 0;
}
-InputOption::InputOption()
- : Option(Option::InputClass, options::OPT_INPUT, "<input>", 0, 0) {
+InputOption::InputOption(OptSpecifier ID)
+ : Option(Option::InputClass, ID, "<input>", 0, 0) {
}
Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const {
@@ -120,8 +103,8 @@ Arg *InputOption::accept(const InputArgList &Args, unsigned &Index) const {
return 0;
}
-UnknownOption::UnknownOption()
- : Option(Option::UnknownClass, options::OPT_UNKNOWN, "<unknown>", 0, 0) {
+UnknownOption::UnknownOption(OptSpecifier ID)
+ : Option(Option::UnknownClass, ID, "<unknown>", 0, 0) {
}
Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
@@ -129,7 +112,7 @@ Arg *UnknownOption::accept(const InputArgList &Args, unsigned &Index) const {
return 0;
}
-FlagOption::FlagOption(options::ID ID, const char *Name,
+FlagOption::FlagOption(OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias)
: Option(Option::FlagClass, ID, Name, Group, Alias) {
}
@@ -143,7 +126,7 @@ Arg *FlagOption::accept(const InputArgList &Args, unsigned &Index) const {
return new FlagArg(this, Index++);
}
-JoinedOption::JoinedOption(options::ID ID, const char *Name,
+JoinedOption::JoinedOption(OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias)
: Option(Option::JoinedClass, ID, Name, Group, Alias) {
}
@@ -153,7 +136,7 @@ Arg *JoinedOption::accept(const InputArgList &Args, unsigned &Index) const {
return new JoinedArg(this, Index++);
}
-CommaJoinedOption::CommaJoinedOption(options::ID ID, const char *Name,
+CommaJoinedOption::CommaJoinedOption(OptSpecifier ID, const char *Name,
const OptionGroup *Group,
const Option *Alias)
: Option(Option::CommaJoinedClass, ID, Name, Group, Alias) {
@@ -170,7 +153,7 @@ Arg *CommaJoinedOption::accept(const InputArgList &Args,
return new CommaJoinedArg(this, Index++, Suffix);
}
-SeparateOption::SeparateOption(options::ID ID, const char *Name,
+SeparateOption::SeparateOption(OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias)
: Option(Option::SeparateClass, ID, Name, Group, Alias) {
}
@@ -188,7 +171,7 @@ Arg *SeparateOption::accept(const InputArgList &Args, unsigned &Index) const {
return new SeparateArg(this, Index - 2, 1);
}
-MultiArgOption::MultiArgOption(options::ID ID, const char *Name,
+MultiArgOption::MultiArgOption(OptSpecifier ID, const char *Name,
const OptionGroup *Group, const Option *Alias,
unsigned _NumArgs)
: Option(Option::MultiArgClass, ID, Name, Group, Alias), NumArgs(_NumArgs) {
@@ -208,7 +191,7 @@ Arg *MultiArgOption::accept(const InputArgList &Args, unsigned &Index) const {
return new SeparateArg(this, Index - 1 - NumArgs, NumArgs);
}
-JoinedOrSeparateOption::JoinedOrSeparateOption(options::ID ID, const char *Name,
+JoinedOrSeparateOption::JoinedOrSeparateOption(OptSpecifier ID, const char *Name,
const OptionGroup *Group,
const Option *Alias)
: Option(Option::JoinedOrSeparateClass, ID, Name, Group, Alias) {
@@ -229,7 +212,7 @@ Arg *JoinedOrSeparateOption::accept(const InputArgList &Args,
return new SeparateArg(this, Index - 2, 1);
}
-JoinedAndSeparateOption::JoinedAndSeparateOption(options::ID ID,
+JoinedAndSeparateOption::JoinedAndSeparateOption(OptSpecifier ID,
const char *Name,
const OptionGroup *Group,
const Option *Alias)
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index ae8119d..af63952 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -14,7 +14,9 @@
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/HostInfo.h"
+#include "clang/Driver/OptTable.h"
#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
@@ -303,9 +305,9 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args,
// and try to push it down into tool specific logic.
Arg *OSXVersion =
- Args.getLastArg(options::OPT_mmacosx_version_min_EQ, false);
+ Args.getLastArgNoClaim(options::OPT_mmacosx_version_min_EQ);
Arg *iPhoneVersion =
- Args.getLastArg(options::OPT_miphoneos_version_min_EQ, false);
+ Args.getLastArgNoClaim(options::OPT_miphoneos_version_min_EQ);
if (OSXVersion && iPhoneVersion) {
getHost().getDriver().Diag(clang::diag::err_drv_argument_not_allowed_with)
<< OSXVersion->getAsString(Args)
@@ -365,8 +367,7 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args,
// Sob. These is strictly gcc compatible for the time being. Apple
// gcc translates options twice, which means that self-expanding
// options add duplicates.
- options::ID id = A->getOption().getId();
- switch (id) {
+ switch ((options::ID) A->getOption().getID()) {
default:
DAL->append(A);
break;
@@ -440,7 +441,7 @@ DerivedArgList *Darwin::TranslateArgs(InputArgList &Args,
if (getTriple().getArch() == llvm::Triple::x86 ||
getTriple().getArch() == llvm::Triple::x86_64)
- if (!Args.hasArg(options::OPT_mtune_EQ, false))
+ if (!Args.hasArgNoClaim(options::OPT_mtune_EQ))
DAL->append(DAL->MakeJoinedArg(0, Opts.getOption(options::OPT_mtune_EQ),
"core2"));
diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp
index 34154f3..5f0551b 100644
--- a/lib/Driver/Tools.cpp
+++ b/lib/Driver/Tools.cpp
@@ -18,6 +18,7 @@
#include "clang/Driver/Job.h"
#include "clang/Driver/HostInfo.h"
#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
#include "clang/Driver/ToolChain.h"
#include "clang/Driver/Util.h"
@@ -81,8 +82,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
DepFile = Output.getFilename();
} else if (Arg *MF = Args.getLastArg(options::OPT_MF)) {
DepFile = MF->getValue(Args);
- } else if (A->getOption().getId() == options::OPT_M ||
- A->getOption().getId() == options::OPT_MM) {
+ } else if (A->getOption().matches(options::OPT_M) ||
+ A->getOption().matches(options::OPT_MM)) {
DepFile = "-";
} else {
DepFile = darwin::CC1::getDependencyFileName(Args, Inputs);
@@ -116,8 +117,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,
CmdArgs.push_back(DepTarget);
}
- if (A->getOption().getId() == options::OPT_M ||
- A->getOption().getId() == options::OPT_MD)
+ if (A->getOption().matches(options::OPT_M) ||
+ A->getOption().matches(options::OPT_MD))
CmdArgs.push_back("-sys-header-deps");
}
@@ -778,12 +779,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
break;
}
- if (Args.hasFlag(options::OPT_fmath_errno,
+ // -fmath-errno is default.
+ if (!Args.hasFlag(options::OPT_fmath_errno,
options::OPT_fno_math_errno,
getToolChain().IsMathErrnoDefault()))
- CmdArgs.push_back("--fmath-errno=1");
- else
- CmdArgs.push_back("--fmath-errno=0");
+ CmdArgs.push_back("-fno-math-errno");
if (Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("--limit-float-precision");
@@ -822,7 +822,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// Manually translate -O to -O2 and -O4 to -O3; let clang reject
// others.
if (Arg *A = Args.getLastArg(options::OPT_O_Group)) {
- if (A->getOption().getId() == options::OPT_O4)
+ if (A->getOption().matches(options::OPT_O4))
CmdArgs.push_back("-O3");
else if (A->getValue(Args)[0] == '\0')
CmdArgs.push_back("-O2");
@@ -864,7 +864,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back(A->getValue(Args));
}
- if (Args.hasArg(options::OPT__relocatable_pch, true))
+ if (Args.hasArg(options::OPT__relocatable_pch))
CmdArgs.push_back("--relocatable-pch");
if (Arg *A = Args.getLastArg(options::OPT_fconstant_string_class_EQ)) {
@@ -922,7 +922,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -fbuiltin is default.
if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin))
- CmdArgs.push_back("-fbuiltin=0");
+ CmdArgs.push_back("-fno-builtin");
// -fblocks=0 is default.
if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
@@ -938,7 +938,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// -frtti is default.
if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti))
- CmdArgs.push_back("-frtti=0");
+ CmdArgs.push_back("-fno-rtti");
// -fsigned-char is default.
if (!Args.hasFlag(options::OPT_fsigned_char,
@@ -2609,6 +2609,8 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
// FIXME: For some reason GCC passes -lgcc and -lgcc_s before adding
// the default system libraries. Just mimic this for now.
CmdArgs.push_back("-lgcc");
+ if (D.CCCIsCXX)
+ CmdArgs.push_back("-lstdc++");
if (Args.hasArg(options::OPT_static)) {
CmdArgs.push_back("-lgcc_eh");
} else {
@@ -2638,10 +2640,6 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA,
else
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));
CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));
- // FIXME: g++ is more complicated here, it tries to put -lstdc++
- // before -lm, for example.
- if (D.CCCIsCXX)
- CmdArgs.push_back("-lstdc++");
}
const char *Exec =
diff --git a/lib/Driver/Types.cpp b/lib/Driver/Types.cpp
index 30893e7..750286b 100644
--- a/lib/Driver/Types.cpp
+++ b/lib/Driver/Types.cpp
@@ -16,14 +16,14 @@
using namespace clang::driver;
using namespace clang::driver::types;
-struct Info {
+struct TypeInfo {
const char *Name;
const char *Flags;
const char *TempSuffix;
ID PreprocessedType;
};
-static Info TypeInfos[] = {
+static TypeInfo TypeInfos[] = {
#define TYPE(NAME, ID, PP_TYPE, TEMP_SUFFIX, FLAGS) \
{ NAME, FLAGS, TEMP_SUFFIX, TY_##PP_TYPE, },
#include "clang/Driver/Types.def"
@@ -31,7 +31,7 @@ static Info TypeInfos[] = {
};
static const unsigned numTypes = sizeof(TypeInfos) / sizeof(TypeInfos[0]);
-static Info &getInfo(unsigned id) {
+static TypeInfo &getInfo(unsigned id) {
assert(id > 0 && id - 1 < numTypes && "Invalid Type ID.");
return TypeInfos[id - 1];
}
OpenPOWER on IntegriCloud