summaryrefslogtreecommitdiff
path: root/lib/Lex/PPMacroExpansion.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Lex/PPMacroExpansion.cpp')
-rw-r--r--lib/Lex/PPMacroExpansion.cpp144
1 files changed, 120 insertions, 24 deletions
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index 3f8ede23da56..41633f90c34d 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -369,11 +369,17 @@ void Preprocessor::RegisterBuiltinMacros() {
Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
+ Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
Ident__has_declspec = RegisterBuiltinMacro(*this, "__has_declspec_attribute");
Ident__has_include = RegisterBuiltinMacro(*this, "__has_include");
Ident__has_include_next = RegisterBuiltinMacro(*this, "__has_include_next");
Ident__has_warning = RegisterBuiltinMacro(*this, "__has_warning");
Ident__is_identifier = RegisterBuiltinMacro(*this, "__is_identifier");
+ Ident__is_target_arch = RegisterBuiltinMacro(*this, "__is_target_arch");
+ Ident__is_target_vendor = RegisterBuiltinMacro(*this, "__is_target_vendor");
+ Ident__is_target_os = RegisterBuiltinMacro(*this, "__is_target_os");
+ Ident__is_target_environment =
+ RegisterBuiltinMacro(*this, "__is_target_environment");
// Modules.
Ident__building_module = RegisterBuiltinMacro(*this, "__building_module");
@@ -1023,7 +1029,7 @@ Token *Preprocessor::cacheMacroExpandedTokens(TokenLexer *tokLexer,
size_t newIndex = MacroExpandedTokens.size();
bool cacheNeedsToGrow = tokens.size() >
- MacroExpandedTokens.capacity()-MacroExpandedTokens.size();
+ MacroExpandedTokens.capacity()-MacroExpandedTokens.size();
MacroExpandedTokens.append(tokens.begin(), tokens.end());
if (cacheNeedsToGrow) {
@@ -1098,6 +1104,8 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("address_sanitizer",
LangOpts.Sanitize.hasOneOf(SanitizerKind::Address |
SanitizerKind::KernelAddress))
+ .Case("hwaddress_sanitizer",
+ LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress))
.Case("assume_nonnull", true)
.Case("attribute_analyzer_noreturn", true)
.Case("attribute_availability", true)
@@ -1135,9 +1143,11 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) {
.Case("nullability_on_arrays", true)
.Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))
.Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread))
- .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
+ .Case("dataflow_sanitizer",
+ LangOpts.Sanitize.has(SanitizerKind::DataFlow))
.Case("efficiency_sanitizer",
LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency))
+ .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
// Objective-C features
.Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
.Case("objc_arc", LangOpts.ObjCAutoRefCount)
@@ -1588,6 +1598,56 @@ static IdentifierInfo *ExpectFeatureIdentifierInfo(Token &Tok,
return nullptr;
}
+/// Implements the __is_target_arch builtin macro.
+static bool isTargetArch(const TargetInfo &TI, const IdentifierInfo *II) {
+ std::string ArchName = II->getName().lower() + "--";
+ llvm::Triple Arch(ArchName);
+ const llvm::Triple &TT = TI.getTriple();
+ if (TT.isThumb()) {
+ // arm matches thumb or thumbv7. armv7 matches thumbv7.
+ if ((Arch.getSubArch() == llvm::Triple::NoSubArch ||
+ Arch.getSubArch() == TT.getSubArch()) &&
+ ((TT.getArch() == llvm::Triple::thumb &&
+ Arch.getArch() == llvm::Triple::arm) ||
+ (TT.getArch() == llvm::Triple::thumbeb &&
+ Arch.getArch() == llvm::Triple::armeb)))
+ return true;
+ }
+ // Check the parsed arch when it has no sub arch to allow Clang to
+ // match thumb to thumbv7 but to prohibit matching thumbv6 to thumbv7.
+ return (Arch.getSubArch() == llvm::Triple::NoSubArch ||
+ Arch.getSubArch() == TT.getSubArch()) &&
+ Arch.getArch() == TT.getArch();
+}
+
+/// Implements the __is_target_vendor builtin macro.
+static bool isTargetVendor(const TargetInfo &TI, const IdentifierInfo *II) {
+ StringRef VendorName = TI.getTriple().getVendorName();
+ if (VendorName.empty())
+ VendorName = "unknown";
+ return VendorName.equals_lower(II->getName());
+}
+
+/// Implements the __is_target_os builtin macro.
+static bool isTargetOS(const TargetInfo &TI, const IdentifierInfo *II) {
+ std::string OSName =
+ (llvm::Twine("unknown-unknown-") + II->getName().lower()).str();
+ llvm::Triple OS(OSName);
+ if (OS.getOS() == llvm::Triple::Darwin) {
+ // Darwin matches macos, ios, etc.
+ return TI.getTriple().isOSDarwin();
+ }
+ return TI.getTriple().getOS() == OS.getOS();
+}
+
+/// Implements the __is_target_environment builtin macro.
+static bool isTargetEnvironment(const TargetInfo &TI,
+ const IdentifierInfo *II) {
+ std::string EnvName = (llvm::Twine("---") + II->getName().lower()).str();
+ llvm::Triple Env(EnvName);
+ return TI.getTriple().getEnvironment() == Env.getEnvironment();
+}
+
/// 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) {
@@ -1750,6 +1810,10 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
.Case("__make_integer_seq", LangOpts.CPlusPlus)
.Case("__type_pack_element", LangOpts.CPlusPlus)
.Case("__builtin_available", true)
+ .Case("__is_target_arch", true)
+ .Case("__is_target_vendor", true)
+ .Case("__is_target_os", true)
+ .Case("__is_target_environment", true)
.Default(false);
}
});
@@ -1774,30 +1838,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
return II ? hasAttribute(AttrSyntax::Declspec, nullptr, II,
getTargetInfo(), getLangOpts()) : 0;
});
- } else if (II == Ident__has_cpp_attribute) {
- EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this,
- [this](Token &Tok, bool &HasLexedNextToken) -> int {
- IdentifierInfo *ScopeII = nullptr;
- IdentifierInfo *II = ExpectFeatureIdentifierInfo(Tok, *this,
- diag::err_feature_check_malformed);
- if (!II)
- return false;
-
- // It is possible to receive a scope token. Read the "::", if it is
- // available, and the subsequent identifier.
- LexUnexpandedToken(Tok);
- if (Tok.isNot(tok::coloncolon))
- HasLexedNextToken = true;
- else {
- ScopeII = II;
+ } else if (II == Ident__has_cpp_attribute ||
+ II == Ident__has_c_attribute) {
+ bool IsCXX = II == Ident__has_cpp_attribute;
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [&](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *ScopeII = nullptr;
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ if (!II)
+ return false;
+
+ // It is possible to receive a scope token. Read the "::", if it is
+ // available, and the subsequent identifier.
LexUnexpandedToken(Tok);
- II = ExpectFeatureIdentifierInfo(Tok, *this,
- diag::err_feature_check_malformed);
- }
+ if (Tok.isNot(tok::coloncolon))
+ HasLexedNextToken = true;
+ else {
+ ScopeII = II;
+ LexUnexpandedToken(Tok);
+ II = ExpectFeatureIdentifierInfo(Tok, *this,
+ diag::err_feature_check_malformed);
+ }
- return II ? hasAttribute(AttrSyntax::CXX, ScopeII, II,
- getTargetInfo(), getLangOpts()) : 0;
- });
+ AttrSyntax Syntax = IsCXX ? AttrSyntax::CXX : AttrSyntax::C;
+ return II ? hasAttribute(Syntax, ScopeII, II, getTargetInfo(),
+ getLangOpts())
+ : 0;
+ });
} else if (II == Ident__has_include ||
II == Ident__has_include_next) {
// The argument to these two builtins should be a parenthesized
@@ -1897,6 +1965,34 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) {
Diag(LParenLoc, diag::note_matching) << tok::l_paren;
}
return;
+ } else if (II == Ident__is_target_arch) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetArch(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_vendor) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetVendor(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_os) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetOS(getTargetInfo(), II);
+ });
+ } else if (II == Ident__is_target_environment) {
+ EvaluateFeatureLikeBuiltinMacro(
+ OS, Tok, II, *this, [this](Token &Tok, bool &HasLexedNextToken) -> int {
+ IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+ Tok, *this, diag::err_feature_check_malformed);
+ return II && isTargetEnvironment(getTargetInfo(), II);
+ });
} else {
llvm_unreachable("Unknown identifier!");
}