blob: d3faeb58dba50fe40a0d6689e25e38b061508d17 [file] [log] [blame]
Chris Lattner4b009652007-07-25 00:24:17 +00001//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the IdentifierInfo, IdentifierVisitor, and
11// IdentifierTable interfaces.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Lex/IdentifierTable.h"
16#include "clang/Lex/MacroInfo.h"
17#include "clang/Basic/LangOptions.h"
18using namespace clang;
19
20//===----------------------------------------------------------------------===//
Steve Naroff87c329f2007-08-23 18:16:40 +000021// Token Implementation
22//===----------------------------------------------------------------------===//
23
24/// isObjCAtKeyword - Return true if we have an ObjC keyword identifier.
25bool Token::isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const {
26 return getKind() == tok::identifier &&
27 getIdentifierInfo()->getObjCKeywordID() == objcKey;
28}
29
30/// getObjCKeywordID - Return the ObjC keyword kind.
31tok::ObjCKeywordKind Token::getObjCKeywordID() const {
32 IdentifierInfo *specId = getIdentifierInfo();
33 return specId ? specId->getObjCKeywordID() : tok::objc_not_keyword;
34}
35
36//===----------------------------------------------------------------------===//
Chris Lattner4b009652007-07-25 00:24:17 +000037// IdentifierInfo Implementation
38//===----------------------------------------------------------------------===//
39
40IdentifierInfo::IdentifierInfo() {
41 Macro = 0;
42 TokenID = tok::identifier;
43 PPID = tok::pp_not_keyword;
44 ObjCID = tok::objc_not_keyword;
45 BuiltinID = 0;
46 IsExtension = false;
47 IsPoisoned = false;
48 IsOtherTargetMacro = false;
49 IsCPPOperatorKeyword = false;
50 IsNonPortableBuiltin = false;
51 FETokenInfo = 0;
52}
53
54IdentifierInfo::~IdentifierInfo() {
55 delete Macro;
56}
57
58//===----------------------------------------------------------------------===//
59// IdentifierTable Implementation
60//===----------------------------------------------------------------------===//
61
62IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
63 // Start with space for 8K identifiers.
64 : HashTable(8192) {
65
66 // Populate the identifier table with info about keywords for the current
67 // language.
68 AddKeywords(LangOpts);
69}
70
71//===----------------------------------------------------------------------===//
72// Language Keyword Implementation
73//===----------------------------------------------------------------------===//
74
75/// AddKeyword - This method is used to associate a token ID with specific
76/// identifiers because they are language keywords. This causes the lexer to
77/// automatically map matching identifiers to specialized token codes.
78///
79/// The C90/C99/CPP/CPP0x flags are set to 0 if the token should be
80/// enabled in the specified langauge, set to 1 if it is an extension
81/// in the specified language, and set to 2 if disabled in the
82/// specified language.
83static void AddKeyword(const char *Keyword, unsigned KWLen,
84 tok::TokenKind TokenCode,
85 int C90, int C99, int CXX, int CXX0x,
86 const LangOptions &LangOpts, IdentifierTable &Table) {
87 int Flags = LangOpts.CPlusPlus ? (LangOpts.CPlusPlus0x? CXX0x : CXX)
88 : (LangOpts.C99 ? C99 : C90);
89
90 // Don't add this keyword if disabled in this language or if an extension
91 // and extensions are disabled.
92 if (Flags + LangOpts.NoExtensions >= 2) return;
93
94 IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
95 Info.setTokenID(TokenCode);
96 Info.setIsExtensionToken(Flags == 1);
97}
98
99static void AddAlias(const char *Keyword, unsigned KWLen,
100 const char *AliaseeKeyword, unsigned AliaseeKWLen,
101 const LangOptions &LangOpts, IdentifierTable &Table) {
102 IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
103 IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
104 AliaseeKeyword+AliaseeKWLen);
105 AliasInfo.setTokenID(AliaseeInfo.getTokenID());
106 AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
107}
108
109/// AddPPKeyword - Register a preprocessor keyword like "define" "undef" or
110/// "elif".
111static void AddPPKeyword(tok::PPKeywordKind PPID,
112 const char *Name, unsigned NameLen,
113 IdentifierTable &Table) {
114 Table.get(Name, Name+NameLen).setPPKeywordID(PPID);
115}
116
117/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
118/// representations.
119static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
120 tok::TokenKind TokenCode,
121 IdentifierTable &Table) {
122 IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
123 Info.setTokenID(TokenCode);
124 Info.setIsCPlusplusOperatorKeyword();
125}
126
127/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
128/// "property".
129static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
130 const char *Name, unsigned NameLen,
131 IdentifierTable &Table) {
132 Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
133}
134
135/// AddKeywords - Add all keywords to the symbol table.
136///
137void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
138 enum {
139 C90Shift = 0,
140 EXTC90 = 1 << C90Shift,
141 NOTC90 = 2 << C90Shift,
142 C99Shift = 2,
143 EXTC99 = 1 << C99Shift,
144 NOTC99 = 2 << C99Shift,
145 CPPShift = 4,
146 EXTCPP = 1 << CPPShift,
147 NOTCPP = 2 << CPPShift,
148 CPP0xShift = 6,
149 EXTCPP0x = 1 << CPP0xShift,
150 NOTCPP0x = 2 << CPP0xShift,
151 Mask = 3
152 };
153
154 // Add keywords and tokens for the current language.
155#define KEYWORD(NAME, FLAGS) \
156 AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
157 ((FLAGS) >> C90Shift) & Mask, \
158 ((FLAGS) >> C99Shift) & Mask, \
159 ((FLAGS) >> CPPShift) & Mask, \
160 ((FLAGS) >> CPP0xShift) & Mask, LangOpts, *this);
161#define ALIAS(NAME, TOK) \
162 AddAlias(NAME, strlen(NAME), #TOK, strlen(#TOK), LangOpts, *this);
163#define PPKEYWORD(NAME) \
164 AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
165#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
166 if (LangOpts.CXXOperatorNames) \
167 AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
168#define OBJC1_AT_KEYWORD(NAME) \
169 if (LangOpts.ObjC1) \
170 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
171#define OBJC2_AT_KEYWORD(NAME) \
172 if (LangOpts.ObjC2) \
173 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
174#include "clang/Basic/TokenKinds.def"
175}
176
177
178//===----------------------------------------------------------------------===//
179// Stats Implementation
180//===----------------------------------------------------------------------===//
181
182/// PrintStats - Print statistics about how well the identifier table is doing
183/// at hashing identifiers.
184void IdentifierTable::PrintStats() const {
185 unsigned NumBuckets = HashTable.getNumBuckets();
186 unsigned NumIdentifiers = HashTable.getNumItems();
187 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
188 unsigned AverageIdentifierSize = 0;
189 unsigned MaxIdentifierLength = 0;
190
191 // TODO: Figure out maximum times an identifier had to probe for -stats.
192 for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
193 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
194 unsigned IdLen = I->getKeyLength();
195 AverageIdentifierSize += IdLen;
196 if (MaxIdentifierLength < IdLen)
197 MaxIdentifierLength = IdLen;
198 }
199
200 fprintf(stderr, "\n*** Identifier Table Stats:\n");
201 fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
202 fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
203 fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
204 NumIdentifiers/(double)NumBuckets);
205 fprintf(stderr, "Ave identifier length: %f\n",
206 (AverageIdentifierSize/(double)NumIdentifiers));
207 fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
208
209 // Compute statistics about the memory allocated for identifiers.
210 HashTable.getAllocator().PrintStats();
211}