Skip to content

Commit

Permalink
[Sema] Add deprecation warnings for some compiler provided __has_* ty…
Browse files Browse the repository at this point in the history
…pe traits

Some compiler provided type traits like __has_trivial_constructor have been documented
as deprecated for quite some time.
Still, some people apparently still use them, even though mixing them with concepts
and with deleted functions leads to weird results. There's also disagreement about some
edge cases between GCC (which Clang claims to follow) and MSVC.

This patch adds deprecation warnings for the usage of those builtins, except for __has_trivial_destructor
which doesn't have a GCC alternative.

I made the warning on by default, so I had to silence it for some tests but it's not too many.

Some (decade old) history of issues with those builtins:
#18187
#18559
#22161
#33063

The abseil usage of them that triggered me to add this warning:
abseil/abseil-cpp#1201

Weird interaction of those builtins with C++20's conditionally trivial special member functions:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106085

Reviewed By: #clang-language-wg, aaron.ballman

Differential Revision: https://reviews.llvm.org/D129170
  • Loading branch information
royjacobson committed Jul 12, 2022
1 parent 2240d72 commit 0b89d1d
Show file tree
Hide file tree
Showing 20 changed files with 95 additions and 32 deletions.
4 changes: 4 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ Non-comprehensive list of changes in this release
- ASAN_OPTIONS=detect_stack_use_after_return=1 (only on Linux).
- MSAN_OPTIONS=poison_in_dtor=1.

- Some type-trait builtins, such as ``__has_trivial_assign``, have been documented
as deprecated for a while because their semantics don't mix well with post-C++11 type-traits.
Clang now emits deprecation warnings for them under the flag ``-Wdeprecated-builtins``.

New Compiler Flags
------------------
- Added the ``-fno-knr-functions`` flag to allow users to opt into the C2x
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def UnguardedAvailability : DiagGroup<"unguarded-availability",
def : DiagGroup<"partial-availability", [UnguardedAvailability]>;
def DeprecatedDynamicExceptionSpec
: DiagGroup<"deprecated-dynamic-exception-spec">;
def DeprecatedBuiltins : DiagGroup<"deprecated-builtins">;
def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
def DeprecatedRegister : DiagGroup<"deprecated-register">;
Expand All @@ -210,6 +211,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAnonEnumEnumConversion,
DeprecatedEnumCompareConditional,
DeprecatedEnumEnumConversion,
DeprecatedEnumFloatConversion,
DeprecatedBuiltins,
DeprecatedIncrementBool,
DeprecatedPragma,
DeprecatedRegister,
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5562,6 +5562,9 @@ def warn_deprecated_def : Warning<
def warn_unavailable_def : Warning<
"implementing unavailable method">,
InGroup<DeprecatedImplementations>, DefaultIgnore;
def warn_deprecated_builtin : Warning<
"builtin %0 is deprecated; use %1 instead">,
InGroup<DeprecatedBuiltins>;
def err_unavailable : Error<"%0 is unavailable">;
def err_property_method_unavailable :
Error<"property access is using %0 method which is unavailable">;
Expand Down
35 changes: 35 additions & 0 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5394,6 +5394,39 @@ static bool evaluateTypeTrait(Sema &S, TypeTrait Kind, SourceLocation KWLoc,
return false;
}

namespace {
void DiagnoseBuiltinDeprecation(Sema& S, TypeTrait Kind,
SourceLocation KWLoc) {
TypeTrait Replacement;
switch (Kind) {
case UTT_HasNothrowAssign:
case UTT_HasNothrowMoveAssign:
Replacement = BTT_IsNothrowAssignable;
break;
case UTT_HasNothrowCopy:
case UTT_HasNothrowConstructor:
Replacement = TT_IsNothrowConstructible;
break;
case UTT_HasTrivialAssign:
case UTT_HasTrivialMoveAssign:
Replacement = BTT_IsTriviallyAssignable;
break;
case UTT_HasTrivialCopy:
case UTT_HasTrivialDefaultConstructor:
case UTT_HasTrivialMoveConstructor:
Replacement = TT_IsTriviallyConstructible;
break;
case UTT_HasTrivialDestructor:
Replacement = UTT_IsTriviallyDestructible;
break;
default:
return;
}
S.Diag(KWLoc, diag::warn_deprecated_builtin)
<< getTraitSpelling(Kind) << getTraitSpelling(Replacement);
}
}

ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<TypeSourceInfo *> Args,
SourceLocation RParenLoc) {
Expand All @@ -5403,6 +5436,8 @@ ExprResult Sema::BuildTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
*this, Kind, KWLoc, Args[0]->getType()))
return ExprError();

DiagnoseBuiltinDeprecation(*this, Kind, KWLoc);

