blob: 6ab0ef1a69b1ed4e56eb480d3dd0c074591c2a8a [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
Steve Naroff4ed9d662007-09-27 14:38:14 +000036char *SelectorInfo::getName(llvm::SmallString<128> methodName) {
37 int len=0;
38 methodName[0] = '\0';
39 if (NumArgs) {
40 keyword_iterator KeyIter = keyword_begin();
41 for (unsigned int i = 0; i < NumArgs; i++) {
42 if (KeyIter[i]) {
43 methodName += KeyIter[i]->getName();
44 len += strlen(KeyIter[i]->getName());
45 }
46 methodName += ":";
47 len++;
48 }
49 } else {
50 IdentifierInfo **UnaryInfo = reinterpret_cast<IdentifierInfo **>(this+1);
51 methodName += UnaryInfo[0]->getName();
52 len += strlen(UnaryInfo[0]->getName());
53 }
54 methodName[len] = '\0';
55 return &methodName[0];
56}
57
Steve Naroff87c329f2007-08-23 18:16:40 +000058//===----------------------------------------------------------------------===//
Chris Lattner4b009652007-07-25 00:24:17 +000059// IdentifierInfo Implementation
60//===----------------------------------------------------------------------===//
61
62IdentifierInfo::IdentifierInfo() {
63 Macro = 0;
64 TokenID = tok::identifier;
65 PPID = tok::pp_not_keyword;
66 ObjCID = tok::objc_not_keyword;
67 BuiltinID = 0;
68 IsExtension = false;
69 IsPoisoned = false;
70 IsOtherTargetMacro = false;
71 IsCPPOperatorKeyword = false;
72 IsNonPortableBuiltin = false;
73 FETokenInfo = 0;
74}
75
76IdentifierInfo::~IdentifierInfo() {
77 delete Macro;
78}
79
80//===----------------------------------------------------------------------===//
81// IdentifierTable Implementation
82//===----------------------------------------------------------------------===//
83
84IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
85 // Start with space for 8K identifiers.
86 : HashTable(8192) {
87
88 // Populate the identifier table with info about keywords for the current
89 // language.
90 AddKeywords(LangOpts);
91}
92
93//===----------------------------------------------------------------------===//
94// Language Keyword Implementation
95//===----------------------------------------------------------------------===//
96
97/// AddKeyword - This method is used to associate a token ID with specific
98/// identifiers because they are language keywords. This causes the lexer to
99/// automatically map matching identifiers to specialized token codes.
100///
101/// The C90/C99/CPP/CPP0x flags are set to 0 if the token should be
102/// enabled in the specified langauge, set to 1 if it is an extension
103/// in the specified language, and set to 2 if disabled in the
104/// specified language.
105static void AddKeyword(const char *Keyword, unsigned KWLen,
106 tok::TokenKind TokenCode,
107 int C90, int C99, int CXX, int CXX0x,
108 const LangOptions &LangOpts, IdentifierTable &Table) {
109 int Flags = LangOpts.CPlusPlus ? (LangOpts.CPlusPlus0x? CXX0x : CXX)
110 : (LangOpts.C99 ? C99 : C90);
111
112 // Don't add this keyword if disabled in this language or if an extension
113 // and extensions are disabled.
114 if (Flags + LangOpts.NoExtensions >= 2) return;
115
116 IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
117 Info.setTokenID(TokenCode);
118 Info.setIsExtensionToken(Flags == 1);
119}
120
121static void AddAlias(const char *Keyword, unsigned KWLen,
122 const char *AliaseeKeyword, unsigned AliaseeKWLen,
123 const LangOptions &LangOpts, IdentifierTable &Table) {
124 IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
125 IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
126 AliaseeKeyword+AliaseeKWLen);
127 AliasInfo.setTokenID(AliaseeInfo.getTokenID());
128 AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
129}
130
131/// AddPPKeyword - Register a preprocessor keyword like "define" "undef" or
132/// "elif".
133static void AddPPKeyword(tok::PPKeywordKind PPID,
134 const char *Name, unsigned NameLen,
135 IdentifierTable &Table) {
136 Table.get(Name, Name+NameLen).setPPKeywordID(PPID);
137}
138
139/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
140/// representations.
141static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
142 tok::TokenKind TokenCode,
143 IdentifierTable &Table) {
144 IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
145 Info.setTokenID(TokenCode);
146 Info.setIsCPlusplusOperatorKeyword();
147}
148
149/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
150/// "property".
151static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
152 const char *Name, unsigned NameLen,
153 IdentifierTable &Table) {
154 Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
155}
156
157/// AddKeywords - Add all keywords to the symbol table.
158///
159void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
160 enum {
161 C90Shift = 0,
162 EXTC90 = 1 << C90Shift,
163 NOTC90 = 2 << C90Shift,
164 C99Shift = 2,
165 EXTC99 = 1 << C99Shift,
166 NOTC99 = 2 << C99Shift,
167 CPPShift = 4,
168 EXTCPP = 1 << CPPShift,
169 NOTCPP = 2 << CPPShift,
170 CPP0xShift = 6,
171 EXTCPP0x = 1 << CPP0xShift,
172 NOTCPP0x = 2 << CPP0xShift,
173 Mask = 3
174 };
175
176 // Add keywords and tokens for the current language.
177#define KEYWORD(NAME, FLAGS) \
178 AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
179 ((FLAGS) >> C90Shift) & Mask, \
180 ((FLAGS) >> C99Shift) & Mask, \
181 ((FLAGS) >> CPPShift) & Mask, \
182 ((FLAGS) >> CPP0xShift) & Mask, LangOpts, *this);
183#define ALIAS(NAME, TOK) \
184 AddAlias(NAME, strlen(NAME), #TOK, strlen(#TOK), LangOpts, *this);
185#define PPKEYWORD(NAME) \
186 AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
187#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
188 if (LangOpts.CXXOperatorNames) \
189 AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
190#define OBJC1_AT_KEYWORD(NAME) \
191 if (LangOpts.ObjC1) \
192 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
193#define OBJC2_AT_KEYWORD(NAME) \
194 if (LangOpts.ObjC2) \
195 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
196#include "clang/Basic/TokenKinds.def"
197}
198
199
200//===----------------------------------------------------------------------===//
201// Stats Implementation
202//===----------------------------------------------------------------------===//
203
204/// PrintStats - Print statistics about how well the identifier table is doing
205/// at hashing identifiers.
206void IdentifierTable::PrintStats() const {
207 unsigned NumBuckets = HashTable.getNumBuckets();
208 unsigned NumIdentifiers = HashTable.getNumItems();
209 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
210 unsigned AverageIdentifierSize = 0;
211 unsigned MaxIdentifierLength = 0;
212
213 // TODO: Figure out maximum times an identifier had to probe for -stats.
214 for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
215 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
216 unsigned IdLen = I->getKeyLength();
217 AverageIdentifierSize += IdLen;
218 if (MaxIdentifierLength < IdLen)
219 MaxIdentifierLength = IdLen;
220 }
221
222 fprintf(stderr, "\n*** Identifier Table Stats:\n");
223 fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
224 fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
225 fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
226 NumIdentifiers/(double)NumBuckets);
227 fprintf(stderr, "Ave identifier length: %f\n",
228 (AverageIdentifierSize/(double)NumIdentifiers));
229 fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
230
231 // Compute statistics about the memory allocated for identifiers.
232 HashTable.getAllocator().PrintStats();
233}
Steve Naroff4ed9d662007-09-27 14:38:14 +0000234