diff options
author | ed <ed@FreeBSD.org> | 2009-06-14 09:24:02 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-06-14 09:24:02 +0000 |
commit | b8e7410b22fa573fb0078712439f343bc69208dd (patch) | |
tree | d472a7615b5c7e413aa62a77d0777c1a9cf76478 /lib/Lex/PPMacroExpansion.cpp | |
parent | 6514d87c1aa5b544d02c3822fe41217e2051673d (diff) | |
download | FreeBSD-src-b8e7410b22fa573fb0078712439f343bc69208dd.zip FreeBSD-src-b8e7410b22fa573fb0078712439f343bc69208dd.tar.gz |
Import Clang r73340.
Diffstat (limited to 'lib/Lex/PPMacroExpansion.cpp')
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 95 |
1 files changed, 82 insertions, 13 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 55222c9..2867051 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -36,14 +36,14 @@ void Preprocessor::setMacroInfo(IdentifierInfo *II, MacroInfo *MI) { /// RegisterBuiltinMacro - Register the specified identifier in the identifier /// table and mark it as a builtin macro to be expanded. -IdentifierInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) { +static IdentifierInfo *RegisterBuiltinMacro(Preprocessor &PP, const char *Name){ // Get the identifier. - IdentifierInfo *Id = getIdentifierInfo(Name); + IdentifierInfo *Id = PP.getIdentifierInfo(Name); // Mark it as being a macro that is builtin. - MacroInfo *MI = AllocateMacroInfo(SourceLocation()); + MacroInfo *MI = PP.AllocateMacroInfo(SourceLocation()); MI->setIsBuiltinMacro(); - setMacroInfo(Id, MI); + PP.setMacroInfo(Id, MI); return Id; } @@ -51,17 +51,21 @@ IdentifierInfo *Preprocessor::RegisterBuiltinMacro(const char *Name) { /// RegisterBuiltinMacros - Register builtin macros, such as __LINE__ with the /// identifier table. void Preprocessor::RegisterBuiltinMacros() { - Ident__LINE__ = RegisterBuiltinMacro("__LINE__"); - Ident__FILE__ = RegisterBuiltinMacro("__FILE__"); - Ident__DATE__ = RegisterBuiltinMacro("__DATE__"); - Ident__TIME__ = RegisterBuiltinMacro("__TIME__"); - Ident__COUNTER__ = RegisterBuiltinMacro("__COUNTER__"); - Ident_Pragma = RegisterBuiltinMacro("_Pragma"); + Ident__LINE__ = RegisterBuiltinMacro(*this, "__LINE__"); + Ident__FILE__ = RegisterBuiltinMacro(*this, "__FILE__"); + Ident__DATE__ = RegisterBuiltinMacro(*this, "__DATE__"); + Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__"); + Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__"); + Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma"); // GCC Extensions. - Ident__BASE_FILE__ = RegisterBuiltinMacro("__BASE_FILE__"); - Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro("__INCLUDE_LEVEL__"); - Ident__TIMESTAMP__ = RegisterBuiltinMacro("__TIMESTAMP__"); + Ident__BASE_FILE__ = RegisterBuiltinMacro(*this, "__BASE_FILE__"); + Ident__INCLUDE_LEVEL__ = RegisterBuiltinMacro(*this, "__INCLUDE_LEVEL__"); + Ident__TIMESTAMP__ = RegisterBuiltinMacro(*this, "__TIMESTAMP__"); + + // Clang Extensions. + Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); + Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); } /// isTrivialSingleTokenExpansion - Return true if MI, which has a single token @@ -469,6 +473,34 @@ static void ComputeDATE_TIME(SourceLocation &DATELoc, SourceLocation &TIMELoc, TIMELoc = TmpTok.getLocation(); } + +/// HasFeature - Return true if we recognize and implement the specified feature +/// specified by the identifier. +static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) { + const LangOptions &LangOpts = PP.getLangOptions(); + + switch (II->getLength()) { + default: return false; + case 6: + if (II->isStr("blocks")) return LangOpts.Blocks; + return false; + case 22: + if (II->isStr("attribute_overloadable")) return true; + return false; + case 25: + if (II->isStr("attribute_ext_vector_type")) return true; + return false; + case 27: + if (II->isStr("attribute_analyzer_noreturn")) return true; + return false; + case 29: + if (II->isStr("attribute_ns_returns_retained")) return true; + if (II->isStr("attribute_cf_returns_retained")) return true; + return false; + } +} + + /// ExpandBuiltinMacro - If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void Preprocessor::ExpandBuiltinMacro(Token &Tok) { @@ -599,6 +631,43 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { sprintf(TmpBuffer, "%u", CounterValue++); Tok.setKind(tok::numeric_constant); CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation()); + } else if (II == Ident__has_feature || + II == Ident__has_builtin) { + // The argument to these two builtins should be a parenthesized identifier. + SourceLocation StartLoc = Tok.getLocation(); + + bool IsValid = false; + IdentifierInfo *FeatureII = 0; + + // Read the '('. + Lex(Tok); + if (Tok.is(tok::l_paren)) { + // Read the identifier + Lex(Tok); + if (Tok.is(tok::identifier)) { + FeatureII = Tok.getIdentifierInfo(); + + // Read the ')'. + Lex(Tok); + if (Tok.is(tok::r_paren)) + IsValid = true; + } + } + + bool Value = false; + if (!IsValid) + Diag(StartLoc, diag::err_feature_check_malformed); + else if (II == Ident__has_builtin) { + // Check for a builtin is trivial. + Value = FeatureII->getBuiltinID() != 0; + } else { + assert(II == Ident__has_feature && "Must be feature check"); + Value = HasFeature(*this, FeatureII); + } + + sprintf(TmpBuffer, "%d", (int)Value); + Tok.setKind(tok::numeric_constant); + CreateString(TmpBuffer, strlen(TmpBuffer), Tok, Tok.getLocation()); } else { assert(0 && "Unknown identifier!"); } |