//===- IdentifierTable.h - Hash table for identifier lookup -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file /// Defines the clang::IdentifierInfo, clang::IdentifierTable, and /// clang::Selector interfaces. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H #include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/TokenKinds.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include "llvm/Support/type_traits.h" #include <cassert> #include <cstddef> #include <cstdint> #include <cstring> #include <string> #include <utility> namespace clang { class DeclarationName; class DeclarationNameTable; class IdentifierInfo; class LangOptions; class MultiKeywordSelector; class SourceLocation; enum class ReservedIdentifierStatus { … }; enum class ReservedLiteralSuffixIdStatus { … }; /// Determine whether an identifier is reserved for use as a name at global /// scope. Such identifiers might be implementation-specific global functions /// or variables. inline bool isReservedAtGlobalScope(ReservedIdentifierStatus Status) { … } /// Determine whether an identifier is reserved in all contexts. Such /// identifiers might be implementation-specific keywords or macros, for /// example. inline bool isReservedInAllContexts(ReservedIdentifierStatus Status) { … } /// A simple pair of identifier info and location. IdentifierLocPair; /// IdentifierInfo and other related classes are aligned to /// 8 bytes so that DeclarationName can use the lower 3 bits /// of a pointer to one of these classes. enum { … }; static constexpr int InterestingIdentifierBits = …; /// The "layout" of InterestingIdentifier is: /// - ObjCKeywordKind enumerators /// - NotableIdentifierKind enumerators /// - Builtin::ID enumerators /// - NotInterestingIdentifier enum class InterestingIdentifier { … }; /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, /// is a language keyword, or if it is a front-end token of some sort (e.g. a /// variable or function name). The preprocessor keeps this information in a /// set, and all tok::identifier tokens have a pointer to one of these. /// It is aligned to 8 bytes because DeclarationName needs the lower 3 bits. class alignas(IdentifierInfoAlignment) IdentifierInfo { … }; /// An RAII object for [un]poisoning an identifier within a scope. /// /// \p II is allowed to be null, in which case objects of this type have /// no effect. class PoisonIdentifierRAIIObject { … }; /// An iterator that walks over all of the known identifiers /// in the lookup table. /// /// Since this iterator uses an abstract interface via virtual /// functions, it uses an object-oriented interface rather than the /// more standard C++ STL iterator interface. In this OO-style /// iteration, the single function \c Next() provides dereference, /// advance, and end-of-sequence checking in a single /// operation. Subclasses of this iterator type will provide the /// actual functionality. class IdentifierIterator { … }; /// Provides lookups to, and iteration over, IdentiferInfo objects. class IdentifierInfoLookup { … }; /// Implements an efficient mapping from strings to IdentifierInfo nodes. /// /// This has no other purpose, but this is an extremely performance-critical /// piece of the code, as each occurrence of every identifier goes through /// here when lexed. class IdentifierTable { … }; /// A family of Objective-C methods. /// /// These families have no inherent meaning in the language, but are /// nonetheless central enough in the existing implementations to /// merit direct AST support. While, in theory, arbitrary methods can /// be considered to form families, we focus here on the methods /// involving allocation and retain-count management, as these are the /// most "core" and the most likely to be useful to diverse clients /// without extra information. /// /// Both selectors and actual method declarations may be classified /// into families. Method families may impose additional restrictions /// beyond their selector name; for example, a method called '_init' /// that returns void is not considered to be in the 'init' family /// (but would be if it returned 'id'). It is also possible to /// explicitly change or remove a method's family. Therefore the /// method's family should be considered the single source of truth. enum ObjCMethodFamily { … }; /// Enough bits to store any enumerator in ObjCMethodFamily or /// InvalidObjCMethodFamily. enum { … }; /// An invalid value of ObjCMethodFamily. enum { … }; /// A family of Objective-C methods. /// /// These are family of methods whose result type is initially 'id', but /// but are candidate for the result type to be changed to 'instancetype'. enum ObjCInstanceTypeFamily { … }; enum ObjCStringFormatFamily { … }; namespace detail { /// DeclarationNameExtra is used as a base of various uncommon special names. /// This class is needed since DeclarationName has not enough space to store /// the kind of every possible names. Therefore the kind of common names is /// stored directly in DeclarationName, and the kind of uncommon names is /// stored in DeclarationNameExtra. It is aligned to 8 bytes because /// DeclarationName needs the lower 3 bits to store the kind of common names. /// DeclarationNameExtra is tightly coupled to DeclarationName and any change /// here is very likely to require changes in DeclarationName(Table). class alignas(IdentifierInfoAlignment) DeclarationNameExtra { … }; } // namespace detail /// One of these variable length records is kept for each /// selector containing more than one keyword. We use a folding set /// to unique aggregate names (keyword selectors in ObjC parlance). Access to /// this class is provided strictly through Selector. class alignas(IdentifierInfoAlignment) MultiKeywordSelector : public detail::DeclarationNameExtra, public llvm::FoldingSetNode { … }; /// Smart pointer class that efficiently represents Objective-C method /// names. /// /// This class will either point to an IdentifierInfo or a /// MultiKeywordSelector (which is private). This enables us to optimize /// selectors that take no arguments and selectors that take 1 argument, which /// accounts for 78% of all selectors in Cocoa.h. class Selector { … }; /// This table allows us to fully hide how we implement /// multi-keyword caching. class SelectorTable { … }; } // namespace clang namespace llvm { /// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and /// DenseSets. template <> struct DenseMapInfo<clang::Selector> { … }; template<> struct PointerLikeTypeTraits<clang::Selector> { … }; } // namespace llvm #endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H