[clang] [clang] Explain why std::is_integral is not satisfied (PR #235416)
Aaron Advait Anish via cfe-commits
cfe-commits at lists.llvm.org
Sun Oct 25 01:32:05 PDT 2026
https://github.com/skylarcs-the-limit created https://github.com/llvm/llvm-project/pull/235416
Part of #141911.
This adds missing diagnostic notes explaining why std::is_integral fails.
>From 23208672099931b3ce8840dade1417ec5d3ff21b Mon Sep 17 00:00:00 2001
From: Aaron Advait Anish <cs24btech11002 at iith.ac.in>
Date: Sun, 25 Oct 2026 13:59:08 +0530
Subject: [PATCH] [clang] Explain why std::is_integral is not satisfied
Part of #141911.
Co-authored-by: Aare Renu Shri <cs24btech11001 at iith.ac.in>, Rupesh Devarapalli <cs24btech11023 at iith.ac.in>
---
clang/include/clang/Basic/BuiltinTraits.td | 1 +
.../clang/Basic/DiagnosticSemaKinds.td | 6 ++
clang/lib/Sema/SemaTypeTraits.cpp | 38 +++++++++++++
.../type-traits-unsatisfied-diags-std.cpp | 47 ++++++++++++++++
.../SemaCXX/type-traits-unsatisfied-diags.cpp | 56 +++++++++++++++++++
5 files changed, 148 insertions(+)
diff --git a/clang/include/clang/Basic/BuiltinTraits.td b/clang/include/clang/Basic/BuiltinTraits.td
index f80234dd21e145..a00ad3a24e5402 100644
--- a/clang/include/clang/Basic/BuiltinTraits.td
+++ b/clang/include/clang/Basic/BuiltinTraits.td
@@ -494,6 +494,7 @@ def IsFloatingPoint : UnaryTrait {
def IsIntegral : UnaryTrait {
let Spelling = "__is_integral";
+ let StdName = "is_integral";
}
def IsCompleteType : UnaryTrait {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index dcb5732c3c19e7..0890bd0ad13461 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1855,6 +1855,7 @@ def note_unsatisfied_trait
"%TriviallyRelocatable{trivially relocatable}|"
"%TriviallyCopyable{trivially copyable}|"
"%Empty{empty}|"
+ "%Integral{an integral type}|"
"%StandardLayout{standard-layout}|"
"%Aggregate{aggregate}|"
"%Final{final}|"
@@ -1908,6 +1909,11 @@ def note_unsatisfied_trait_reason
"%NotClassOrUnion{is not a class or union type}|"
"%NotMarkedFinal{is not marked 'final'}|"
"%PointerType{is a pointer type}|"
+ "%FloatingPointType{is a floating-point type}|"
+ "%EnumType{is an enum type}|"
+ "%VoidType{is void}|"
+ "%ClassType{is a class type}|"
+ "%MemberPointerType{is a member pointer type}|"
"%ArrayType{is an array type}|"
"%UnionType{is a union type}|"
"%NotStructOrClass{is not a struct or class type}|"
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index cb30ff9fd02da9..0a0e37ac0e0a50 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -2406,6 +2406,41 @@ static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, QualType T) {
}
}
+static void DiagnoseNonIntegralReason(Sema &S, SourceLocation Loc, QualType T) {
+ S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Integral;
+ if (T->isFloatingType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::FloatingPointType;
+ } else if (T->isEnumeralType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::EnumType;
+ } else if (T->isPointerType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::PointerType;
+ } else if (T->isReferenceType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::Ref;
+ } else if (T->isArrayType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::ArrayType;
+ } else if (T->isUnionType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::UnionType;
+ } else if (T->isFunctionType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::FunctionType;
+ } else if (T->isVoidType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::VoidType;
+ } else if (T->isStructureOrClassType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::ClassType;
+ } else if (T->isMemberPointerType()) {
+ S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::MemberPointerType;
+ }
+}
+
static void DiagnoseIsFinalReason(Sema &S, SourceLocation Loc,
const CXXRecordDecl *D) {
if (!D || D->isInvalidDecl())
@@ -2773,6 +2808,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
case UTT_IsEmpty:
DiagnoseIsEmptyReason(*this, E->getBeginLoc(), Args[0]);
break;
+ case UTT_IsIntegral:
+ DiagnoseNonIntegralReason(*this, E->getBeginLoc(), Args[0]);
+ break;
case UTT_IsStandardLayout:
DiagnoseNonStandardLayoutReason(*this, E->getBeginLoc(), Args[0]);
break;
diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
index 8a9f3bc400d206..2b301d02f496dd 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
@@ -73,6 +73,13 @@ struct is_abstract {
template <typename T>
constexpr bool is_abstract_v = __is_abstract(T);
+template <typename T>
+struct is_integral {
+ static constexpr bool value = __is_integral(T);
+};
+template <typename T>
+constexpr bool is_integral_v = __is_integral(T);
+
#endif
#ifdef STD2
@@ -167,6 +174,15 @@ using is_abstract = __details_is_abstract<T>;
template <typename T>
constexpr bool is_abstract_v = __is_abstract(T);
+template <typename T>
+struct __details_is_integral {
+ static constexpr bool value = __is_integral(T);
+};
+template <typename T>
+using is_integral = __details_is_integral<T>;
+template <typename T>
+constexpr bool is_integral_v = __is_integral(T);
+
#endif
@@ -252,6 +268,13 @@ using is_abstract = __details_is_abstract<T>;
template <typename T>
constexpr bool is_abstract_v = is_abstract<T>::value;
+template <typename T>
+struct __details_is_integral : bool_constant<__is_integral(T)> {};
+template <typename T>
+using is_integral = __details_is_integral<T>;
+template <typename T>
+constexpr bool is_integral_v = is_integral<T>::value;
+
#endif
}
@@ -590,4 +613,28 @@ void test() {
// expected-note@#concept10 {{'void' is not aggregate}} \
// expected-note@#concept10 {{because it is a cv void type}}
}
+ static_assert(std::is_integral<double>::value);
+ // expected-error-re at -1 {{static assertion failed due to requirement 'std::{{.*}}is_integral<double>::value'}} \
+ // expected-note at -1 {{'double' is not an integral type}} \
+ // expected-note at -1 {{because it is a floating-point type}}
+ static_assert(std::is_integral_v<double>);
+ // expected-error at -1 {{static assertion failed due to requirement 'std::is_integral_v<double>'}} \
+ // expected-note at -1 {{'double' is not an integral type}} \
+ // expected-note at -1 {{because it is a floating-point type}}
+
+ static_assert(std::is_integral_v<int*>);
+ // expected-error at -1 {{static assertion failed due to requirement 'std::is_integral_v<int *>'}} \
+ // expected-note at -1 {{'int *' is not an integral type}} \
+ // expected-note at -1 {{because it is a pointer type}}
+
+ static_assert(std::is_integral_v<int&>);
+ // expected-error at -1 {{static assertion failed due to requirement 'std::is_integral_v<int &>'}} \
+ // expected-note at -1 {{'int &' is not an integral type}} \
+ // expected-note at -1 {{because it is a reference type}}
+
+ enum E {};
+ static_assert(std::is_integral_v<E>);
+ // expected-error at -1 {{static assertion failed due to requirement 'std::is_integral_v<concepts::E>'}} \
+ // expected-note at -1 {{'concepts::E' is not an integral type}} \
+ // expected-note at -1 {{because it is an enum type}}
}
diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
index 3bde5b06a3aba4..a4f42f5530a5b2 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
@@ -892,3 +892,59 @@ static_assert(__is_abstract(U));
// expected-note at -1 {{because it is not a struct or class type}}
}
+
+namespace is_integral_tests {
+ static_assert(__is_integral(double));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(double)'}} \
+ // expected-note at -1 {{'double' is not an integral type}} \
+ // expected-note at -1 {{because it is a floating-point type}}
+
+ static_assert(__is_integral(int*));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(int *)'}} \
+ // expected-note at -1 {{'int *' is not an integral type}} \
+ // expected-note at -1 {{because it is a pointer type}}
+
+ static_assert(__is_integral(int&));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(int &)'}} \
+ // expected-note at -1 {{'int &' is not an integral type}} \
+ // expected-note at -1 {{because it is a reference type}}
+
+ enum E {};
+ static_assert(__is_integral(E));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(is_integral_tests::E)'}} \
+ // expected-note at -1 {{'E' is not an integral type}} \
+ // expected-note at -1 {{because it is an enum type}}
+
+ static_assert(__is_integral(int[3]));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(int[3])'}} \
+ // expected-note at -1 {{'int[3]' is not an integral type}} \
+ // expected-note at -1 {{because it is an array type}}
+
+ union U {};
+ static_assert(__is_integral(U));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(is_integral_tests::U)'}} \
+ // expected-note at -1 {{'U' is not an integral type}} \
+ // expected-note at -1 {{because it is a union type}}
+
+ struct S {};
+ static_assert(__is_integral(S));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(is_integral_tests::S)'}} \
+ // expected-note at -1 {{'S' is not an integral type}} \
+ // expected-note at -1 {{because it is a class type}}
+
+ static_assert(__is_integral(int S::*));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(int is_integral_tests::S::*)'}} \
+ // expected-note at -1 {{'int S::*' is not an integral type}} \
+ // expected-note at -1 {{because it is a member pointer type}}
+
+ using F = int(char);
+ static_assert(__is_integral(F));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(int (char))'}} \
+ // expected-note at -1 {{'F' (aka 'int (char)') is not an integral type}} \
+ // expected-note at -1 {{because it is a function type}}
+
+ static_assert(__is_integral(void));
+ // expected-error at -1 {{static assertion failed due to requirement '__is_integral(void)'}} \
+ // expected-note at -1 {{'void' is not an integral type}} \
+ // expected-note at -1 {{because it is void}}
+}
More information about the cfe-commits
mailing list