jfb created this revision.
jfb added reviewers: mclow.lists, rsmith.
jfb added a subscriber: cfe-commits.
Herald added subscribers: dschuff, jfb.

This was voted into C++17 at last week's Jacksonville meeting. The final 
P0152R1 paper will be in the upcoming post-Jacksonville mailing, and is also 
available here:
  http://jfbastien.github.io/papers/P0152R1.html

The libc++ part of this implementation is in the following code review:
  <TODO inter-dependent code reviews...>

http://reviews.llvm.org/D17950

Files:
  lib/Frontend/InitPreprocessor.cpp
  test/Lexer/cxx-features.cpp
  test/Preprocessor/init.c

Index: test/Preprocessor/init.c
===================================================================
--- test/Preprocessor/init.c
+++ test/Preprocessor/init.c
@@ -3282,7 +3282,10 @@
 // MIPSN32BE: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
 // MIPSN32BE: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
 // MIPSN32BE: #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// MIPSN32BE: #define __GCC_ATOMIC_DOUBLE_LOCK_FREE 2
+// MIPSN32BE: #define __GCC_ATOMIC_FLOAT_LOCK_FREE 2
 // MIPSN32BE: #define __GCC_ATOMIC_INT_LOCK_FREE 2
+// MIPSN32BE: #define __GCC_ATOMIC_LDOUBLE_LOCK_FREE 1
 // MIPSN32BE: #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
 // MIPSN32BE: #define __GCC_ATOMIC_LONG_LOCK_FREE 2
 // MIPSN32BE: #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
@@ -3372,6 +3375,12 @@
 // MIPSN32BE: #define __LDBL_MIN_10_EXP__ (-4931)
 // MIPSN32BE: #define __LDBL_MIN_EXP__ (-16381)
 // MIPSN32BE: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+// MIPSN32BE: #define __LLVM_ATOMIC_16_BYTES_LOCK_FREE 1
+// MIPSN32BE: #define __LLVM_ATOMIC_1_BYTES_LOCK_FREE 2
+// MIPSN32BE: #define __LLVM_ATOMIC_2_BYTES_LOCK_FREE 2
+// MIPSN32BE: #define __LLVM_ATOMIC_4_BYTES_LOCK_FREE 2
+// MIPSN32BE: #define __LLVM_ATOMIC_8_BYTES_LOCK_FREE 2
+// MIPSN32BE: #define __LLVM_LOCK_FREE_IS_SIZE_BASED 1
 // MIPSN32BE: #define __LONG_LONG_MAX__ 9223372036854775807LL
 // MIPSN32BE: #define __LONG_MAX__ 2147483647L
 // MIPSN32BE: #define __MIPSEB 1
@@ -3587,7 +3596,10 @@
 // MIPSN32EL: #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
 // MIPSN32EL: #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
 // MIPSN32EL: #define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// MIPSN32EL: #define __GCC_ATOMIC_DOUBLE_LOCK_FREE 2
+// MIPSN32EL: #define __GCC_ATOMIC_FLOAT_LOCK_FREE 2
 // MIPSN32EL: #define __GCC_ATOMIC_INT_LOCK_FREE 2
+// MIPSN32EL: #define __GCC_ATOMIC_LDOUBLE_LOCK_FREE 1
 // MIPSN32EL: #define __GCC_ATOMIC_LLONG_LOCK_FREE 2
 // MIPSN32EL: #define __GCC_ATOMIC_LONG_LOCK_FREE 2
 // MIPSN32EL: #define __GCC_ATOMIC_POINTER_LOCK_FREE 2
@@ -3678,6 +3690,12 @@
 // MIPSN32EL: #define __LDBL_MIN_EXP__ (-16381)
 // MIPSN32EL: #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
 // MIPSN32EL: #define __LITTLE_ENDIAN__ 1
+// MIPSN32EL: #define __LLVM_ATOMIC_16_BYTES_LOCK_FREE 1
+// MIPSN32EL: #define __LLVM_ATOMIC_1_BYTES_LOCK_FREE 2
+// MIPSN32EL: #define __LLVM_ATOMIC_2_BYTES_LOCK_FREE 2
+// MIPSN32EL: #define __LLVM_ATOMIC_4_BYTES_LOCK_FREE 2
+// MIPSN32EL: #define __LLVM_ATOMIC_8_BYTES_LOCK_FREE 2
+// MIPSN32EL: #define __LLVM_LOCK_FREE_IS_SIZE_BASED 1
 // MIPSN32EL: #define __LONG_LONG_MAX__ 9223372036854775807LL
 // MIPSN32EL: #define __LONG_MAX__ 2147483647L
 // MIPSN32EL: #define __MIPSEL 1
