[cfe-commits] r67548 - in /cfe/trunk: include/clang/Driver/Options.h lib/Driver/OptTable.cpp
Daniel Dunbar
daniel at zuster.org
Mon Mar 23 11:41:45 PDT 2009
Author: ddunbar
Date: Mon Mar 23 13:41:45 2009
New Revision: 67548
URL: http://llvm.org/viewvc/llvm-project?rev=67548&view=rev
Log:
Driver: Check that options are ordered properly (outside of
Release-Asserts mode).
Also, avoid searching through option groups (which will never match).
Modified:
cfe/trunk/include/clang/Driver/Options.h
cfe/trunk/lib/Driver/OptTable.cpp
Modified: cfe/trunk/include/clang/Driver/Options.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.h?rev=67548&r1=67547&r2=67548&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.h (original)
+++ cfe/trunk/include/clang/Driver/Options.h Mon Mar 23 13:41:45 2009
@@ -37,8 +37,15 @@
/// instantiating Options, while letting other parts of the driver
/// still use Option instances where convient.
class OptTable {
+ /// The table of options which have been constructed, indexed by
+ /// option::ID - 1.
mutable Option **Options;
+ /// The index of the first option which can be parsed (i.e., is
+ /// not a special option like 'input' or 'unknown', and is not an
+ /// option group).
+ unsigned FirstSearchableOption;
+
Option *constructOption(options::ID id) const;
public:
Modified: cfe/trunk/lib/Driver/OptTable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/OptTable.cpp?rev=67548&r1=67547&r2=67548&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/OptTable.cpp (original)
+++ cfe/trunk/lib/Driver/OptTable.cpp Mon Mar 23 13:41:45 2009
@@ -27,6 +27,48 @@
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
+// them). Second, for options with the same name, the less permissive
+// version should come first; a Flag option should preceed a Joined
+// option, for example.
+
+static int StrCmpOptionName(const char *A, const char *B) {
+ char a = *A, b = *B;
+ while (a == b) {
+ if (a == '\0')
+ return 0;
+
+ a = *++A;
+ b = *++B;
+ }
+
+ if (a == '\0') // A is a prefix of B.
+ return 1;
+ if (b == '\0') // B is a prefix of A.
+ return -1;
+
+ // Otherwise lexicographic.
+ return (a < b) ? -1 : 1;
+}
+
+static inline bool operator<(const Info &A, const Info &B) {
+ if (&A == &B)
+ return false;
+
+ if (int N = StrCmpOptionName(A.Name, B.Name))
+ return N == -1;
+
+ // Names are the same, check that classes are in order; exactly one
+ // should be joined, and it should succeed the other.
+ assert((A.Kind == Option::JoinedClass ^ B.Kind == Option::JoinedClass) &&
+ "Unexpected classes for options with same name.");
+ return B.Kind == Option::JoinedClass;
+}
+
+//
+
static Info OptionInfos[] = {
// The InputOption info
{ "<input>", "d", Option::InputClass, OPT_INVALID, OPT_INVALID, 0 },
@@ -44,11 +86,40 @@
return OptionInfos[id - 1];
}
-OptTable::OptTable() : Options(new Option*[numOptions]()) {
+OptTable::OptTable() : Options(new Option*[numOptions]()) {
+ // Find start of normal options.
+ FirstSearchableOption = 0;
+ for (unsigned i = OPT_UNKNOWN + 1; i < LastOption; ++i) {
+ if (getInfo(i).Kind != Option::GroupClass) {
+ FirstSearchableOption = i + 1;
+ break;
+ }
+ }
+ assert(FirstSearchableOption != 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;
+ 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();
+ assert(0 && "Options are not in order!");
+ }
+ }
+#endif
}
OptTable::~OptTable() {
- for (unsigned i=0; i<numOptions; ++i)
+ for (unsigned i = 0; i < numOptions; ++i)
delete Options[i];
delete[] Options;
}
@@ -136,9 +207,8 @@
if (Str[0] != '-' || Str[1] == '\0')
return new PositionalArg(getOption(OPT_INPUT), Index++);
- // FIXME: Make this fast, and avoid looking through option
- // groups. Maybe we should declare them separately?
- for (unsigned j = OPT_UNKNOWN + 1; j < LastOption; ++j) {
+ // FIXME: Make this fast.
+ for (unsigned j = FirstSearchableOption; j < LastOption; ++j) {
const char *OptName = getOptionName((options::ID) j);
// Arguments are only accepted by options which prefix them.
More information about the cfe-commits
mailing list