IdentifierTable.h revision 0f84c0059cec39fd1c73ac05bc2864dca664e7f4
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
55f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// This file was developed by Chris Lattner and is distributed under
65f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer// the University of Illinois Open Source License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
10c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner// This file defines the IdentifierInfo, IdentifierTable, and Selector
11c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner// interfaces.
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
15c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
16c7229c338c21ef26b01ef3ecf9eec4fd373fa9ecChris Lattner#define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/TokenKinds.h"
195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/ADT/StringMap.h"
2068d331a78e655d97294e94fcfa63f92cc1f40578Steve Naroff#include "llvm/ADT/SmallString.h"
2193a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek#include "llvm/Bitcode/SerializationFwd.h"
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <string>
239dc62f044a6ba21f503bd56607d94b32704e7945Chris Lattner#include <cassert>
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2585994260c41a54cab061a434ed378fc448333a4eChris Lattnernamespace llvm {
2685994260c41a54cab061a434ed378fc448333a4eChris Lattner  template <typename T> struct DenseMapInfo;
2785994260c41a54cab061a434ed378fc448333a4eChris Lattner}
2829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencernamespace clang {
30b8128140956c6f8f0ab143818775a81f4b4aa477Chris Lattner  struct LangOptions;
3185994260c41a54cab061a434ed378fc448333a4eChris Lattner  class MultiKeywordSelector; // a private class used by Selector.
325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// IdentifierInfo - One of these records is kept for each identifier that
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is lexed.  This contains information about whether the token was #define'd,
355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// is a language keyword, or if it is a front-end token of some sort (e.g. a
365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// variable or function name).  The preprocessor keeps this information in a
375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// set, and all tok::identifier tokens have a pointer to one of these.
385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass IdentifierInfo {
395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  tok::TokenKind TokenID      : 8; // Front-end token ID or tok::identifier.
404365a7e46822700357a272d839ee2656d9603d5aChris Lattner  unsigned BuiltinID          : 9; // ID if this is a builtin (__builtin_inf).
415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  tok::ObjCKeywordKind ObjCID : 5; // ID for objc @ keyword like @'protocol'.
424365a7e46822700357a272d839ee2656d9603d5aChris Lattner  bool HasMacro               : 1; // True if there is a #define for this.
435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsExtension            : 1; // True if identifier is a lang extension.
445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsPoisoned             : 1; // True if identifier is poisoned.
455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsOtherTargetMacro     : 1; // True if ident is macro on another target.
465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsCPPOperatorKeyword   : 1; // True if ident is a C++ operator keyword.
475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool IsNonPortableBuiltin   : 1; // True if builtin varies across targets.
482d29581d2b7ad5ec5df6ff3947fb0711339361a4Chris Lattner  // 4 bits left in 32-bit word.
495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void *FETokenInfo;               // Managed by the language front-end.
505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo(const IdentifierInfo&);  // NONCOPYABLE.
514365a7e46822700357a272d839ee2656d9603d5aChris Lattner  void operator=(const IdentifierInfo&);  // NONASSIGNABLE.
525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo();
545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
553f128ad2691d299b96663da85a9e069c4081ea7cSteve Naroff  /// getName - Return the actual string for this identifier.  The returned
563f128ad2691d299b96663da85a9e069c4081ea7cSteve Naroff  /// string is properly null terminated.
575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  const char *getName() const {
591f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    // We know that this is embedded into a StringMapEntry, and it knows how to
601f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    // efficiently find the string.
611f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    return llvm::StringMapEntry<IdentifierInfo>::
621f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner                  GetStringMapEntryFromValue(*this).getKeyData();
631f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  }
641f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner
651f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  /// getLength - Efficiently return the length of this identifier info.
661f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  ///
671f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner  unsigned getLength() const {
681f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner    return llvm::StringMapEntry<IdentifierInfo>::
691f945f632ae993bbb9f9e69d908f7526924c1a88Chris Lattner                    GetStringMapEntryFromValue(*this).getKeyLength();
705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
729c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  /// hasMacroDefinition - Return true if this identifier is #defined to some
739c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  /// other value.
749c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  bool hasMacroDefinition() const {
759c46de446d18f4a28446cb798d4131bd05515699Chris Lattner    return HasMacro;
769c46de446d18f4a28446cb798d4131bd05515699Chris Lattner  }
77cc1a875f94630e58d24a55577ffbf0e89b7da8c7Chris Lattner  void setHasMacroDefinition(bool Val) { HasMacro = Val; }
785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// get/setTokenID - If this is a source-language token (e.g. 'for'), this API
805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// can be used to cause the lexer to map identifiers to source-language
815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// tokens.
825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  tok::TokenKind getTokenID() const { return TokenID; }
835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setTokenID(tok::TokenKind ID) { TokenID = ID; }
845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
866d9a3e648d6bf6b347174152f191bd1377528f8cChris Lattner  /// For example, "define" will return tok::pp_define.
87387b98d37e08f7aa9ddf23e067e1d27e39ce16f3Chris Lattner  tok::PPKeywordKind getPPKeywordID() const;
885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getObjCKeywordID - Return the Objective-C keyword ID for the this
905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// identifier.  For example, 'class' will return tok::objc_class if ObjC is
915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// enabled.
925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  tok::ObjCKeywordKind getObjCKeywordID() const { return ObjCID; }
935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCID = ID; }
945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getBuiltinID - Return a value indicating whether this is a builtin
965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// function.  0 is not-built-in.  1 is builtin-for-some-nonprimary-target.
975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// 2+ are specific builtin functions.
985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned getBuiltinID() const { return BuiltinID; }
995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setBuiltinID(unsigned ID) {
1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    BuiltinID = ID;
101adb83b41cb00acac7a9c035996318d88ecf2e6c8Chris Lattner    assert(BuiltinID == ID && "ID too large for field!");
1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// isNonPortableBuiltin - Return true if this identifier corresponds to a
1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// builtin on some other target, but isn't one on this target, or if it is on
1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// the target but not on another, or if it is on both but it differs somehow
1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// in behavior.
1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isNonPortableBuiltin() const { return IsNonPortableBuiltin; }
1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setNonPortableBuiltin(bool Val) { IsNonPortableBuiltin = Val; }
1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// get/setExtension - Initialize information about whether or not this
1125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// language token is an extension.  This controls extension warnings, and is
1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// only valid if a custom token ID is set.
1145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isExtensionToken() const { return IsExtension; }
1155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setIsExtensionToken(bool Val) { IsExtension = Val; }
1165f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// setIsPoisoned - Mark this identifier as poisoned.  After poisoning, the
1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// Preprocessor will emit an error every time this token is used.
1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setIsPoisoned(bool Value = true) { IsPoisoned = Value; }
1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// isPoisoned - Return true if this token has been poisoned.
1225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isPoisoned() const { return IsPoisoned; }
1235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// setIsOtherTargetMacro/isOtherTargetMacro control whether this identifier
1255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// is seen as being a macro on some other target.
1265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setIsOtherTargetMacro(bool Val = true) { IsOtherTargetMacro = Val; }
1275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isOtherTargetMacro() const { return IsOtherTargetMacro; }
1285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
1305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// this identifier is a C++ alternate representation of an operator.
131c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  void setIsCPlusPlusOperatorKeyword(bool Val = true)
1325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    { IsCPPOperatorKeyword = Val; }
1335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
1345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to
1365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// associate arbitrary metadata with this token.
1375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  template<typename T>
1385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); }
1395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void setFETokenInfo(void *T) { FETokenInfo = T; }
14093a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
14193a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  /// Emit - Serialize this IdentifierInfo to a bitstream.
14293a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  void Emit(llvm::Serializer& S) const;
14393a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
14493a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  /// Read - Deserialize an IdentifierInfo object from a bitstream.
14593a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  void Read(llvm::Deserializer& D);
1465f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
1475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// IdentifierTable - This table implements an efficient mapping from strings to
1495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// IdentifierInfo nodes.  It has no other purpose, but this is an
1505f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// extremely performance-critical piece of the code, as each occurrance of
1515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// every identifier goes through here when lexed.
1525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerclass IdentifierTable {
1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Shark shows that using MallocAllocator is *much* slower than using this
1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // BumpPtrAllocator!
1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  typedef llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator> HashTableTy;
1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  HashTableTy HashTable;
1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerpublic:
1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// IdentifierTable ctor - Create the identifier table, populating it with
1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// info about the language keywords for the language specified by LangOpts.
1605f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierTable(const LangOptions &LangOpts);
1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1625f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// get - Return the identifier token info for the specified named identifier.
1635f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  ///
1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo &get(const char *NameStart, const char *NameEnd) {
1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return HashTable.GetOrCreateValue(NameStart, NameEnd).getValue();
1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1675f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo &get(const char *Name) {
1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return get(Name, Name+strlen(Name));
1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  IdentifierInfo &get(const std::string &Name) {
1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    // Don't use c_str() here: no need to be null terminated.
1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    const char *NameBytes = &Name[0];
1745f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    return get(NameBytes, NameBytes+Name.size());
1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  typedef HashTableTy::const_iterator iterator;
1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  typedef HashTableTy::const_iterator const_iterator;
1795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  iterator begin() const { return HashTable.begin(); }
1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  iterator end() const   { return HashTable.end(); }
1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
183c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  unsigned size() const { return HashTable.size(); }
184c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek
1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// PrintStats - Print some statistics to stderr that indicate how well the
1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  /// hashing is doing.
1875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void PrintStats() const;
188bfa82c4c23ce96fdcf357a8f7ef70a9b71b69144Ted Kremenek
1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  void AddKeywords(const LangOptions &LangOpts);
190c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek
19193a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  /// Emit - Serialize this IdentifierTable to a bitstream.  This should
19293a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  ///  be called AFTER objects that externally reference the identifiers in the
19393a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  ///  table have been serialized.  This is because only the identifiers that
19493a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  ///  are actually referenced are serialized.
19593a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  void Emit(llvm::Serializer& S) const;
19693a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
1970f84c0059cec39fd1c73ac05bc2864dca664e7f4Ted Kremenek  /// Create - Deserialize an IdentifierTable from a bitstream.
1980f84c0059cec39fd1c73ac05bc2864dca664e7f4Ted Kremenek  static IdentifierTable* Create(llvm::Deserializer& D);
19993a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek
200c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenekprivate:
201c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  /// This ctor is not intended to be used by anyone except for object
202c637e6b7afeebc6b4f751e4373715b6a8ea77272Ted Kremenek  /// serialization.
20393a9ab4bdc607b12fdcf6aa5cf56950dd45ae0f5Ted Kremenek  IdentifierTable();
2045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer};
2055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
20629238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// Selector - This smart pointer class efficiently represents Objective-C
20729238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// method names. This class will either point to an IdentifierInfo or a
20829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// MultiKeywordSelector (which is private). This enables us to optimize
20929238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// selectors that no arguments and selectors that take 1 argument, which
21029238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// accounts for 78% of all selectors in Cocoa.h.
211bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroffclass Selector {
212bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  enum IdentifierInfoFlag {
2130e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    // MultiKeywordSelector = 0.
214bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    ZeroArg  = 0x1,
215bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    OneArg   = 0x2,
216bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    ArgFlags = ZeroArg|OneArg
217bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  };
218bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo.
219bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff
220bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  Selector(IdentifierInfo *II, unsigned nArgs) {
221bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    InfoPtr = reinterpret_cast<uintptr_t>(II);
2220e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
2230e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    assert(nArgs < 2 && "nArgs not equal to 0/1");
2240e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    InfoPtr |= nArgs+1;
225bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
226bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  Selector(MultiKeywordSelector *SI) {
227bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    InfoPtr = reinterpret_cast<uintptr_t>(SI);
2280e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
229bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
23085994260c41a54cab061a434ed378fc448333a4eChris Lattner  Selector(intptr_t V) : InfoPtr(V) {}
23129238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroffpublic:
23229238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  friend class SelectorTable; // only the SelectorTable can create these.
233bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff
234bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  IdentifierInfo *getAsIdentifierInfo() const {
2350e2dfd3963465d238e791eb8996e4d49fa47b615Chris Lattner    if (getIdentifierInfoFlag())
236bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff      return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags);
237bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return 0;
238bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
239bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  unsigned getIdentifierInfoFlag() const {
240bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return InfoPtr & ArgFlags;
241bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
242bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  /// operator==/!= - Indicate whether the specified selectors are identical.
243bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool operator==(const Selector &RHS) const {
244bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return InfoPtr == RHS.InfoPtr;
245bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
246bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool operator!=(const Selector &RHS) const {
247bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return InfoPtr != RHS.InfoPtr;
248bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
249bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  void *getAsOpaquePtr() const {
250bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return reinterpret_cast<void*>(InfoPtr);
251bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
252bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  // Predicates to identify the selector type.
253bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool isKeywordSelector() const {
254bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return getIdentifierInfoFlag() != ZeroArg;
255bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
256bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  bool isUnarySelector() const {
257bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff    return getIdentifierInfoFlag() == ZeroArg;
258bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff  }
2595b6b72f53ad164497cf62484b60cdbb4361f1978Steve Naroff  unsigned getNumArgs() const;
260f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
2615b6b72f53ad164497cf62484b60cdbb4361f1978Steve Naroff
262f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  /// getName - Derive the full selector name (e.g. "foo:bar:") and return it.
263f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  ///
264f836e3fea2c77fdbb18170fb313ee0d45551320bChris Lattner  std::string getName() const;
26585994260c41a54cab061a434ed378fc448333a4eChris Lattner
26685994260c41a54cab061a434ed378fc448333a4eChris Lattner  static Selector getEmptyMarker() {
26785994260c41a54cab061a434ed378fc448333a4eChris Lattner    return Selector(uintptr_t(-1));
26885994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
26985994260c41a54cab061a434ed378fc448333a4eChris Lattner  static Selector getTombstoneMarker() {
27085994260c41a54cab061a434ed378fc448333a4eChris Lattner    return Selector(uintptr_t(-2));
27185994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
272bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff};
273bcfb06ac6da1aa3c74ac1ef7a49c2807522366e7Steve Naroff
27429238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// SelectorTable - This table allows us to fully hide how we implement
27529238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff/// multi-keyword caching.
27629238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroffclass SelectorTable {
27729238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  void *Impl;  // Actually a FoldingSet<MultiKeywordSelector>*
27829238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  SelectorTable(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
27929238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  void operator=(const SelectorTable&); // DISABLED: DO NOT IMPLEMENT
28029238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroffpublic:
28129238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  SelectorTable();
28229238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff  ~SelectorTable();
28329238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
284ff38491c18b060526d754765b952f4a497a89416Chris Lattner  /// getSelector - This can create any sort of selector.  NumArgs indicates
285ff38491c18b060526d754765b952f4a497a89416Chris Lattner  /// whether this is a no argument selector "foo", a single argument selector
286ff38491c18b060526d754765b952f4a497a89416Chris Lattner  /// "foo:" or multi-argument "foo:bar:".
287ff38491c18b060526d754765b952f4a497a89416Chris Lattner  Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
288ff38491c18b060526d754765b952f4a497a89416Chris Lattner
289ff38491c18b060526d754765b952f4a497a89416Chris Lattner  Selector getUnarySelector(IdentifierInfo *ID) {
290ff38491c18b060526d754765b952f4a497a89416Chris Lattner    return Selector(ID, 1);
291ff38491c18b060526d754765b952f4a497a89416Chris Lattner  }
292ff38491c18b060526d754765b952f4a497a89416Chris Lattner  Selector getNullarySelector(IdentifierInfo *ID) {
293ff38491c18b060526d754765b952f4a497a89416Chris Lattner    return Selector(ID, 0);
294ff38491c18b060526d754765b952f4a497a89416Chris Lattner  }
29529238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff};
29629238a0bf7cbf5b396efb451a0adb5fe4aa037caSteve Naroff
2975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}  // end namespace clang
2985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
2994365a7e46822700357a272d839ee2656d9603d5aChris Lattner
3004365a7e46822700357a272d839ee2656d9603d5aChris Lattner/// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
3014365a7e46822700357a272d839ee2656d9603d5aChris Lattner/// DenseSets.
30285994260c41a54cab061a434ed378fc448333a4eChris Lattnernamespace llvm {
30385994260c41a54cab061a434ed378fc448333a4eChris Lattnertemplate <>
30485994260c41a54cab061a434ed378fc448333a4eChris Lattnerstruct DenseMapInfo<clang::Selector> {
30585994260c41a54cab061a434ed378fc448333a4eChris Lattner  static inline clang::Selector getEmptyKey() {
30685994260c41a54cab061a434ed378fc448333a4eChris Lattner    return clang::Selector::getEmptyMarker();
30785994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
30885994260c41a54cab061a434ed378fc448333a4eChris Lattner  static inline clang::Selector getTombstoneKey() {
30985994260c41a54cab061a434ed378fc448333a4eChris Lattner    return clang::Selector::getTombstoneMarker();
31085994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
31185994260c41a54cab061a434ed378fc448333a4eChris Lattner
31285994260c41a54cab061a434ed378fc448333a4eChris Lattner  static unsigned getHashValue(clang::Selector S);
31385994260c41a54cab061a434ed378fc448333a4eChris Lattner
31485994260c41a54cab061a434ed378fc448333a4eChris Lattner  static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
31585994260c41a54cab061a434ed378fc448333a4eChris Lattner    return LHS == RHS;
31685994260c41a54cab061a434ed378fc448333a4eChris Lattner  }
31785994260c41a54cab061a434ed378fc448333a4eChris Lattner
31885994260c41a54cab061a434ed378fc448333a4eChris Lattner  static bool isPod() { return true; }
31985994260c41a54cab061a434ed378fc448333a4eChris Lattner};
32085994260c41a54cab061a434ed378fc448333a4eChris Lattner}  // end namespace llvm
32185994260c41a54cab061a434ed378fc448333a4eChris Lattner
3225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#endif
323