@@ -7614,7 +7632,10 @@
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __GCC_ATOMIC_DOUBLE_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __GCC_ATOMIC_FLOAT_LOCK_FREE 2
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_INT_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __GCC_ATOMIC_LDOUBLE_LOCK_FREE 2
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
 // X86_64-CLOUDABI:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
@@ -7705,6 +7726,12 @@
 // X86_64-CLOUDABI:#define __LDBL_MIN_EXP__ (-16381)
 // X86_64-CLOUDABI:#define __LDBL_MIN__ 3.36210314311209350626e-4932L
 // X86_64-CLOUDABI:#define __LITTLE_ENDIAN__ 1
+// X86_64-CLOUDABI:#define __LLVM_ATOMIC_16_BYTES_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __LLVM_ATOMIC_1_BYTES_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __LLVM_ATOMIC_2_BYTES_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __LLVM_ATOMIC_4_BYTES_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __LLVM_ATOMIC_8_BYTES_LOCK_FREE 2
+// X86_64-CLOUDABI:#define __LLVM_LOCK_FREE_IS_SIZE_BASED 1
 // X86_64-CLOUDABI:#define __LONG_LONG_MAX__ 9223372036854775807LL
 // X86_64-CLOUDABI:#define __LONG_MAX__ 9223372036854775807L
 // X86_64-CLOUDABI:#define __LP64__ 1
@@ -8478,7 +8505,10 @@
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_DOUBLE_LOCK_FREE 1
+// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_FLOAT_LOCK_FREE 2
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2
+// WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LDOUBLE_LOCK_FREE 1
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 1
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
 // WEBASSEMBLY32-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
@@ -8570,6 +8600,12 @@
 // WEBASSEMBLY32-NEXT:#define __LDBL_MIN_EXP__ (-16381)
 // WEBASSEMBLY32-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
 // WEBASSEMBLY32-NEXT:#define __LITTLE_ENDIAN__ 1
+// WEBASSEMBLY32-NEXT:#define __LLVM_ATOMIC_16_BYTES_LOCK_FREE 1
+// WEBASSEMBLY32-NEXT:#define __LLVM_ATOMIC_1_BYTES_LOCK_FREE 2
+// WEBASSEMBLY32-NEXT:#define __LLVM_ATOMIC_2_BYTES_LOCK_FREE 2
+// WEBASSEMBLY32-NEXT:#define __LLVM_ATOMIC_4_BYTES_LOCK_FREE 2
+// WEBASSEMBLY32-NEXT:#define __LLVM_ATOMIC_8_BYTES_LOCK_FREE 1
+// WEBASSEMBLY32-NEXT:#define __LLVM_LOCK_FREE_IS_SIZE_BASED 1
 // WEBASSEMBLY32-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL
 // WEBASSEMBLY32-NEXT:#define __LONG_MAX__ 2147483647L
 // WEBASSEMBLY32-NOT:#define __LP64__
@@ -8793,7 +8829,10 @@
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_CHAR_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_DOUBLE_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_FLOAT_LOCK_FREE 2
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_INT_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LDOUBLE_LOCK_FREE 1
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LLONG_LOCK_FREE 2
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_LONG_LOCK_FREE 2
 // WEBASSEMBLY64-NEXT:#define __GCC_ATOMIC_POINTER_LOCK_FREE 2
@@ -8885,6 +8924,12 @@
 // WEBASSEMBLY64-NEXT:#define __LDBL_MIN_EXP__ (-16381)
 // WEBASSEMBLY64-NEXT:#define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
 // WEBASSEMBLY64-NEXT:#define __LITTLE_ENDIAN__ 1
+// WEBASSEMBLY64-NEXT:#define __LLVM_ATOMIC_16_BYTES_LOCK_FREE 1
+// WEBASSEMBLY64-NEXT:#define __LLVM_ATOMIC_1_BYTES_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __LLVM_ATOMIC_2_BYTES_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __LLVM_ATOMIC_4_BYTES_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __LLVM_ATOMIC_8_BYTES_LOCK_FREE 2
+// WEBASSEMBLY64-NEXT:#define __LLVM_LOCK_FREE_IS_SIZE_BASED 1
 // WEBASSEMBLY64-NEXT:#define __LONG_LONG_MAX__ 9223372036854775807LL
 // WEBASSEMBLY64-NEXT:#define __LONG_MAX__ 9223372036854775807L
 // WEBASSEMBLY64-NEXT:#define __LP64__ 1
