Layering refinements for selectors (suggested by Chris). Specifics...
- Add SelectorTable, which enables us to remove MultiKeywordSelector from the public header.
- Remove FoldingSet from IdentifierInfo.h and Preprocessor.h.
- Remove Parser::ObjcGetUnarySelector and Parser::ObjcGetKeywordSelector, they are subsumed by SelectorTable.
- Add MultiKeywordSelector to IdentifierInfo.cpp.
- Move a bunch of selector related methods from ParseObjC.cpp to IdentifierInfo.cpp.
- Added some comments.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42643 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Lex/IdentifierTable.cpp b/Lex/IdentifierTable.cpp
index a5ba4d4..2ca1225 100644
--- a/Lex/IdentifierTable.cpp
+++ b/Lex/IdentifierTable.cpp
@@ -15,6 +15,7 @@
#include "clang/Lex/IdentifierTable.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Basic/LangOptions.h"
+#include "llvm/ADT/FoldingSet.h"
using namespace clang;
//===----------------------------------------------------------------------===//
@@ -210,3 +211,150 @@
HashTable.getAllocator().PrintStats();
}
+//===----------------------------------------------------------------------===//
+// SelectorTable Implementation
+//===----------------------------------------------------------------------===//
+
+/// MultiKeywordSelector - One of these variable length records is kept for each
+/// selector containing more than one keyword. We use a folding set
+/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
+/// this class is provided strictly through Selector.
+class MultiKeywordSelector : public llvm::FoldingSetNode {
+public:
+ unsigned NumArgs;
+
+ // Constructor for keyword selectors.
+ MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
+ assert((nKeys > 1) && "not a multi-keyword selector");
+ NumArgs = nKeys;
+ // Fill in the trailing keyword array.
+ IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
+ for (unsigned i = 0; i != nKeys; ++i)
+ KeyInfo[i] = IIV[i];
+ }
+ // Derive the full selector name, placing the result into methodBuffer.
+ // As a convenience, a pointer to the first character is returned.
+ // Example usage: llvm::SmallString<128> mbuf; Selector->getName(mbuf);
+ char *getName(llvm::SmallVectorImpl<char> &methodBuffer);
+
+ unsigned getNumArgs() const { return NumArgs; }
+
+ typedef IdentifierInfo *const *keyword_iterator;
+ keyword_iterator keyword_begin() const {
+ return reinterpret_cast<keyword_iterator>(this+1);
+ }
+ keyword_iterator keyword_end() const {
+ return keyword_begin()+NumArgs;
+ }
+ IdentifierInfo *getIdentifierInfoForSlot(unsigned i) {
+ assert((i < NumArgs) && "getIdentifierInfoForSlot(): illegal index");
+ return keyword_begin()[i];
+ }
+ static void Profile(llvm::FoldingSetNodeID &ID,
+ keyword_iterator ArgTys, unsigned NumArgs) {
+ ID.AddInteger(NumArgs);
+ if (NumArgs) { // handle keyword selector.
+ for (unsigned i = 0; i != NumArgs; ++i)
+ ID.AddPointer(ArgTys[i]);
+ } else // handle unary selector.
+ ID.AddPointer(ArgTys[0]);
+ }
+ void Profile(llvm::FoldingSetNodeID &ID) {
+ Profile(ID, keyword_begin(), NumArgs);
+ }
+};
+
+unsigned Selector::getNumArgs() const {
+ unsigned IIF = getIdentifierInfoFlag();
+ if (IIF == ZeroArg)
+ return 0;
+ if (IIF == OneArg)
+ return 1;
+ // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ return SI->getNumArgs();
+}
+
+IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) {
+ IdentifierInfo *II = getAsIdentifierInfo();
+ if (II) {
+ assert(((argIndex == 0) || (argIndex == 1)) && "illegal keyword index");
+ return II;
+ }
+ // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ return SI->getIdentifierInfoForSlot(argIndex);
+}
+
+char *MultiKeywordSelector::getName(llvm::SmallVectorImpl<char> &methodName) {
+ methodName[0] = '\0';
+ keyword_iterator KeyIter = keyword_begin();
+ for (unsigned int i = 0; i < NumArgs; i++) {
+ if (KeyIter[i]) {
+ unsigned KeyLen = KeyIter[i]->getLength();
+ methodName.append(KeyIter[i]->getName(), KeyIter[i]->getName()+KeyLen);
+ }
+ methodName.push_back(':');
+ }
+ methodName.push_back('\0');
+ return &methodName[0];
+}
+
+char *Selector::getName(llvm::SmallVectorImpl<char> &methodName) {
+ methodName[0] = '\0';
+ IdentifierInfo *II = getAsIdentifierInfo();
+ if (II) {
+ unsigned NameLen = II->getLength();
+ methodName.append(II->getName(), II->getName()+NameLen);
+ if (getNumArgs() == 1)
+ methodName.push_back(':');
+ methodName.push_back('\0');
+ } else { // We have a multiple keyword selector (no embedded flags).
+ MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
+ SI->getName(methodName);
+ }
+ return &methodName[0];
+}
+
+
+Selector SelectorTable::getKeywordSelector(unsigned nKeys, IdentifierInfo **IIV)
+{
+ llvm::FoldingSet<MultiKeywordSelector> *SelTab;
+
+ SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
+
+ // Unique selector, to guarantee there is one per name.
+ llvm::FoldingSetNodeID ID;
+ MultiKeywordSelector::Profile(ID, IIV, nKeys);
+
+ void *InsertPos = 0;
+ if (MultiKeywordSelector *SI = SelTab->FindNodeOrInsertPos(ID, InsertPos)) {
+ return Selector(SI);
+ }
+ // MultiKeywordSelector objects are not allocated with new because they have a
+ // variable size array (for parameter types) at the end of them.
+ MultiKeywordSelector *SI =
+ (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
+ nKeys*sizeof(IdentifierInfo *));
+ new (SI) MultiKeywordSelector(nKeys, IIV);
+ SelTab->InsertNode(SI, InsertPos);
+ return Selector(SI);
+}
+
+Selector SelectorTable::getUnarySelector(IdentifierInfo *ID) {
+ return Selector(ID, 1);
+}
+
+Selector SelectorTable::getNullarySelector(IdentifierInfo *ID) {
+ return Selector(ID, 0);
+}
+
+SelectorTable::SelectorTable() {
+ Impl = new llvm::FoldingSet<MultiKeywordSelector>;
+}
+
+SelectorTable::~SelectorTable() {
+ delete static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
+}
+
+