summaryrefslogtreecommitdiff
path: root/Lex/IdentifierTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Lex/IdentifierTable.cpp')
-rw-r--r--Lex/IdentifierTable.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/Lex/IdentifierTable.cpp b/Lex/IdentifierTable.cpp
new file mode 100644
index 0000000000..e671af9839
--- /dev/null
+++ b/Lex/IdentifierTable.cpp
@@ -0,0 +1,188 @@
+//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Chris Lattner and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IdentifierInfo, IdentifierVisitor, and
+// IdentifierTable interfaces.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Lex/IdentifierTable.h"
+#include "clang/Lex/MacroInfo.h"
+#include "clang/Basic/LangOptions.h"
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// IdentifierInfo Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierInfo::IdentifierInfo() {
+ Macro = 0;
+ TokenID = tok::identifier;
+ PPID = tok::pp_not_keyword;
+ ObjCID = tok::objc_not_keyword;
+ BuiltinID = 0;
+ IsExtension = false;
+ IsPoisoned = false;
+ IsOtherTargetMacro = false;
+ IsCPPOperatorKeyword = false;
+ FETokenInfo = 0;
+}
+
+IdentifierInfo::~IdentifierInfo() {
+ delete Macro;
+}
+
+//===----------------------------------------------------------------------===//
+// IdentifierTable Implementation
+//===----------------------------------------------------------------------===//
+
+IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
+ // Start with space for 8K identifiers.
+ : HashTable(8192) {
+
+ // Populate the identifier table with info about keywords for the current
+ // language.
+ AddKeywords(LangOpts);
+}
+
+//===----------------------------------------------------------------------===//
+// Language Keyword Implementation
+//===----------------------------------------------------------------------===//
+
+/// AddKeyword - This method is used to associate a token ID with specific
+/// identifiers because they are language keywords. This causes the lexer to
+/// automatically map matching identifiers to specialized token codes.
+///
+/// The C90/C99/CPP flags are set to 0 if the token should be enabled in the
+/// specified langauge, set to 1 if it is an extension in the specified
+/// language, and set to 2 if disabled in the specified language.
+static void AddKeyword(const char *Keyword, unsigned KWLen,
+ tok::TokenKind TokenCode,
+ int C90, int C99, int CXX,
+ const LangOptions &LangOpts, IdentifierTable &Table) {
+ int Flags = LangOpts.CPlusPlus ? CXX : (LangOpts.C99 ? C99 : C90);
+
+ // Don't add this keyword if disabled in this language or if an extension
+ // and extensions are disabled.
+ if (Flags + LangOpts.NoExtensions >= 2) return;
+
+ IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
+ Info.setTokenID(TokenCode);
+ Info.setIsExtensionToken(Flags == 1);
+}
+
+static void AddAlias(const char *Keyword, unsigned KWLen,
+ const char *AliaseeKeyword, unsigned AliaseeKWLen,
+ const LangOptions &LangOpts, IdentifierTable &Table) {
+ IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
+ IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
+ AliaseeKeyword+AliaseeKWLen);
+ AliasInfo.setTokenID(AliaseeInfo.getTokenID());
+ AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
+}
+
+/// AddPPKeyword - Register a preprocessor keyword like "define" "undef" or
+/// "elif".
+static void AddPPKeyword(tok::PPKeywordKind PPID,
+ const char *Name, unsigned NameLen,
+ IdentifierTable &Table) {
+ Table.get(Name, Name+NameLen).setPPKeywordID(PPID);
+}
+
+/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
+/// representations.
+static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
+ tok::TokenKind TokenCode,
+ IdentifierTable &Table) {
+ IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
+ Info.setTokenID(TokenCode);
+ Info.setIsCPlusplusOperatorKeyword();
+}
+
+/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
+/// "property".
+static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
+ const char *Name, unsigned NameLen,
+ IdentifierTable &Table) {
+ Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
+}
+
+/// AddKeywords - Add all keywords to the symbol table.
+///
+void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
+ enum {
+ C90Shift = 0,
+ EXTC90 = 1 << C90Shift,
+ NOTC90 = 2 << C90Shift,
+ C99Shift = 2,
+ EXTC99 = 1 << C99Shift,
+ NOTC99 = 2 << C99Shift,
+ CPPShift = 4,
+ EXTCPP = 1 << CPPShift,
+ NOTCPP = 2 << CPPShift,
+ Mask = 3
+ };
+
+ // Add keywords and tokens for the current language.
+#define KEYWORD(NAME, FLAGS) \
+ AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
+ ((FLAGS) >> C90Shift) & Mask, \
+ ((FLAGS) >> C99Shift) & Mask, \
+ ((FLAGS) >> CPPShift) & Mask, LangOpts, *this);
+#define ALIAS(NAME, TOK) \
+ AddAlias(NAME, strlen(NAME), #TOK, strlen(#TOK), LangOpts, *this);
+#define PPKEYWORD(NAME) \
+ AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
+#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
+ if (LangOpts.CXXOperatorNames) \
+ AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
+#define OBJC1_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC1) \
+ AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
+#define OBJC2_AT_KEYWORD(NAME) \
+ if (LangOpts.ObjC2) \
+ AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
+#include "clang/Basic/TokenKinds.def"
+}
+
+
+//===----------------------------------------------------------------------===//
+// Stats Implementation
+//===----------------------------------------------------------------------===//
+
+/// PrintStats - Print statistics about how well the identifier table is doing
+/// at hashing identifiers.
+void IdentifierTable::PrintStats() const {
+ unsigned NumBuckets = HashTable.getNumBuckets();
+ unsigned NumIdentifiers = HashTable.getNumItems();
+ unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
+ unsigned AverageIdentifierSize = 0;
+ unsigned MaxIdentifierLength = 0;
+
+ // TODO: Figure out maximum times an identifier had to probe for -stats.
+ for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
+ I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
+ unsigned IdLen = I->getKeyLength();
+ AverageIdentifierSize += IdLen;
+ if (MaxIdentifierLength < IdLen)
+ MaxIdentifierLength = IdLen;
+ }
+
+ fprintf(stderr, "\n*** Identifier Table Stats:\n");
+ fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
+ fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
+ fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
+ NumIdentifiers/(double)NumBuckets);
+ fprintf(stderr, "Ave identifier length: %f\n",
+ (AverageIdentifierSize/(double)NumIdentifiers));
+ fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
+
+ // Compute statistics about the memory allocated for identifiers.
+ HashTable.getAllocator().PrintStats();
+}