@@ -9057,4 +9102,3 @@
 
 // RUN: %clang_cc1 -E -dM -ffreestanding -triple x86_64-windows-cygnus < /dev/null | FileCheck -match-full-lines -check-prefix CYGWIN-X64 %s
 // CYGWIN-X64: #define __USER_LABEL_PREFIX__
-
Index: test/Lexer/cxx-features.cpp
===================================================================
--- test/Lexer/cxx-features.cpp
+++ test/Lexer/cxx-features.cpp
@@ -1,133 +1,141 @@
 // RUN: %clang_cc1 -std=c++98 -verify %s
 // RUN: %clang_cc1 -std=c++11 -verify %s
 // RUN: %clang_cc1 -std=c++1y -fsized-deallocation -verify %s
-// RUN: %clang_cc1 -std=c++1y -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
+// RUN: %clang_cc1 -std=c++14 -fsized-deallocation -verify %s
+// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -verify %s
+// RUN: %clang_cc1 -std=c++1z -fsized-deallocation -fconcepts-ts -DCONCEPTS_TS=1 -verify %s
 // RUN: %clang_cc1 -fcoroutines -DCOROUTINES -verify %s
 
 // expected-no-diagnostics
 
 // FIXME using `defined` in a macro has undefined behavior.
 #if __cplusplus < 201103L
-#define check(macro, cxx98, cxx11, cxx1y) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
-#elif __cplusplus < 201304L
-#define check(macro, cxx98, cxx11, cxx1y) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
+#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx98 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx98
+#elif __cplusplus < 201402L
+#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx11 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx11
+#elif __cplusplus < 201406L
+#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx14 == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx14
 #else
-#define check(macro, cxx98, cxx11, cxx1y) cxx1y == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1y
+#define check(macro, cxx98, cxx11, cxx14, cxx1z) cxx1z == 0 ? defined(__cpp_##macro) : __cpp_##macro != cxx1z
 #endif
 
-#if check(binary_literals, 0, 0, 201304)
+#if check(binary_literals, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_binary_literals"
 #endif
 
-#if check(digit_separators, 0, 0, 201309)
+#if check(digit_separators, 0, 0, 201309, 201309)
 #error "wrong value for __cpp_digit_separators"
 #endif
 
-#if check(init_captures, 0, 0, 201304)
+#if check(init_captures, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_init_captures"
 #endif
 
-#if check(generic_lambdas, 0, 0, 201304)
+#if check(generic_lambdas, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_generic_lambdas"
 #endif
 
-#if check(sized_deallocation, 0, 0, 201309)
+#if check(sized_deallocation, 0, 0, 201309, 201309)
 #error "wrong value for __cpp_sized_deallocation"
 #endif
 
-#if check(constexpr, 0, 200704, 201304)
+#if check(constexpr, 0, 200704, 201304, 201304)
 #error "wrong value for __cpp_constexpr"
 #endif
 
-#if check(decltype_auto, 0, 0, 201304)
+#if check(decltype_auto, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_decltype_auto"
 #endif
 
-#if check(return_type_deduction, 0, 0, 201304)
+#if check(return_type_deduction, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_return_type_deduction"
 #endif
 
-#if check(runtime_arrays, 0, 0, 0)
+#if check(runtime_arrays, 0, 0, 0, 0)
 #error "wrong value for __cpp_runtime_arrays"
 #endif
 
-#if check(aggregate_nsdmi, 0, 0, 201304)
+#if check(aggregate_nsdmi, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_aggregate_nsdmi"
 #endif
 
-#if check(variable_templates, 0, 0, 201304)
+#if check(variable_templates, 0, 0, 201304, 201304)
 #error "wrong value for __cpp_variable_templates"
 #endif
 
-#if check(unicode_characters, 0, 200704, 200704)
+#if check(unicode_characters, 0, 200704, 200704, 200704)
 #error "wrong value for __cpp_unicode_characters"
 #endif
 
-#if check(raw_strings, 0, 200710, 200710)
+#if check(raw_strings, 0, 200710, 200710, 200710)
 #error "wrong value for __cpp_raw_strings"
 #endif
 
-#if check(unicode_literals, 0, 200710, 200710)
+#if check(unicode_literals, 0, 200710, 200710, 200710)
 #error "wrong value for __cpp_unicode_literals"
 #endif
 
-#if check(user_defined_literals, 0, 200809, 200809)
+#if check(user_defined_literals, 0, 200809, 200809, 200809)
 #error "wrong value for __cpp_user_defined_literals"
 #endif
 
-#if check(lambdas, 0, 200907, 200907)
+#if check(lambdas, 0, 200907, 200907, 200907)
 #error "wrong value for __cpp_lambdas"
 #endif
 
