diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp index cccf418f65fd..71752bb38f6d 100644 --- a/clang/lib/Basic/DiagnosticIDs.cpp +++ b/clang/lib/Basic/DiagnosticIDs.cpp @@ -501,21 +501,22 @@ DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass, return Result; } -struct clang::WarningOption { - const char *NameStr; - uint16_t NameLen; - uint16_t Members; - uint16_t SubGroups; - - StringRef getName() const { - return StringRef(NameStr, NameLen); - } -}; - #define GET_DIAG_ARRAYS #include "clang/Basic/DiagnosticGroups.inc" #undef GET_DIAG_ARRAYS +struct clang::WarningOption { + uint16_t NameOffset; + uint16_t Members; + uint16_t SubGroups; + + // String is stored with a pascal-style length byte. + StringRef getName() const { + return StringRef(DiagGroupNames + NameOffset + 1, + DiagGroupNames[NameOffset]); + } +}; + // Second the table of options, sorted by name for fast binary lookup. static const WarningOption OptionTable[] = { #define GET_DIAG_TABLE @@ -524,9 +525,8 @@ static const WarningOption OptionTable[] = { }; static const size_t OptionTableSize = llvm::array_lengthof(OptionTable); -static bool WarningOptionCompare(const WarningOption &LHS, - const WarningOption &RHS) { - return LHS.getName() < RHS.getName(); +static bool WarningOptionCompare(const WarningOption &LHS, StringRef RHS) { + return LHS.getName() < RHS; } /// getWarningOptionForDiag - Return the lowest-level warning option that @@ -555,11 +555,8 @@ void DiagnosticIDs::getDiagnosticsInGroup( bool DiagnosticIDs::getDiagnosticsInGroup( StringRef Group, SmallVectorImpl &Diags) const { - if (Group.size() > UINT16_MAX) - return true; // Option is too long to be one in the table. - WarningOption Key = { Group.data(), (uint16_t)Group.size(), 0, 0 }; const WarningOption *Found = - std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, + std::lower_bound(OptionTable, OptionTable + OptionTableSize, Group, WarningOptionCompare); if (Found == OptionTable + OptionTableSize || Found->getName() != Group) diff --git a/clang/tools/diagtool/DiagnosticNames.cpp b/clang/tools/diagtool/DiagnosticNames.cpp index fa510eb6ec44..34c3229c6eb6 100644 --- a/clang/tools/diagtool/DiagnosticNames.cpp +++ b/clang/tools/diagtool/DiagnosticNames.cpp @@ -73,6 +73,10 @@ static const GroupRecord OptionTable[] = { #undef GET_DIAG_TABLE }; +llvm::StringRef GroupRecord::getName() const { + return StringRef(DiagGroupNames + NameOffset + 1, DiagGroupNames[NameOffset]); +} + GroupRecord::subgroup_iterator GroupRecord::subgroup_begin() const { return DiagSubGroups + SubGroups; } diff --git a/clang/tools/diagtool/DiagnosticNames.h b/clang/tools/diagtool/DiagnosticNames.h index 957a1818e89c..a3321fa68175 100644 --- a/clang/tools/diagtool/DiagnosticNames.h +++ b/clang/tools/diagtool/DiagnosticNames.h @@ -35,14 +35,11 @@ namespace diagtool { struct GroupRecord { - const char *NameStr; - uint16_t NameLen; + uint16_t NameOffset; uint16_t Members; uint16_t SubGroups; - llvm::StringRef getName() const { - return llvm::StringRef(NameStr, NameLen); - } + llvm::StringRef getName() const; template class group_iterator { @@ -94,8 +91,8 @@ namespace diagtool { diagnostics_iterator diagnostics_begin() const; diagnostics_iterator diagnostics_end() const; - bool operator<(const GroupRecord &Other) const { - return getName() < Other.getName(); + bool operator<(llvm::StringRef Other) const { + return getName() < Other; } }; diff --git a/clang/tools/diagtool/TreeView.cpp b/clang/tools/diagtool/TreeView.cpp index 10809c1d8d99..fd548ef011bd 100644 --- a/clang/tools/diagtool/TreeView.cpp +++ b/clang/tools/diagtool/TreeView.cpp @@ -99,9 +99,8 @@ static int showGroup(llvm::raw_ostream &out, StringRef RootGroup, return 1; } - GroupRecord Key = { RootGroup.data(), (uint16_t)RootGroup.size(), 0, 0 }; const GroupRecord *Found = - std::lower_bound(AllGroups.begin(), AllGroups.end(), Key); + std::lower_bound(AllGroups.begin(), AllGroups.end(), RootGroup); if (Found == AllGroups.end() || Found->getName() != RootGroup) { llvm::errs() << "No such diagnostic group exists\n"; diff --git a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index 9a1cd345a7de..d1bd58e1aa7e 100644 --- a/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/Debug.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" +#include "llvm/TableGen/StringToOffsetTable.h" #include "llvm/TableGen/TableGenBackend.h" #include #include @@ -671,7 +672,20 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { OS << "-1,\n"; } } - OS << "};\n"; + OS << "};\n\n"; + + StringToOffsetTable GroupNames; + for (std::map::const_iterator + I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { + // Store a pascal-style length byte at the beginning of the string. + std::string Name = char(I->first.size()) + I->first; + GroupNames.GetOrAddStringOffset(Name, false); + } + + OS << "static const char DiagGroupNames[] = {\n"; + GroupNames.EmitString(OS); + OS << "};\n\n"; + OS << "#endif // GET_DIAG_ARRAYS\n\n"; // Emit the table now. @@ -680,18 +694,16 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { for (std::map::const_iterator I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { // Group option string. - OS << " { "; - OS << "\""; + OS << " { /* "; if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789!@#$%^*-+=:?")!=std::string::npos) PrintFatalError("Invalid character in diagnostic group '" + I->first + "'"); - OS.write_escaped(I->first) << "\"," - << std::string(MaxLen-I->first.size()+1, ' '); - if (I->first.size() > UINT16_MAX) - PrintFatalError("Diagnostic group name is too long for NameLen field."); - OS << I->first.size() << ", "; + OS << I->first << " */ " << std::string(MaxLen-I->first.size(), ' '); + // Store a pascal-style length byte at the beginning of the string. + std::string Name = char(I->first.size()) + I->first; + OS << GroupNames.GetOrAddStringOffset(Name, false) << ", "; // Special handling for 'pedantic'. const bool IsPedantic = I->first == "pedantic"; @@ -707,7 +719,7 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { DiagArrayIndex += DiagsInPedantic.size(); DiagArrayIndex += V.size() + 1; } else { - OS << "/* Empty */ 0, "; + OS << "/* Empty */ 0, "; } // Subgroups. @@ -720,7 +732,7 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { SubGroupIndex += GroupsInPedantic.size(); SubGroupIndex += SubGroups.size() + 1; } else { - OS << "/* Empty */ 0"; + OS << "/* Empty */ 0"; } OS << " },\n"; }