summaryrefslogtreecommitdiffstats
path: root/lib/Basic/IdentifierTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Basic/IdentifierTable.cpp')
-rw-r--r--lib/Basic/IdentifierTable.cpp119
1 files changed, 91 insertions, 28 deletions
diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp
index 2198459..613b43f 100644
--- a/lib/Basic/IdentifierTable.cpp
+++ b/lib/Basic/IdentifierTable.cpp
@@ -110,49 +110,59 @@ namespace {
HALFSUPPORT = 0x04000,
KEYALL = (0xffff & ~KEYNOMS) // Because KEYNOMS is used to exclude.
};
+
+ /// \brief How a keyword is treated in the selected standard.
+ enum KeywordStatus {
+ KS_Disabled, // Disabled
+ KS_Extension, // Is an extension
+ KS_Enabled, // Enabled
+ KS_Future // Is a keyword in future standard
+ };
+}
+
+/// \brief Translates flags as specified in TokenKinds.def into keyword status
+/// in the given language standard.
+static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
+ unsigned Flags) {
+ if (Flags == KEYALL) return KS_Enabled;
+ if (LangOpts.CPlusPlus && (Flags & KEYCXX)) return KS_Enabled;
+ if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) return KS_Enabled;
+ if (LangOpts.C99 && (Flags & KEYC99)) return KS_Enabled;
+ if (LangOpts.GNUKeywords && (Flags & KEYGNU)) return KS_Extension;
+ if (LangOpts.MicrosoftExt && (Flags & KEYMS)) return KS_Extension;
+ if (LangOpts.Borland && (Flags & KEYBORLAND)) return KS_Extension;
+ if (LangOpts.Bool && (Flags & BOOLSUPPORT)) return KS_Enabled;
+ if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled;
+ if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled;
+ if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled;
+ if (LangOpts.OpenCL && (Flags & KEYOPENCL)) return KS_Enabled;
+ if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) return KS_Enabled;
+ if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled;
+ // We treat bridge casts as objective-C keywords so we can warn on them
+ // in non-arc mode.
+ if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
+ if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
+ return KS_Disabled;
}
/// AddKeyword - This method is used to associate a token ID with specific
/// identifiers because they are language keywords. This causes the lexer to
/// automatically map matching identifiers to specialized token codes.
-///
-/// The C90/C99/CPP/CPP0x flags are set to 3 if the token is a keyword in a
-/// future language standard, set to 2 if the token should be enabled in the
-/// specified language, set to 1 if it is an extension in the specified
-/// language, and set to 0 if disabled in the specified language.
static void AddKeyword(StringRef Keyword,
tok::TokenKind TokenCode, unsigned Flags,
const LangOptions &LangOpts, IdentifierTable &Table) {
- unsigned AddResult = 0;
- if (Flags == KEYALL) AddResult = 2;
- else if (LangOpts.CPlusPlus && (Flags & KEYCXX)) AddResult = 2;
- else if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) AddResult = 2;
- else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2;
- else if (LangOpts.GNUKeywords && (Flags & KEYGNU)) AddResult = 1;
- else if (LangOpts.MicrosoftExt && (Flags & KEYMS)) AddResult = 1;
- else if (LangOpts.Borland && (Flags & KEYBORLAND)) AddResult = 1;
- else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2;
- else if (LangOpts.Half && (Flags & HALFSUPPORT)) AddResult = 2;
- else if (LangOpts.WChar && (Flags & WCHARSUPPORT)) AddResult = 2;
- else if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) AddResult = 2;
- else if (LangOpts.OpenCL && (Flags & KEYOPENCL)) AddResult = 2;
- else if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) AddResult = 2;
- else if (LangOpts.C11 && (Flags & KEYC11)) AddResult = 2;
- // We treat bridge casts as objective-C keywords so we can warn on them
- // in non-arc mode.
- else if (LangOpts.ObjC2 && (Flags & KEYARC)) AddResult = 2;
- else if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) AddResult = 3;
+ KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
// Don't add this keyword under MSVCCompat.
if (LangOpts.MSVCCompat && (Flags & KEYNOMS))
return;
// Don't add this keyword if disabled in this language.
- if (AddResult == 0) return;
+ if (AddResult == KS_Disabled) return;
IdentifierInfo &Info =
- Table.get(Keyword, AddResult == 3 ? tok::identifier : TokenCode);
- Info.setIsExtensionToken(AddResult == 1);
- Info.setIsCXX11CompatKeyword(AddResult == 3);
+ Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
+ Info.setIsExtensionToken(AddResult == KS_Extension);
+ Info.setIsCXX11CompatKeyword(AddResult == KS_Future);
}
/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
@@ -199,6 +209,31 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
LangOpts, *this);
}
+/// \brief Checks if the specified token kind represents a keyword in the
+/// specified language.
+/// \returns Status of the keyword in the language.
+static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
+ tok::TokenKind K) {
+ switch (K) {
+#define KEYWORD(NAME, FLAGS) \
+ case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
+#include "clang/Basic/TokenKinds.def"
+ default: return KS_Disabled;
+ }
+}
+
+/// \brief Returns true if the identifier represents a keyword in the
+/// specified language.
+bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) {
+ switch (getTokenKwStatus(LangOpts, getTokenID())) {
+ case KS_Enabled:
+ case KS_Extension:
+ return true;
+ default:
+ return false;
+ }
+}
+
tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
// We use a perfect hash function here involving the length of the keyword,
// the first and third character. For preprocessor ID's there are no
@@ -428,6 +463,7 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
if (name == "retain") return OMF_retain;
if (name == "retainCount") return OMF_retainCount;
if (name == "self") return OMF_self;
+ if (name == "initialize") return OMF_initialize;
}
if (name == "performSelector") return OMF_performSelector;
@@ -486,6 +522,33 @@ ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
return OIT_None;
}
+ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
+ IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
+ if (!first) return SFF_None;
+
+ StringRef name = first->getName();
+
+ switch (name.front()) {
+ case 'a':
+ if (name == "appendFormat") return SFF_NSString;
+ break;
+
+ case 'i':
+ if (name == "initWithFormat") return SFF_NSString;
+ break;
+
+ case 'l':
+ if (name == "localizedStringWithFormat") return SFF_NSString;
+ break;
+
+ case 's':
+ if (name == "stringByAppendingFormat" ||
+ name == "stringWithFormat") return SFF_NSString;
+ break;
+ }
+ return SFF_None;
+}
+
namespace {
struct SelectorTableImpl {
llvm::FoldingSet<MultiKeywordSelector> Table;
OpenPOWER on IntegriCloud