blob: d3faeb58dba50fe40a0d6689e25e38b061508d17 [file] [log] [blame]
Chris Lattnerec659fc2006-10-29 22:09:44 +00001//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
Chris Lattner22eb9722006-06-18 05:43:12 +00002//
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//
Chris Lattnerc79f6fb2006-07-04 17:53:21 +000010// This file implements the IdentifierInfo, IdentifierVisitor, and
Chris Lattner91cbf112006-07-03 04:28:52 +000011// IdentifierTable interfaces.
Chris Lattner22eb9722006-06-18 05:43:12 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Lex/IdentifierTable.h"
16#include "clang/Lex/MacroInfo.h"
Chris Lattner25e0d542006-10-18 06:07:05 +000017#include "clang/Basic/LangOptions.h"
Chris Lattner22eb9722006-06-18 05:43:12 +000018using namespace clang;
19
20//===----------------------------------------------------------------------===//
Steve Naroff7c348172007-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 Lattnerc79f6fb2006-07-04 17:53:21 +000037// IdentifierInfo Implementation
Chris Lattner22eb9722006-06-18 05:43:12 +000038//===----------------------------------------------------------------------===//
39
Chris Lattner3bc804e2006-10-28 23:46:24 +000040IdentifierInfo::IdentifierInfo() {
41 Macro = 0;
42 TokenID = tok::identifier;
43 PPID = tok::pp_not_keyword;
44 ObjCID = tok::objc_not_keyword;
Chris Lattner9561a0b2007-01-28 08:20:04 +000045 BuiltinID = 0;
Chris Lattner3bc804e2006-10-28 23:46:24 +000046 IsExtension = false;
47 IsPoisoned = false;
48 IsOtherTargetMacro = false;
Chris Lattner5b9f4892006-11-21 17:23:33 +000049 IsCPPOperatorKeyword = false;
Chris Lattner5e629292007-07-19 00:11:19 +000050 IsNonPortableBuiltin = false;
Chris Lattner3bc804e2006-10-28 23:46:24 +000051 FETokenInfo = 0;
52}
53
54IdentifierInfo::~IdentifierInfo() {
Chris Lattner22eb9722006-06-18 05:43:12 +000055 delete Macro;
56}
57
Chris Lattner91cbf112006-07-03 04:28:52 +000058//===----------------------------------------------------------------------===//
Chris Lattner22eb9722006-06-18 05:43:12 +000059// IdentifierTable Implementation
60//===----------------------------------------------------------------------===//
61
Chris Lattner2b9e19b2006-10-29 23:43:13 +000062IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
63 // Start with space for 8K identifiers.
64 : HashTable(8192) {
Chris Lattnerda933aa2006-10-29 23:49:15 +000065
Chris Lattnerf2e3ac32006-10-27 03:59:10 +000066 // Populate the identifier table with info about keywords for the current
67 // language.
Chris Lattner25e0d542006-10-18 06:07:05 +000068 AddKeywords(LangOpts);
Chris Lattner91cbf112006-07-03 04:28:52 +000069}
Chris Lattner22eb9722006-06-18 05:43:12 +000070
Chris Lattner25e0d542006-10-18 06:07:05 +000071//===----------------------------------------------------------------------===//
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///
Chris Lattner539007a2007-07-16 04:18:29 +000079/// 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.
Chris Lattner2b9e19b2006-10-29 23:43:13 +000083static void AddKeyword(const char *Keyword, unsigned KWLen,
84 tok::TokenKind TokenCode,
Chris Lattner539007a2007-07-16 04:18:29 +000085 int C90, int C99, int CXX, int CXX0x,
Chris Lattner25e0d542006-10-18 06:07:05 +000086 const LangOptions &LangOpts, IdentifierTable &Table) {
Chris Lattner539007a2007-07-16 04:18:29 +000087 int Flags = LangOpts.CPlusPlus ? (LangOpts.CPlusPlus0x? CXX0x : CXX)
88 : (LangOpts.C99 ? C99 : C90);
Chris Lattner25e0d542006-10-18 06:07:05 +000089
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
Chris Lattner2b9e19b2006-10-29 23:43:13 +000094 IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
Chris Lattner25e0d542006-10-18 06:07:05 +000095 Info.setTokenID(TokenCode);
96 Info.setIsExtensionToken(Flags == 1);
97}
98
Chris Lattnere8b27242007-06-08 17:27:55 +000099static 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
Chris Lattner25e0d542006-10-18 06:07:05 +0000109/// 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
Chris Lattner5b9f4892006-11-21 17:23:33 +0000117/// 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
Chris Lattner25e0d542006-10-18 06:07:05 +0000127/// 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,
Chris Lattner539007a2007-07-16 04:18:29 +0000148 CPP0xShift = 6,
149 EXTCPP0x = 1 << CPP0xShift,
150 NOTCPP0x = 2 << CPP0xShift,
Chris Lattner25e0d542006-10-18 06:07:05 +0000151 Mask = 3
152 };
153
154 // Add keywords and tokens for the current language.
155#define KEYWORD(NAME, FLAGS) \
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000156 AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
Chris Lattner25e0d542006-10-18 06:07:05 +0000157 ((FLAGS) >> C90Shift) & Mask, \
158 ((FLAGS) >> C99Shift) & Mask, \
Chris Lattner539007a2007-07-16 04:18:29 +0000159 ((FLAGS) >> CPPShift) & Mask, \
160 ((FLAGS) >> CPP0xShift) & Mask, LangOpts, *this);
Chris Lattner25e0d542006-10-18 06:07:05 +0000161#define ALIAS(NAME, TOK) \
Chris Lattnere8b27242007-06-08 17:27:55 +0000162 AddAlias(NAME, strlen(NAME), #TOK, strlen(#TOK), LangOpts, *this);
Chris Lattner25e0d542006-10-18 06:07:05 +0000163#define PPKEYWORD(NAME) \
164 AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
Chris Lattner5b9f4892006-11-21 17:23:33 +0000165#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
Chris Lattner3e7592e2006-12-04 07:48:37 +0000166 if (LangOpts.CXXOperatorNames) \
Chris Lattner5b9f4892006-11-21 17:23:33 +0000167 AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
Chris Lattner25e0d542006-10-18 06:07:05 +0000168#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
Chris Lattner22eb9722006-06-18 05:43:12 +0000182/// PrintStats - Print statistics about how well the identifier table is doing
183/// at hashing identifiers.
184void IdentifierTable::PrintStats() const {
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000185 unsigned NumBuckets = HashTable.getNumBuckets();
186 unsigned NumIdentifiers = HashTable.getNumItems();
187 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
Chris Lattner22eb9722006-06-18 05:43:12 +0000188 unsigned AverageIdentifierSize = 0;
189 unsigned MaxIdentifierLength = 0;
190
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000191 // TODO: Figure out maximum times an identifier had to probe for -stats.
Chris Lattner23b7eb62007-06-15 23:05:46 +0000192 for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
Chris Lattnerb055f2d2007-02-11 08:19:57 +0000193 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 }
Chris Lattner22eb9722006-06-18 05:43:12 +0000199
Chris Lattner23b7eb62007-06-15 23:05:46 +0000200 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);
Chris Lattner22eb9722006-06-18 05:43:12 +0000208
209 // Compute statistics about the memory allocated for identifiers.
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000210 HashTable.getAllocator().PrintStats();
Chris Lattner22eb9722006-06-18 05:43:12 +0000211}