Index: clang/include/clang/Basic/IdentifierTable.h =================================================================== --- clang/include/clang/Basic/IdentifierTable.h +++ clang/include/clang/Basic/IdentifierTable.h @@ -76,6 +76,21 @@ static constexpr int ObjCOrBuiltinIDBits = 16; +/// The "layout" of ObjCOrBuiltinID is: +/// - The first value (0) represents "not a special identifier". +/// - The next (NUM_OBJC_KEYWORDS - 1) values represent ObjCKeywordKinds (not +/// including objc_not_keyword). +/// - The next (NUM_INTERESTING_IDENTIFIERS - 1) values represent +/// InterestingIdentifierKinds (not including not_interesting). +/// - The rest of the values represent builtin IDs (not including NotBuiltin). +static constexpr int FirstObjCKeywordID = 1; +static constexpr int LastObjCKeywordID = + FirstObjCKeywordID + tok::NUM_OBJC_KEYWORDS - 2; +static constexpr int FirstInterestingIdentifierID = LastObjCKeywordID + 1; +static constexpr int LastInterestingIdentifierID = + FirstInterestingIdentifierID + tok::NUM_INTERESTING_IDENTIFIERS - 2; +static constexpr int FirstBuiltinID = LastInterestingIdentifierID + 1; + /// 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 @@ -290,7 +305,9 @@ /// /// For example, 'class' will return tok::objc_class if ObjC is enabled. tok::ObjCKeywordKind getObjCKeywordID() const { - if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS) + static_assert(FirstObjCKeywordID == 1, + "hard-coding this assumption to simplify code"); + if (ObjCOrBuiltinID <= LastObjCKeywordID) return tok::ObjCKeywordKind(ObjCOrBuiltinID); else return tok::objc_not_keyword; @@ -301,15 +318,30 @@ /// /// 0 is not-built-in. 1+ are specific builtin functions. unsigned getBuiltinID() const { - if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS) - return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS; + if (ObjCOrBuiltinID >= FirstBuiltinID) + return 1 + (ObjCOrBuiltinID - FirstBuiltinID); else return 0; } void setBuiltinID(unsigned ID) { - ObjCOrBuiltinID = ID + tok::NUM_OBJC_KEYWORDS; - assert(ObjCOrBuiltinID - unsigned(tok::NUM_OBJC_KEYWORDS) == ID - && "ID too large for field!"); + assert(ID != 0); + ObjCOrBuiltinID = FirstBuiltinID + (ID - 1); + assert(getBuiltinID() == ID && "ID too large for field!"); + } + void clearBuiltinID() { ObjCOrBuiltinID = 0; } + + tok::InterestingIdentifierKind getInterestingIdentifierID() const { + if (ObjCOrBuiltinID >= FirstInterestingIdentifierID && + ObjCOrBuiltinID <= LastInterestingIdentifierID) + return tok::InterestingIdentifierKind( + 1 + (ObjCOrBuiltinID - FirstInterestingIdentifierID)); + else + return tok::not_interesting; + } + void setInterestingIdentifierID(unsigned ID) { + assert(ID != tok::not_interesting); + ObjCOrBuiltinID = FirstInterestingIdentifierID + (ID - 1); + assert(getInterestingIdentifierID() == ID && "ID too large for field!"); } unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; } Index: clang/include/clang/Basic/TokenKinds.h =================================================================== --- clang/include/clang/Basic/TokenKinds.h +++ clang/include/clang/Basic/TokenKinds.h @@ -44,6 +44,14 @@ NUM_OBJC_KEYWORDS }; +/// Provides a namespace for interesting identifers such as float_t and +/// double_t. +enum InterestingIdentifierKind { +#define INTERESTING_IDENTIFIER(X) X, +#include "clang/Basic/TokenKinds.def" + NUM_INTERESTING_IDENTIFIERS +}; + /// Defines the possible values of an on-off-switch (C99 6.10.6p2). enum OnOffSwitch { OOS_ON, OOS_OFF, OOS_DEFAULT Index: clang/include/clang/Basic/TokenKinds.def =================================================================== --- clang/include/clang/Basic/TokenKinds.def +++ clang/include/clang/Basic/TokenKinds.def @@ -85,6 +85,9 @@ #ifndef PRAGMA_ANNOTATION #define PRAGMA_ANNOTATION(X) ANNOTATION(X) #endif +#ifndef INTERESTING_IDENTIFIER +#define INTERESTING_IDENTIFIER(X) +#endif //===----------------------------------------------------------------------===// // Preprocessor keywords. @@ -794,6 +797,17 @@ OBJC_AT_KEYWORD(import) OBJC_AT_KEYWORD(available) +//===----------------------------------------------------------------------===// +// Interesting idenitifiers. +//===----------------------------------------------------------------------===// +INTERESTING_IDENTIFIER(not_interesting) +INTERESTING_IDENTIFIER(float_t) +INTERESTING_IDENTIFIER(double_t) +INTERESTING_IDENTIFIER(FILE) +INTERESTING_IDENTIFIER(jmp_buf) +INTERESTING_IDENTIFIER(sigjmp_buf) +INTERESTING_IDENTIFIER(ucontext_t) + // TODO: What to do about context-sensitive keywords like: // bycopy/byref/in/inout/oneway/out? @@ -974,3 +988,4 @@ #undef TOK #undef C99_KEYWORD #undef C2X_KEYWORD +#undef INTERESTING_IDENTIFIER Index: clang/lib/Basic/Builtins.cpp =================================================================== --- clang/lib/Basic/Builtins.cpp +++ clang/lib/Basic/Builtins.cpp @@ -151,7 +151,7 @@ unsigned ID = NameIt->second->getBuiltinID(); if (ID != Builtin::NotBuiltin && isPredefinedLibFunction(ID) && isInStdNamespace(ID) == InStdNamespace) { - Table.get(Name).setBuiltinID(Builtin::NotBuiltin); + NameIt->second->clearBuiltinID(); } } } Index: clang/lib/Basic/IdentifierTable.cpp =================================================================== --- clang/lib/Basic/IdentifierTable.cpp +++ clang/lib/Basic/IdentifierTable.cpp @@ -279,6 +279,16 @@ Table.get(Name).setObjCKeywordID(ObjCID); } +static void AddInterestingIdentifier(StringRef Name, + tok::InterestingIdentifierKind BTID, + IdentifierTable &Table) { + // Don't add 'not_interesting' identifier. + if (BTID != tok::not_interesting) { + IdentifierInfo &Info = Table.get(Name, tok::identifier); + Info.setInterestingIdentifierID(BTID); + } +} + /// AddKeywords - Add all keywords to the symbol table. /// void IdentifierTable::AddKeywords(const LangOptions &LangOpts) { @@ -295,6 +305,9 @@ #define OBJC_AT_KEYWORD(NAME) \ if (LangOpts.ObjC) \ AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this); +#define INTERESTING_IDENTIFIER(NAME) \ + AddInterestingIdentifier(StringRef(#NAME), tok::##NAME, *this); + #define TESTING_KEYWORD(NAME, FLAGS) #include "clang/Basic/TokenKinds.def" Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -6763,14 +6763,22 @@ if (IdentifierInfo *II = NewTD->getIdentifier()) if (!NewTD->isInvalidDecl() && NewTD->getDeclContext()->getRedeclContext()->isTranslationUnit()) { - if (II->isStr("FILE")) + switch (II->getInterestingIdentifierID()) { + case tok::InterestingIdentifierKind::FILE: Context.setFILEDecl(NewTD); - else if (II->isStr("jmp_buf")) + break; + case tok::InterestingIdentifierKind::jmp_buf: Context.setjmp_bufDecl(NewTD); - else if (II->isStr("sigjmp_buf")) + break; + case tok::InterestingIdentifierKind::sigjmp_buf: Context.setsigjmp_bufDecl(NewTD); - else if (II->isStr("ucontext_t")) + break; + case tok::InterestingIdentifierKind::ucontext_t: Context.setucontext_tDecl(NewTD); + break; + default: + break; + } } return NewTD; Index: clang/lib/Sema/SemaLookup.cpp =================================================================== --- clang/lib/Sema/SemaLookup.cpp +++ clang/lib/Sema/SemaLookup.cpp @@ -320,10 +320,11 @@ // Compiler builtins are always visible, regardless of where they end // up being declared. if (IdentifierInfo *Id = NameInfo.getName().getAsIdentifierInfo()) { - if (unsigned BuiltinID = Id->getBuiltinID()) { - if (!getSema().Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - AllowHidden = true; - } + if (!Id->getInterestingIdentifierID()) + if (unsigned BuiltinID = Id->getBuiltinID()) { + if (!getSema().Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) + AllowHidden = true; + } } } @@ -943,6 +944,10 @@ // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { + if (unsigned ID = II->getInterestingIdentifierID()) { + // Don't think we should LazyCreate the interesting identifier? + return true; + } // In C++ and OpenCL (spec v1.2 s6.9.f), we don't have any predefined // library functions like 'malloc'. Instead, we'll just error. if ((getLangOpts().CPlusPlus || getLangOpts().OpenCL) &&