LLVM __has_feature

今天在项目中遇到了__has_feature(objc_arc)宏,通过查找文档发现该宏语句是用来判断clang(编译前端)是否支持某个功能特性,这里是判断是否支持objc_arc(自动引用计数)。

栗子:

#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif

Clang文档中的定义:

__has_feature and __has_extension

These function-like macros take a single identifier argument that is the name of a feature. __has_feature evaluates to 1 if the feature is both supported by Clang and standardized in the current language standard or 0 if not (but see below), while __has_extension evaluates to 1 if the feature is supported by Clang in the current language (either as a language extension or a standard language feature) or 0 if not. They can be used like this:

#ifndef __has_feature         // Optional of course.
  #define __has_feature(x) 0  // Compatibility with non-clang compilers.
#endif
#ifndef __has_extension
  #define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
#endif

...
#if __has_feature(cxx_rvalue_references)
// This code will only be compiled with the -std=c++11 and -std=gnu++11
// options, because rvalue references are only standardized in C++11.
#endif

#if __has_extension(cxx_rvalue_references)
// This code will be compiled with the -std=c++11, -std=gnu++11, -std=c++98
// and -std=gnu++98 options, because rvalue references are supported as a
// language extension in C++98.
#endif

For backward compatibility, __has_feature can also be used to test for support for non-standardized features, i.e. features not prefixed c_, cxx_ or objc_.

Another use of __has_feature is to check for compiler features not related to the language standard, such as e.g. AddressSanitizer.

If the -pedantic-errors option is given, __has_extension is equivalent to __has_feature.

The feature tag is described along with the language feature below.

The feature name or extension name can also be specified with a preceding and following __ (double underscore) to avoid interference from a macro with the same name. For instance, __cxx_rvalue_references__ can be used instead of cxx_rvalue_references.

clang API Documentation:

00855 /// HasFeature - Return true if we recognize and implement the feature
00856 /// specified by the identifier as a standard language feature.
00857 static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
00858   const LangOptions &LangOpts = PP.getLangOpts();
00859   StringRef Feature = II->getName();
00860 
00861   // Normalize the feature name, __foo__ becomes foo.
00862   if (Feature.startswith("__") && Feature.endswith("__") && Feature.size() >= 4)
00863     Feature = Feature.substr(2, Feature.size() - 4);
00864 
00865   return llvm::StringSwitch<bool>(Feature)
00866       .Case("address_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Address))
00867       .Case("attribute_analyzer_noreturn", true)
00868       .Case("attribute_availability", true)
00869       .Case("attribute_availability_with_message", true)
00870       .Case("attribute_cf_returns_not_retained", true)
00871       .Case("attribute_cf_returns_retained", true)
00872       .Case("attribute_deprecated_with_message", true)
00873       .Case("attribute_ext_vector_type", true)
00874       .Case("attribute_ns_returns_not_retained", true)
00875       .Case("attribute_ns_returns_retained", true)
00876       .Case("attribute_ns_consumes_self", true)
00877       .Case("attribute_ns_consumed", true)
00878       .Case("attribute_cf_consumed", true)
00879       .Case("attribute_objc_ivar_unused", true)
00880       .Case("attribute_objc_method_family", true)
00881       .Case("attribute_overloadable", true)
00882       .Case("attribute_unavailable_with_message", true)
00883       .Case("attribute_unused_on_fields", true)
00884       .Case("blocks", LangOpts.Blocks)
00885       .Case("c_thread_safety_attributes", true)
00886       .Case("cxx_exceptions", LangOpts.CXXExceptions)
00887       .Case("cxx_rtti", LangOpts.RTTI)
00888       .Case("enumerator_attributes", true)
00889       .Case("memory_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Memory))
00890       .Case("thread_sanitizer", LangOpts.Sanitize.has(SanitizerKind::Thread))
00891       .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow))
00892       // Objective-C features
00893       .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE?
00894       .Case("objc_arc", LangOpts.ObjCAutoRefCount)
00895       .Case("objc_arc_weak", LangOpts.ObjCARCWeak)
00896       .Case("objc_default_synthesize_properties", LangOpts.ObjC2)
00897       .Case("objc_fixed_enum", LangOpts.ObjC2)
00898       .Case("objc_instancetype", LangOpts.ObjC2)
00899       .Case("objc_modules", LangOpts.ObjC2 && LangOpts.Modules)
00900       .Case("objc_nonfragile_abi", LangOpts.ObjCRuntime.isNonFragile())
00901       .Case("objc_property_explicit_atomic",
00902             true) // Does clang support explicit "atomic" keyword?
00903       .Case("objc_protocol_qualifier_mangling", true)
00904       .Case("objc_weak_class", LangOpts.ObjCRuntime.hasWeakClassImport())
00905       .Case("ownership_holds", true)
00906       .Case("ownership_returns", true)
00907       .Case("ownership_takes", true)
00908       .Case("objc_bool", true)
00909       .Case("objc_subscripting", LangOpts.ObjCRuntime.isNonFragile())
00910       .Case("objc_array_literals", LangOpts.ObjC2)
00911       .Case("objc_dictionary_literals", LangOpts.ObjC2)
00912       .Case("objc_boxed_expressions", LangOpts.ObjC2)
00913       .Case("arc_cf_code_audited", true)
00914       // C11 features
00915       .Case("c_alignas", LangOpts.C11)
00916       .Case("c_atomic", LangOpts.C11)
00917       .Case("c_generic_selections", LangOpts.C11)
00918       .Case("c_static_assert", LangOpts.C11)
00919       .Case("c_thread_local",
00920             LangOpts.C11 && PP.getTargetInfo().isTLSSupported())
00921       // C++11 features
00922       .Case("cxx_access_control_sfinae", LangOpts.CPlusPlus11)
00923       .Case("cxx_alias_templates", LangOpts.CPlusPlus11)
00924       .Case("cxx_alignas", LangOpts.CPlusPlus11)
00925       .Case("cxx_atomic", LangOpts.CPlusPlus11)
00926       .Case("cxx_attributes", LangOpts.CPlusPlus11)
00927       .Case("cxx_auto_type", LangOpts.CPlusPlus11)
00928       .Case("cxx_constexpr", LangOpts.CPlusPlus11)
00929       .Case("cxx_decltype", LangOpts.CPlusPlus11)
00930       .Case("cxx_decltype_incomplete_return_types", LangOpts.CPlusPlus11)
00931       .Case("cxx_default_function_template_args", LangOpts.CPlusPlus11)
00932       .Case("cxx_defaulted_functions", LangOpts.CPlusPlus11)
00933       .Case("cxx_delegating_constructors", LangOpts.CPlusPlus11)
00934       .Case("cxx_deleted_functions", LangOpts.CPlusPlus11)
00935       .Case("cxx_explicit_conversions", LangOpts.CPlusPlus11)
00936       .Case("cxx_generalized_initializers", LangOpts.CPlusPlus11)
00937       .Case("cxx_implicit_moves", LangOpts.CPlusPlus11)
00938       .Case("cxx_inheriting_constructors", LangOpts.CPlusPlus11)
00939       .Case("cxx_inline_namespaces", LangOpts.CPlusPlus11)
00940       .Case("cxx_lambdas", LangOpts.CPlusPlus11)
00941       .Case("cxx_local_type_template_args", LangOpts.CPlusPlus11)
00942       .Case("cxx_nonstatic_member_init", LangOpts.CPlusPlus11)
00943       .Case("cxx_noexcept", LangOpts.CPlusPlus11)
00944       .Case("cxx_nullptr", LangOpts.CPlusPlus11)
00945       .Case("cxx_override_control", LangOpts.CPlusPlus11)
00946       .Case("cxx_range_for", LangOpts.CPlusPlus11)
00947       .Case("cxx_raw_string_literals", LangOpts.CPlusPlus11)
00948       .Case("cxx_reference_qualified_functions", LangOpts.CPlusPlus11)
00949       .Case("cxx_rvalue_references", LangOpts.CPlusPlus11)
00950       .Case("cxx_strong_enums", LangOpts.CPlusPlus11)
00951       .Case("cxx_static_assert", LangOpts.CPlusPlus11)
00952       .Case("cxx_thread_local",
00953             LangOpts.CPlusPlus11 && PP.getTargetInfo().isTLSSupported())
00954       .Case("cxx_trailing_return", LangOpts.CPlusPlus11)
00955       .Case("cxx_unicode_literals", LangOpts.CPlusPlus11)
00956       .Case("cxx_unrestricted_unions", LangOpts.CPlusPlus11)
00957       .Case("cxx_user_literals", LangOpts.CPlusPlus11)
00958       .Case("cxx_variadic_templates", LangOpts.CPlusPlus11)
00959       // C++1y features
00960       .Case("cxx_aggregate_nsdmi", LangOpts.CPlusPlus14)
00961       .Case("cxx_binary_literals", LangOpts.CPlusPlus14)
00962       .Case("cxx_contextual_conversions", LangOpts.CPlusPlus14)
00963       .Case("cxx_decltype_auto", LangOpts.CPlusPlus14)
00964       .Case("cxx_generic_lambdas", LangOpts.CPlusPlus14)
00965       .Case("cxx_init_captures", LangOpts.CPlusPlus14)
00966       .Case("cxx_relaxed_constexpr", LangOpts.CPlusPlus14)
00967       .Case("cxx_return_type_deduction", LangOpts.CPlusPlus14)
00968       .Case("cxx_variable_templates", LangOpts.CPlusPlus14)
00969       // C++ TSes
00970       //.Case("cxx_runtime_arrays", LangOpts.CPlusPlusTSArrays)
00971       //.Case("cxx_concepts", LangOpts.CPlusPlusTSConcepts)
00972       // FIXME: Should this be __has_feature or __has_extension?
00973       //.Case("raw_invocation_type", LangOpts.CPlusPlus)
00974       // Type traits
00975       .Case("has_nothrow_assign", LangOpts.CPlusPlus)
00976       .Case("has_nothrow_copy", LangOpts.CPlusPlus)
00977       .Case("has_nothrow_constructor", LangOpts.CPlusPlus)
00978       .Case("has_trivial_assign", LangOpts.CPlusPlus)
00979       .Case("has_trivial_copy", LangOpts.CPlusPlus)
00980       .Case("has_trivial_constructor", LangOpts.CPlusPlus)
00981       .Case("has_trivial_destructor", LangOpts.CPlusPlus)
00982       .Case("has_virtual_destructor", LangOpts.CPlusPlus)
00983       .Case("is_abstract", LangOpts.CPlusPlus)
00984       .Case("is_base_of", LangOpts.CPlusPlus)
00985       .Case("is_class", LangOpts.CPlusPlus)
00986       .Case("is_constructible", LangOpts.CPlusPlus)
00987       .Case("is_convertible_to", LangOpts.CPlusPlus)
00988       .Case("is_empty", LangOpts.CPlusPlus)
00989       .Case("is_enum", LangOpts.CPlusPlus)
00990       .Case("is_final", LangOpts.CPlusPlus)
00991       .Case("is_literal", LangOpts.CPlusPlus)
00992       .Case("is_standard_layout", LangOpts.CPlusPlus)
00993       .Case("is_pod", LangOpts.CPlusPlus)
00994       .Case("is_polymorphic", LangOpts.CPlusPlus)
00995       .Case("is_sealed", LangOpts.MicrosoftExt)
00996       .Case("is_trivial", LangOpts.CPlusPlus)
00997       .Case("is_trivially_assignable", LangOpts.CPlusPlus)
00998       .Case("is_trivially_constructible", LangOpts.CPlusPlus)
00999       .Case("is_trivially_copyable", LangOpts.CPlusPlus)
01000       .Case("is_union", LangOpts.CPlusPlus)
01001       .Case("modules", LangOpts.Modules)
01002       .Case("tls", PP.getTargetInfo().isTLSSupported())
01003       .Case("underlying_type", LangOpts.CPlusPlus)
01004       .Default(false);
01005 }

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • 在iOS开发中总能看见__has_feature宏,最常见的例如__has_feature(objc_arc),表...
    Miridescent阅读 3,386评论 0 3
  • 前言 通过阅读别人的优秀源码,你会发现别人的开源API设计中,有一些宏你是经常忽略的,或者你不知道的。通过这些宏,...
    gitKong阅读 5,166评论 5 41
  • 参考链接今天看 MJRefresh 源码有一段忽略获的代码,借机整理下相关内容 #pragma在本质上是声明,常用...
    wpf_register阅读 6,812评论 0 2
  • C++ 开源库列表https://en.cppreference.com/w/cpp/links/libs[htt...
    老陕西阅读 2,093评论 0 0
  • This chapter discusses some of the design decisions that ...
    狂风无迹阅读 974评论 0 0