-#if check(range_based_for, 0, 200907, 200907)
+#if check(range_based_for, 0, 200907, 200907, 200907)
 #error "wrong value for __cpp_range_based_for"
 #endif
 
-#if check(static_assert, 0, 200410, 200410)
+#if check(static_assert, 0, 200410, 200410, 200410)
 #error "wrong value for __cpp_static_assert"
 #endif
 
-#if check(decltype, 0, 200707, 200707)
+#if check(decltype, 0, 200707, 200707, 200707)
 #error "wrong value for __cpp_decltype"
 #endif
 
-#if check(attributes, 0, 200809, 200809)
+#if check(attributes, 0, 200809, 200809, 200809)
 #error "wrong value for __cpp_attributes"
 #endif
 
-#if check(rvalue_references, 0, 200610, 200610)
+#if check(rvalue_references, 0, 200610, 200610, 200610)
 #error "wrong value for __cpp_rvalue_references"
 #endif
 
-#if check(variadic_templates, 0, 200704, 200704)
+#if check(variadic_templates, 0, 200704, 200704, 200704)
 #error "wrong value for __cpp_variadic_templates"
 #endif
 
-#if check(initializer_lists, 0, 200806, 200806)
+#if check(initializer_lists, 0, 200806, 200806, 200806)
 #error "wrong value for __cpp_initializer_lists"
 #endif
 
-#if check(delegating_constructors, 0, 200604, 200604)
+#if check(delegating_constructors, 0, 200604, 200604, 200604)
 #error "wrong value for __cpp_delegating_constructors"
 #endif
 
-#if check(nsdmi, 0, 200809, 200809)
+#if check(nsdmi, 0, 200809, 200809, 200809)
 #error "wrong value for __cpp_nsdmi"
 #endif
 
-#if check(inheriting_constructors, 0, 200802, 200802)
+#if check(inheriting_constructors, 0, 200802, 200802, 200802)
 #error "wrong value for __cpp_inheriting_constructors"
 #endif
 
-#if check(ref_qualifiers, 0, 200710, 200710)
+#if check(ref_qualifiers, 0, 200710, 200710, 200710)
 #error "wrong value for __cpp_ref_qualifiers"
 #endif
 
-#if check(alias_templates, 0, 200704, 200704)
+#if check(alias_templates, 0, 200704, 200704, 200704)
 #error "wrong value for __cpp_alias_templates"
 #endif
 
-#if check(experimental_concepts, 0, 0, CONCEPTS_TS)
+#if check(lib_atomic_is_always_lock_free, 0, 0, 0, 201603)
+#error "wrong value for __cpp_lib_atomic_is_always_lock_free"
+#endif
+
+#if check(experimental_concepts, 0, 0, CONCEPTS_TS, CONCEPTS_TS)
 #error "wrong value for __cpp_experimental_concepts"
 #endif
 
Index: lib/Frontend/InitPreprocessor.cpp
===================================================================
--- lib/Frontend/InitPreprocessor.cpp
+++ lib/Frontend/InitPreprocessor.cpp
@@ -286,20 +286,35 @@
   DefineFmt(Prefix + Twine(TypeWidth), Ty, TI, Builder);
 }
 
+/// Get values for:
+///  - ATOMIC_*_LOCK_FREE macros
+///  - constexpr is_always_lock_free
+struct LockFree {
+  enum Value { Never, Sometimes, Always };  // Values specified by C standard.
+
+  // Currently LLVM always bases lock-freeness on the size of the type, and not
+  // on type of address. Were this to change then constexpr is_always_lock_free
+  // couldn't base its value solely on sizeof(T).
+  static bool getIsSizeBased() { return true; }
+
+  static Value getValue(unsigned TypeWidth, unsigned TypeAlign,
+                        unsigned InlineWidth) {
+    // Fully-aligned, power-of-2 sizes no larger than the inline width will be
+    // inlined as lock-free operations.
+    if (TypeWidth == TypeAlign && (TypeWidth & (TypeWidth - 1)) == 0 &&
+        TypeWidth <= InlineWidth)
+      return Always;
+    // We cannot be certain what operations the lib calls might be able to
+    // implement as lock-free on future processors.
+    return Sometimes;
+  }
 
-/// Get the value the ATOMIC_*_LOCK_FREE macro should have for a type with
-/// the specified properties.
-static const char *getLockFreeValue(unsigned TypeWidth, unsigned TypeAlign,
-                                    unsigned InlineWidth) {
-  // Fully-aligned, power-of-2 sizes no larger than the inline
-  // width will be inlined as lock-free operations.
-  if (TypeWidth == TypeAlign && (TypeWidth & (TypeWidth - 1)) == 0 &&
-      TypeWidth <= InlineWidth)
-    return "2"; // "always lock free"
-  // We cannot be certain what operations the lib calls might be
-  // able to implement as lock-free on future processors.
-  return "1"; // "sometimes lock free"
-}
+  static const char *getString(unsigned TypeWidth, unsigned TypeAlign,
+                               unsigned InlineWidth) {
+    static const char *str[] = {"0", "1", "2"};
+    return str[getValue(TypeWidth, TypeAlign, InlineWidth)];
+  }
+};
 
 /// \brief Add definitions required for a smooth interaction between
 /// Objective-C++ automated reference counting and libstdc++ (4.2).
