summaryrefslogtreecommitdiffstats
path: root/clang/lib/Lex/PPMacroExpansion.cpp
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2017-12-14 19:22:02 +0000
committerAlex Lorenz <arphaman@gmail.com>2017-12-14 19:22:02 +0000
commitd8ec43114389756f916ad12b73e49f39d3c29a49 (patch)
treebc5b99d1df33b059570482b27cf45367cb9cd0de /clang/lib/Lex/PPMacroExpansion.cpp
parent689c6960ef0a1f1448c699f64361c9be3dfa42b7 (diff)
downloadbcm5719-llvm-d8ec43114389756f916ad12b73e49f39d3c29a49.tar.gz
bcm5719-llvm-d8ec43114389756f916ad12b73e49f39d3c29a49.zip
[Preprocessor] Implement __is_target_{arch|vendor|os|environment} function-like
builtin macros This patch implements the __is_target_arch, __is_target_vendor, __is_target_os, and __is_target_environment Clang preprocessor extensions that were proposed by @compnerd in Bob's cfe-dev post: http://lists.llvm.org/pipermail/cfe-dev/2017-November/056166.html. These macros can be used to examine the components of the target triple at compile time. A has_builtin(is_target_???) preprocessor check can be used to check for their availability. __is_target_arch allows you to check if an arch is specified without worring about a specific subarch, e.g. __is_target_arch(arm) returns 1 for the target arch "armv7" __is_target_arch(armv7) returns 1 for the target arch "armv7" __is_target_arch(armv6) returns 0 for the target arch "armv7" __is_target_vendor and __is_target_environment match the specific vendor or environment. __is_target_os matches the specific OS, but __is_target_os(darwin) will match any Darwin-based OS. "Unknown" can be used to test if the triple's component is specified. rdar://35753116 Differential Revision: https://reviews.llvm.org/D41087 llvm-svn: 320734
Diffstat (limited to 'clang/lib/Lex/PPMacroExpansion.cpp')
-rw-r--r--clang/lib/Lex/PPMacroExpansion.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp
index 2d83badfee9..3d72006bad4 100644
--- a/clang/lib/Lex/PPMacroExpansion.cpp
+++ b/clang/lib/Lex/PPMacroExpansion.cpp
@@ -375,6 +375,11 @@ void Preprocessor::RegisterBuiltinMacros() {
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");
@@ -1593,6 +1598,57 @@ 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.getArch() == TT.getArch()) ||
+ Arch.getArchName() == TT.getArchName();
+}
+
+/// 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) {
+ StringRef EnvName = TI.getTriple().getEnvironmentName();
+ if (EnvName.empty())
+ EnvName = "unknown";
+ return EnvName.equals_lower(II->getName());
+}
+
/// 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) {
@@ -1755,6 +1811,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);
}
});
@@ -1906,6 +1966,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!");
}
OpenPOWER on IntegriCloud