diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -110,6 +110,7 @@ ------------------- - Implemented `WG14 N2674 The noreturn attribute `_. +- Implemented `WG14 N2935 Make false and true first-class language features `_. C++ Language Changes in Clang ----------------------------- diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3249,8 +3249,8 @@ Opts.RenderScript = IK.getLanguage() == Language::RenderScript; - // OpenCL and C++ both have bool, true, false keywords. - Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; + // OpenCL, C++ and C2x have bool, true, false keywords. + Opts.Bool = Opts.OpenCL || Opts.CPlusPlus || Opts.C2x; // OpenCL has half keyword Opts.Half = Opts.OpenCL; diff --git a/clang/lib/Headers/stdbool.h b/clang/lib/Headers/stdbool.h --- a/clang/lib/Headers/stdbool.h +++ b/clang/lib/Headers/stdbool.h @@ -10,8 +10,13 @@ #ifndef __STDBOOL_H #define __STDBOOL_H -/* Don't define bool, true, and false in C++, except as a GNU extension. */ -#ifndef __cplusplus +#define __bool_true_false_are_defined 1 + +#if __STDC_VERSION__ > 201710L +#if !defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS) +#warning "the header is deprecated in C2x" +#endif /* !defined(_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS) */ +#elif !defined(__cplusplus) #define bool _Bool #define true 1 #define false 0 @@ -20,12 +25,10 @@ #define _Bool bool #if __cplusplus < 201103L /* For C++98, define bool, false, true as a GNU extension. */ -#define bool bool +#define bool bool #define false false -#define true true +#define true true #endif #endif -#define __bool_true_false_are_defined 1 - #endif /* __STDBOOL_H */ diff --git a/clang/test/Headers/stdbool.c b/clang/test/Headers/stdbool.c new file mode 100644 --- /dev/null +++ b/clang/test/Headers/stdbool.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fgnuc-version=4.2.1 -std=c11 -E -dM %s 2>&1 | FileCheck --check-prefix=CHECK-C11 %s +// RUN: %clang_cc1 -fgnuc-version=4.2.1 -std=c2x -E -dM %s 2>&1 | FileCheck --check-prefix=CHECK-C2X %s +// RUN: %clang_cc1 -fgnuc-version=4.2.1 -std=c2x -E -dM -D_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS %s 2>&1 | FileCheck --check-prefix=CHECK-C2X-CRT %s + +#include + +// CHECK-C11: #define bool _Bool +// CHECK-C11: #define false 0 +// CHECK-C11: #define true 1 + +// CHECK-C2X: warning "the header is deprecated +// CHECK-C2X-NOT: #define bool +// CHECK-C2X-NOT: #define true +// CHECK-C2X-NOT: #define falsea + +// CHECK-C2X-CRT-NOT: warning "the header is deprecated +// CHECK-C2X-CRT-NOT: #define bool +// CHECK-C2X-CRT-NOT: #define true +// CHECK-C2X-CRT-NOT: #define false diff --git a/clang/test/Sema/c2x-bool.c b/clang/test/Sema/c2x-bool.c new file mode 100644 --- /dev/null +++ b/clang/test/Sema/c2x-bool.c @@ -0,0 +1,41 @@ +// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify %s + +_Static_assert(_Generic(true, _Bool : 1, default: 0)); +_Static_assert(_Generic(false, _Bool : 1, default: 0)); + +_Static_assert(_Generic(true, bool : 1, default: 0)); +_Static_assert(_Generic(false, bool : 1, default: 0)); + +_Static_assert(_Generic(true, bool : true, default: false)); +_Static_assert(_Generic(false, bool : true, default: false)); + +_Static_assert(true == (bool)+1); +_Static_assert(false == (bool)+0); + +_Static_assert(_Generic(+true, bool : 0, unsigned int : 0, signed int : 1, default : 0)); + +struct S { + bool b : 1; +} s; +_Static_assert(_Generic(+s.b, bool : 0, unsigned int : 0, signed int : 1, default : 0)); + +static void *f = false; // expected-warning {{to null from a constant boolean expression}} +static int one = true; +static int zero = false; + +static void do_work() { + char *str = "Foo"; + str[false] = 'f'; + str[true] = 'f'; + + char c1[true]; + char c2[false]; +} + +#if true != 1 +#error true should be 1 in the preprocessor +#endif + +#if false != 0 +#error false should be 0 in the preprocessor +#endif