Index: clang/docs/LanguageExtensions.rst =================================================================== --- clang/docs/LanguageExtensions.rst +++ clang/docs/LanguageExtensions.rst @@ -257,6 +257,28 @@ __wchar_t WideCharacter; ... +``__has_target_feature`` +------------------------ + +This function-like macro takes a single string literal argument that is the name of +a target feature. It evaluates to 1 if the target feature is enabled or 0 if not. +It can be used like this: + +.. code-block:: c++ + + #ifndef __has_target_feature // Optional of course. + #define __has_target_feature(x) 0 // Compatibility with non-clang compilers. + #endif + + ... + // On amdgcn target + #if __has_target_feature("s-memtime-inst") + x = __builtin_amdgcn_s_memtime(); + #else + x = __builtin_readcyclecounter(); + #endif + ... + Include File Checking Macros ============================ Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -68,6 +68,9 @@ Randomizing structure layout is a C-only feature. +- Clang now supports function-like macro __has_target_feature which returns 1 + if the specified target feature is enabled. + Bug Fixes ------------------ - ``CXXNewExpr::getArraySize()`` previously returned a ``llvm::Optional`` Index: clang/include/clang/Lex/Preprocessor.h =================================================================== --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -166,6 +166,7 @@ IdentifierInfo *Ident__has_feature; // __has_feature IdentifierInfo *Ident__has_extension; // __has_extension IdentifierInfo *Ident__has_builtin; // __has_builtin + IdentifierInfo *Ident__has_target_feature; // __has_target_feature IdentifierInfo *Ident__has_attribute; // __has_attribute IdentifierInfo *Ident__has_include; // __has_include IdentifierInfo *Ident__has_include_next; // __has_include_next Index: clang/lib/Lex/PPMacroExpansion.cpp =================================================================== --- clang/lib/Lex/PPMacroExpansion.cpp +++ clang/lib/Lex/PPMacroExpansion.cpp @@ -370,7 +370,9 @@ Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature"); Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension"); Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); - Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute"); + Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin"); + Ident__has_target_feature = + RegisterBuiltinMacro(*this, "__has_target_feature"); if (!getLangOpts().CPlusPlus) Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute"); else @@ -1618,6 +1620,20 @@ diag::err_feature_check_malformed); return II && HasFeature(*this, II->getName()); }); + } else if (II == Ident__has_target_feature) { + EvaluateFeatureLikeBuiltinMacro( + OS, Tok, II, *this, false, + [this](Token &Tok, bool &HasLexedNextToken) -> int { + std::string TargetFeatureName; + HasLexedNextToken = Tok.is(tok::string_literal); + if (!FinishLexStringLiteral(Tok, TargetFeatureName, + "'__has_target_feature'", + /*AllowMacroExpansion=*/false)) + return false; + auto FeatureMap = getTargetInfo().getTargetOpts().FeatureMap; + auto Loc = FeatureMap.find(TargetFeatureName); + return Loc != FeatureMap.end() && Loc->second; + }); } else if (II == Ident__has_extension) { EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false, [this](Token &Tok, bool &HasLexedNextToken) -> int { Index: clang/test/Lexer/has_target_feature.cpp =================================================================== --- /dev/null +++ clang/test/Lexer/has_target_feature.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx906 -E %s -o - | FileCheck %s + +// CHECK: has_s_memtime_inst +#if __has_target_feature("s-memtime-inst") + int has_s_memtime_inst; +#endif + +// CHECK-NOT: has_gfx10_inst +#if __has_target_feature("gfx10-inst") + int has_gfx10_inst; +#endif