forked from OSchip/llvm-project
Make preprocessor keywords like 'define' first class citizens in the
IdentifierTable, instead of making them resort to strcmp'ing. llvm-svn: 39002
This commit is contained in:
parent
b95cca0d33
commit
87d3bec423
|
@ -207,6 +207,7 @@ IdentifierInfo &IdentifierTable::get(const char *NameStart,
|
|||
Identifier->TokInfo.NameLen = Length;
|
||||
Identifier->TokInfo.Macro = 0;
|
||||
Identifier->TokInfo.TokenID = tok::identifier;
|
||||
Identifier->TokInfo.PPID = tok::pp_not_keyword;
|
||||
Identifier->TokInfo.IsExtension = false;
|
||||
Identifier->TokInfo.IsPoisoned = false;
|
||||
Identifier->TokInfo.IsOtherTargetMacro = false;
|
||||
|
|
|
@ -102,6 +102,12 @@ Preprocessor::PerFileInfo &Preprocessor::getFileInfo(const FileEntry *FE) {
|
|||
return FileInfo[FE->getUID()];
|
||||
}
|
||||
|
||||
/// AddPPKeyword - Register a preprocessor keyword like "define" "undef" or
|
||||
/// "elif".
|
||||
static void AddPPKeyword(tok::PPKeywordKind PPID,
|
||||
const char *Name, unsigned NameLen, Preprocessor &PP) {
|
||||
PP.getIdentifierInfo(Name, Name+NameLen)->setPPKeywordID(PPID);
|
||||
}
|
||||
|
||||
/// AddKeywords - Add all keywords to the symbol table.
|
||||
///
|
||||
|
@ -127,9 +133,34 @@ void Preprocessor::AddKeywords() {
|
|||
((FLAGS) >> CPPShift) & Mask);
|
||||
#define ALIAS(NAME, TOK) \
|
||||
AddKeyword(NAME, tok::kw_ ## TOK, 0, 0, 0);
|
||||
#define PPKEYWORD(NAME) \
|
||||
AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
|
||||
#include "clang/Basic/TokenKinds.def"
|
||||
}
|
||||
|
||||
/// 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 flags are set to 0 if the token should be enabled in the
|
||||
/// specified langauge, set to 1 if it is an extension in the specified
|
||||
/// language, and set to 2 if disabled in the specified language.
|
||||
void Preprocessor::AddKeyword(const std::string &Keyword,
|
||||
tok::TokenKind TokenCode,
|
||||
int C90, int C99, int CPP) {
|
||||
int Flags = Features.CPlusPlus ? CPP : (Features.C99 ? C99 : C90);
|
||||
|
||||
// Don't add this keyword if disabled in this language or if an extension
|
||||
// and extensions are disabled.
|
||||
if (Flags+Features.NoExtensions >= 2) return;
|
||||
|
||||
const char *Str = &Keyword[0];
|
||||
IdentifierInfo &Info = *getIdentifierInfo(Str, Str+Keyword.size());
|
||||
Info.setTokenID(TokenCode);
|
||||
Info.setIsExtensionToken(Flags == 1);
|
||||
}
|
||||
|
||||
|
||||
/// Diag - Forwarding function for diagnostics. This emits a diagnostic at
|
||||
/// the specified LexerToken's location, translating the token's start
|
||||
/// position in the current buffer into a SourcePosition object for rendering.
|
||||
|
@ -1405,7 +1436,6 @@ void Preprocessor::HandleDirective(LexerToken &Result) {
|
|||
Diag(Result, diag::ext_embedded_directive);
|
||||
|
||||
switch (Result.getKind()) {
|
||||
default: break;
|
||||
case tok::eom:
|
||||
return; // null directive.
|
||||
|
||||
|
@ -1413,75 +1443,76 @@ void Preprocessor::HandleDirective(LexerToken &Result) {
|
|||
// FIXME: implement # 7 line numbers!
|
||||
DiscardUntilEndOfDirective();
|
||||
return;
|
||||
case tok::kw_else:
|
||||
return HandleElseDirective(Result);
|
||||
case tok::kw_if:
|
||||
default:
|
||||
IdentifierInfo *II = Result.getIdentifierInfo();
|
||||
if (II == 0) break; // Not an identifier.
|
||||
|
||||
// Ask what the preprocessor keyword ID is.
|
||||
switch (II->getPPKeywordID()) {
|
||||
default: break;
|
||||
// C99 6.10.1 - Conditional Inclusion.
|
||||
case tok::pp_if:
|
||||
return HandleIfDirective(Result, ReadAnyTokensBeforeDirective);
|
||||
case tok::identifier:
|
||||
// Get the identifier name without trigraphs or embedded newlines.
|
||||
const char *Directive = Result.getIdentifierInfo()->getName();
|
||||
bool isExtension = false;
|
||||
switch (Result.getIdentifierInfo()->getNameLength()) {
|
||||
case 4:
|
||||
if (Directive[0] == 'l' && !strcmp(Directive, "line")) {
|
||||
case tok::pp_ifdef:
|
||||
return HandleIfdefDirective(Result, false, true/*not valid for miopt*/);
|
||||
case tok::pp_ifndef:
|
||||
return HandleIfdefDirective(Result, true, ReadAnyTokensBeforeDirective);
|
||||
case tok::pp_elif:
|
||||
return HandleElifDirective(Result);
|
||||
case tok::pp_else:
|
||||
return HandleElseDirective(Result);
|
||||
case tok::pp_endif:
|
||||
return HandleEndifDirective(Result);
|
||||
|
||||
// C99 6.10.2 - Source File Inclusion.
|
||||
case tok::pp_include:
|
||||
return HandleIncludeDirective(Result); // Handle #include.
|
||||
|
||||
// C99 6.10.3 - Macro Replacement.
|
||||
case tok::pp_define:
|
||||
return HandleDefineDirective(Result, false);
|
||||
case tok::pp_undef:
|
||||
return HandleUndefDirective(Result);
|
||||
|
||||
// C99 6.10.4 - Line Control.
|
||||
case tok::pp_line:
|
||||
// FIXME: implement #line
|
||||
DiscardUntilEndOfDirective();
|
||||
return;
|
||||
}
|
||||
if (Directive[0] == 'e' && !strcmp(Directive, "elif"))
|
||||
return HandleElifDirective(Result);
|
||||
if (Directive[0] == 's' && !strcmp(Directive, "sccs"))
|
||||
return HandleIdentSCCSDirective(Result);
|
||||
break;
|
||||
case 5:
|
||||
if (Directive[0] == 'e' && !strcmp(Directive, "endif"))
|
||||
return HandleEndifDirective(Result);
|
||||
if (Directive[0] == 'i' && !strcmp(Directive, "ifdef"))
|
||||
return HandleIfdefDirective(Result, false, true/*not valid for miopt*/);
|
||||
if (Directive[0] == 'u' && !strcmp(Directive, "undef"))
|
||||
return HandleUndefDirective(Result);
|
||||
if (Directive[0] == 'e' && !strcmp(Directive, "error"))
|
||||
|
||||
// C99 6.10.5 - Error Directive.
|
||||
case tok::pp_error:
|
||||
return HandleUserDiagnosticDirective(Result, false);
|
||||
if (Directive[0] == 'i' && !strcmp(Directive, "ident"))
|
||||
return HandleIdentSCCSDirective(Result);
|
||||
break;
|
||||
case 6:
|
||||
if (Directive[0] == 'd' && !strcmp(Directive, "define"))
|
||||
return HandleDefineDirective(Result, false);
|
||||
if (Directive[0] == 'i' && !strcmp(Directive, "ifndef"))
|
||||
return HandleIfdefDirective(Result, true, ReadAnyTokensBeforeDirective);
|
||||
if (Directive[0] == 'i' && !strcmp(Directive, "import"))
|
||||
return HandleImportDirective(Result);
|
||||
if (Directive[0] == 'p' && !strcmp(Directive, "pragma"))
|
||||
|
||||
// C99 6.10.6 - Pragma Directive.
|
||||
case tok::pp_pragma:
|
||||
return HandlePragmaDirective();
|
||||
if (Directive[0] == 'a' && !strcmp(Directive, "assert"))
|
||||
isExtension = true; // FIXME: implement #assert
|
||||
break;
|
||||
case 7:
|
||||
if (Directive[0] == 'i' && !strcmp(Directive, "include"))
|
||||
return HandleIncludeDirective(Result); // Handle #include.
|
||||
if (Directive[0] == 'w' && !strcmp(Directive, "warning")) {
|
||||
|
||||
// GNU Extensions.
|
||||
case tok::pp_import:
|
||||
return HandleImportDirective(Result);
|
||||
case tok::pp_include_next:
|
||||
return HandleIncludeNextDirective(Result);
|
||||
|
||||
case tok::pp_warning:
|
||||
Diag(Result, diag::ext_pp_warning_directive);
|
||||
return HandleUserDiagnosticDirective(Result, true);
|
||||
}
|
||||
case tok::pp_ident:
|
||||
return HandleIdentSCCSDirective(Result);
|
||||
case tok::pp_sccs:
|
||||
return HandleIdentSCCSDirective(Result);
|
||||
case tok::pp_assert:
|
||||
//isExtension = true; // FIXME: implement #assert
|
||||
break;
|
||||
case 8:
|
||||
if (Directive[0] == 'u' && !strcmp(Directive, "unassert")) {
|
||||
isExtension = true; // FIXME: implement #unassert
|
||||
}
|
||||
case tok::pp_unassert:
|
||||
//isExtension = true; // FIXME: implement #unassert
|
||||
break;
|
||||
case 12:
|
||||
if (Directive[0] == 'i' && !strcmp(Directive, "include_next"))
|
||||
return HandleIncludeNextDirective(Result); // Handle #include_next.
|
||||
break;
|
||||
case 13:
|
||||
if (Directive[0] == 'd' && !strcmp(Directive, "define_target"))
|
||||
|
||||
// clang extensions.
|
||||
case tok::pp_define_target:
|
||||
return HandleDefineDirective(Result, true);
|
||||
break;
|
||||
case 19:
|
||||
if (Directive[0] == 'd' && !strcmp(Directive, "define_other_target"))
|
||||
case tok::pp_define_other_target:
|
||||
return HandleDefineOtherTargetDirective(Result);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
//
|
||||
// This file defines the TokenKind database. This includes normal tokens like
|
||||
// tok::ampamp (corresponding to the && token) as well as keywords for various
|
||||
// languages. Users of this file must optionally #define the TOK/KEYWORD/ALIAS
|
||||
// macros to make use of this file.
|
||||
// languages. Users of this file must optionally #define the TOK, KEYWORD,
|
||||
// ALIAS, or PPKEYWORD macros to make use of this file.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -23,6 +23,61 @@
|
|||
#ifndef ALIAS
|
||||
#define ALIAS(X,Y)
|
||||
#endif
|
||||
#ifndef PPKEYWORD
|
||||
#define PPKEYWORD(X)
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Preprocessor keywords.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// These have meaning after a '#' at the start of a line. These define enums in
|
||||
// the tok::pp_* namespace.
|
||||
PPKEYWORD(not_keyword)
|
||||
|
||||
// C99 6.10.1 - Conditional Inclusion.
|
||||
PPKEYWORD(if)
|
||||
PPKEYWORD(ifdef)
|
||||
PPKEYWORD(ifndef)
|
||||
PPKEYWORD(elif)
|
||||
PPKEYWORD(else)
|
||||
PPKEYWORD(endif)
|
||||
|
||||
// C99 6.10.2 - Source File Inclusion.
|
||||
PPKEYWORD(include)
|
||||
|
||||
// C99 6.10.3 - Macro Replacement.
|
||||
PPKEYWORD(define)
|
||||
PPKEYWORD(undef)
|
||||
|
||||
// C99 6.10.4 - Line Control.
|
||||
PPKEYWORD(line)
|
||||
|
||||
// C99 6.10.5 - Error Directive.
|
||||
PPKEYWORD(error)
|
||||
|
||||
// C99 6.10.6 - Pragma Directive.
|
||||
PPKEYWORD(pragma)
|
||||
|
||||
// GNU Extensions.
|
||||
PPKEYWORD(import)
|
||||
PPKEYWORD(include_next)
|
||||
PPKEYWORD(warning)
|
||||
PPKEYWORD(ident)
|
||||
PPKEYWORD(sccs)
|
||||
PPKEYWORD(assert)
|
||||
PPKEYWORD(unassert)
|
||||
|
||||
// clang extensions.
|
||||
PPKEYWORD(define_target)
|
||||
PPKEYWORD(define_other_target)
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Language keywords.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// These define members of the tok::kw_* namespace.
|
||||
|
||||
TOK(unknown) // Not a token.
|
||||
TOK(eof) // End of file.
|
||||
|
@ -239,6 +294,7 @@ ALIAS("__typeof__" , typeof )
|
|||
ALIAS("__volatile" , volatile )
|
||||
ALIAS("__volatile__" , volatile )
|
||||
|
||||
#undef PPKEYWORD
|
||||
#undef ALIAS
|
||||
#undef KEYWORD
|
||||
#undef TOK
|
||||
|
|
|
@ -27,6 +27,12 @@ enum TokenKind {
|
|||
NUM_TOKENS
|
||||
};
|
||||
|
||||
enum PPKeywordKind {
|
||||
#define PPKEYWORD(X) pp_##X,
|
||||
#include "clang/Basic/TokenKinds.def"
|
||||
NUM_PP_KEYWORDS
|
||||
};
|
||||
|
||||
const char *getTokenName(enum TokenKind Kind);
|
||||
|
||||
} // end namespace tok
|
||||
|
|
|
@ -32,6 +32,7 @@ class IdentifierInfo {
|
|||
unsigned NameLen; // String that is the identifier.
|
||||
MacroInfo *Macro; // Set if this identifier is #define'd.
|
||||
tok::TokenKind TokenID : 8; // Front-end token ID or tok::identifier.
|
||||
tok::PPKeywordKind PPID : 5; // ID for preprocessor command like 'ifdef'.
|
||||
bool IsExtension : 1; // True if identifier is a lang extension.
|
||||
bool IsPoisoned : 1; // True if identifier is poisoned.
|
||||
bool IsOtherTargetMacro : 1; // True if ident is a macro on another target.
|
||||
|
@ -64,6 +65,9 @@ public:
|
|||
tok::TokenKind getTokenID() const { return TokenID; }
|
||||
void setTokenID(tok::TokenKind ID) { TokenID = ID; }
|
||||
|
||||
tok::PPKeywordKind getPPKeywordID() const { return PPID; }
|
||||
void setPPKeywordID(tok::PPKeywordKind ID) { PPID = ID; }
|
||||
|
||||
/// get/setExtension - Initialize information about whether or not this
|
||||
/// language token is an extension. This controls extension warnings, and is
|
||||
/// only valid if a custom token ID is set.
|
||||
|
|
|
@ -276,18 +276,7 @@ public:
|
|||
/// specified langauge, set to 1 if it is an extension in the specified
|
||||
/// language, and set to 2 if disabled in the specified language.
|
||||
void AddKeyword(const std::string &Keyword, tok::TokenKind TokenCode,
|
||||
int C90, int C99, int CPP) {
|
||||
int Flags = Features.CPlusPlus ? CPP : (Features.C99 ? C99 : C90);
|
||||
|
||||
// Don't add this keyword if disabled in this language or if an extension
|
||||
// and extensions are disabled.
|
||||
if (Flags+Features.NoExtensions >= 2) return;
|
||||
|
||||
const char *Str = &Keyword[0];
|
||||
IdentifierInfo &Info = *getIdentifierInfo(Str, Str+Keyword.size());
|
||||
Info.setTokenID(TokenCode);
|
||||
Info.setIsExtensionToken(Flags == 1);
|
||||
}
|
||||
int C90, int C99, int CPP);
|
||||
|
||||
/// AddKeywords - Add all keywords to the symbol table.
|
||||
///
|
||||
|
|
Loading…
Reference in New Issue