@@ -459,6 +474,12 @@
     Builder.defineMacro("__cpp_aggregate_nsdmi", "201304");
     Builder.defineMacro("__cpp_variable_templates", "201304");
   }
+
+  // C++17 features.
+  if (LangOpts.CPlusPlus1z) {
+    Builder.defineMacro("__cpp_lib_atomic_is_always_lock_free", "201603");
+  }
+
   if (LangOpts.SizedDeallocation)
     Builder.defineMacro("__cpp_sized_deallocation", "201309");
   if (LangOpts.ConceptsTS)
@@ -813,11 +834,11 @@
 
     // Used by libstdc++ to implement ATOMIC_<foo>_LOCK_FREE.
     unsigned InlineWidthBits = TI.getMaxAtomicInlineWidth();
-#define DEFINE_LOCK_FREE_MACRO(TYPE, Type) \
-    Builder.defineMacro("__GCC_ATOMIC_" #TYPE "_LOCK_FREE", \
-                        getLockFreeValue(TI.get##Type##Width(), \
-                                         TI.get##Type##Align(), \
-                                         InlineWidthBits));
+#define DEFINE_LOCK_FREE_MACRO(TYPE, Type)                                     \
+  Builder.defineMacro("__GCC_ATOMIC_" #TYPE "_LOCK_FREE",                      \
+                      LockFree::getString(TI.get##Type##Width(),               \
+                                          TI.get##Type##Align(),               \
+                                          InlineWidthBits));
     DEFINE_LOCK_FREE_MACRO(BOOL, Bool);
     DEFINE_LOCK_FREE_MACRO(CHAR, Char);
     DEFINE_LOCK_FREE_MACRO(CHAR16_T, Char16);
@@ -827,10 +848,33 @@
     DEFINE_LOCK_FREE_MACRO(INT, Int);
     DEFINE_LOCK_FREE_MACRO(LONG, Long);
     DEFINE_LOCK_FREE_MACRO(LLONG, LongLong);
+    DEFINE_LOCK_FREE_MACRO(FLOAT, Float);
+    DEFINE_LOCK_FREE_MACRO(DOUBLE, Double);
+    DEFINE_LOCK_FREE_MACRO(LDOUBLE, LongDouble);
     Builder.defineMacro("__GCC_ATOMIC_POINTER_LOCK_FREE",
-                        getLockFreeValue(TI.getPointerWidth(0),
-                                         TI.getPointerAlign(0),
-                                         InlineWidthBits));
+                        LockFree::getString(TI.getPointerWidth(0),
+                                            TI.getPointerAlign(0),
+                                            InlineWidthBits));
+#undef DEFINE_LOCK_FREE_MACRO
+
+    // Used by libc++ to implement constexpr is_always_lock_free.
+    Builder.defineMacro("__LLVM_LOCK_FREE_IS_SIZE_BASED",
+                        LockFree::getIsSizeBased() ? "1" : "0");
+#define DEFINE_LOCK_FREE_MACRO(BYTES)                                          \
+  Builder.defineMacro(                                                         \
+      "__LLVM_ATOMIC_" #BYTES "_BYTES_LOCK_FREE",                              \
+      LockFree::getString(BYTES * 8, BYTES * 8, InlineWidthBits));
+    if (LockFree::getIsSizeBased()) {
+      DEFINE_LOCK_FREE_MACRO(1);
+      DEFINE_LOCK_FREE_MACRO(2);
+      DEFINE_LOCK_FREE_MACRO(4);
+      DEFINE_LOCK_FREE_MACRO(8);
+      DEFINE_LOCK_FREE_MACRO(16);
+      // constexpr is_always_lock_free is optimistic, it's therefore acceptable
+      // to state "0" even if the implementation is actually always
+      // lock-free. If architectures support wider lock-free operations then
+      // more macro definitions can be appended.
+    }
 #undef DEFINE_LOCK_FREE_MACRO
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to