bool Dependent = false;
for (unsigned I = 0, N = Args.size(); I != N; ++I) {
if (Args[I]->getType()->isDependentType()) {
Expand Down
6 changes: 3 additions & 3 deletions clang/test/CXX/dcl.decl/dcl.init/p5.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-deprecated-builtins -std=c++98 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-deprecated-builtins -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-deprecated-builtins %s

// A program that calls for default-initialization or value-initialization of
// an entity of reference type is illformed. If T is a cv-qualified type, the
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CXX/drs/dr18xx.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors

#if __cplusplus < 201103L
// expected-error@+1 {{variadic macro}}
Expand Down
8 changes: 4 additions & 4 deletions clang/test/CXX/drs/dr21xx.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -Wno-deprecated-builtins -fcxx-exceptions -pedantic-errors

#if __cplusplus < 201103L
// expected-error@+1 {{variadic macro}}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CXX/special/class.copy/p12-0x.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-defaulted-function-deleted
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-defaulted-function-deleted -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -Wno-defaulted-function-deleted
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -Wno-defaulted-function-deleted -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14

// expected-no-diagnostics

Expand Down
4 changes: 2 additions & 2 deletions clang/test/CXX/special/class.copy/p25-0x.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
// RUN: %clang_cc1 -std=c++11 -verify %s -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14

// expected-no-diagnostics

Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/special/class.ctor/p5-0x.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-defaulted-function-deleted
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-deprecated-builtins -Wno-defaulted-function-deleted

struct DefaultedDefCtor1 {};
struct DefaultedDefCtor2 { DefaultedDefCtor2() = default; };
Expand Down
4 changes: 2 additions & 2 deletions clang/test/Modules/cxx-decls.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: rm -rf %t
// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -verify -std=c++11
// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -ast-dump -ast-dump-filter merge -std=c++11 | FileCheck %s
// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Wno-deprecated-builtins -I %S/Inputs %s -verify -std=c++11
// RUN: %clang_cc1 -x objective-c++ -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -Wno-deprecated-builtins -I %S/Inputs %s -ast-dump -ast-dump-filter merge -std=c++11 | FileCheck %s

// expected-no-diagnostics

Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/cxx0x-defaulted-functions.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions %s
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -fcxx-exceptions -Wno-deprecated-builtins %s

void fn() = default; // expected-error {{only special member}}
struct foo {
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/cxx11-crashes.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -std=c++11 -verify %s
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-deprecated-builtins

// rdar://12240916 stack overflow.
namespace rdar12240916 {
Expand Down
19 changes: 19 additions & 0 deletions clang/test/SemaCXX/deprecated-builtins.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s

struct A {};

void f() {
bool a;

a = __has_nothrow_assign(A); // expected-warning-re {{__has_nothrow_assign {{.*}} use __is_nothrow_assignable}}
a = __has_nothrow_move_assign(A); // expected-warning-re {{__has_nothrow_move_assign {{.*}} use __is_nothrow_assignable}}
a = __has_nothrow_copy(A); // expected-warning-re {{__has_nothrow_copy {{.*}} use __is_nothrow_constructible}}
a = __has_nothrow_constructor(A); // expected-warning-re {{__has_nothrow_constructor {{.*}} use __is_nothrow_constructible}}
a = __has_trivial_assign(A); // expected-warning-re {{__has_trivial_assign {{.*}} use __is_trivially_assignable}}
a = __has_trivial_move_assign(A); // expected-warning-re {{__has_trivial_move_assign {{.*}} use __is_trivially_assignable}}
a = __has_trivial_copy(A); // expected-warning-re {{__has_trivial_copy {{.*}} use __is_trivially_constructible}}
a = __has_trivial_constructor(A); // expected-warning-re {{__has_trivial_constructor {{.*}} use __is_trivially_constructible}}
a = __has_trivial_move_constructor(A); // expected-warning-re {{__has_trivial_move_constructor {{.*}} use __is_trivially_constructible}}
a = __has_trivial_destructor(A); // expected-warning-re {{__has_trivial_destructor {{.*}} use __is_trivially_destructible}}

}
8 changes: 4 additions & 4 deletions clang/test/SemaCXX/sizeless-1.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=c++98 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=c++11 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=c++17 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=gnu++17 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-deprecated-builtins -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=c++98 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-deprecated-builtins -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=c++11 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-deprecated-builtins -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=c++17 %s
// RUN: %clang_cc1 -fcxx-exceptions -fsyntax-only -verify -W -Wall -Wno-deprecated-builtins -Wno-unused-but-set-variable -Wrange-loop-analysis -triple arm64-linux-gnu -target-feature +sve -std=gnu++17 %s

namespace std {
struct type_info;
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/trivial-constructor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-deprecated-builtins
// expected-no-diagnostics
struct T1 {
};
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/trivial-destructor.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wno-deprecated-builtins
// expected-no-diagnostics
struct T1 {
};
Expand Down
6 changes: 3 additions & 3 deletions clang/test/SemaCXX/type-traits.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -fms-extensions -Wno-microsoft %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -fms-extensions -Wno-microsoft %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++1z -fms-extensions -Wno-microsoft %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++11 -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++14 -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -verify -std=gnu++1z -Wno-deprecated-builtins -fms-extensions -Wno-microsoft %s

#define T(b) (b) ? 1 : -1
#define F(b) (b) ? -1 : 1
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaObjCXX/arc-type-traits.mm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -verify -std=c++11 %s -Wno-deprecated-builtins
// expected-no-diagnostics

// Check the results of the various type-trait query functions on
Expand Down
2 changes: 1 addition & 1 deletion clang/test/SemaObjCXX/objc-weak-type-traits.mm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -fobjc-weak -fobjc-runtime-has-weak -verify -std=c++11 %s
// RUN: %clang_cc1 -fsyntax-only -fobjc-weak -fobjc-runtime-has-weak -verify -std=c++11 %s -Wno-deprecated-builtins
// expected-no-diagnostics

// Check the results of the various type-trait query functions on
Expand Down

0 comments on commit 0b89d1d

Please sign in to comment.