[clang] [Clang] Added explanation why `is_trivially default_constructible` is false (PR #152888)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 9 21:45:45 PDT 2025
https://github.com/abhijeetsharma200 updated https://github.com/llvm/llvm-project/pull/152888
>From 48d71f870d21a45c0a197d1853788a4aec80018b Mon Sep 17 00:00:00 2001
From: Abhijeet Sharma <abhijeetsharma2002 at gmail.com>
Date: Sun, 10 Aug 2025 04:49:15 +0200
Subject: [PATCH 1/2] Added explain is trivially default constructible
---
.../clang/Basic/DiagnosticSemaKinds.td | 5 +-
clang/lib/Sema/SemaTypeTraits.cpp | 106 ++++++++++++++++
...overload-resolution-deferred-templates.cpp | 45 +++++++
.../type-traits-unsatisfied-diags-std.cpp | 62 ++++++++-
.../SemaCXX/type-traits-unsatisfied-diags.cpp | 119 ++++++++++++++++++
5 files changed, 335 insertions(+), 2 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 116341f4b66d5..37cfcb706030a 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1772,7 +1772,8 @@ def note_unsatisfied_trait
"%Replaceable{replaceable}|"
"%TriviallyCopyable{trivially copyable}|"
"%Empty{empty}|"
- "%StandardLayout{standard-layout}"
+ "%StandardLayout{standard-layout}|"
+ "%TriviallyDefaultConstructible{trivially default constructible}"
"}1">;
def note_unsatisfied_trait_reason
@@ -1807,6 +1808,8 @@ def note_unsatisfied_trait_reason
"constructor}|"
"%DeletedCtr{has a deleted %select{copy|move}1 "
"constructor}|"
+ "%NTDCBase{has a non-trivially-default-constructible base %1}|"
+ "%NTDCField{has a non-trivially-default-constructible member %1 of type %2}|"
"%UserProvidedAssign{has a user provided %select{copy|move}1 "
"assignment operator}|"
"%DeletedAssign{has a deleted %select{copy|move}1 "
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index 9b9dd172003a0..79f6b5ff3e380 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -1963,6 +1963,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
.Case("is_assignable", TypeTrait::BTT_IsAssignable)
.Case("is_empty", TypeTrait::UTT_IsEmpty)
.Case("is_standard_layout", TypeTrait::UTT_IsStandardLayout)
+ .Case("is_trivially_default_constructible", TypeTrait::UTT_HasTrivialDefaultConstructor)
.Case("is_constructible", TypeTrait::TT_IsConstructible)
.Default(std::nullopt);
}
@@ -2592,6 +2593,108 @@ static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,
SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;
}
+static void DiagnoseNonTriviallyDefaultConstructibleReason(Sema &SemaRef,
+ SourceLocation Loc,
+ const CXXRecordDecl *D) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait)
+ << D << diag::TraitName::TriviallyDefaultConstructible;
+
+ // Check if the class has a user-provided constructor
+ if (D->hasUserDeclaredConstructor()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::UserProvidedCtr << /*Copy*/ 0
+ << D->getLocation();
+ }
+
+ // Check if the class has a deleted constructor
+ if (D->hasDeletedDefaultConstructor()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::DeletedCtr << /*Copy*/ 0
+ << D->getLocation();
+ }
+
+ // Check for virtual functions and virtual base classes
+ if (D->isPolymorphic()) {
+ // Find a virtual function to point to
+ for (const CXXMethodDecl *Method : D->methods()) {
+ if (Method->isVirtual()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::VirtualFunction << Method
+ << Method->getSourceRange();
+ break;
+ }
+ }
+ }
+
+ // Check base classes
+ for (const CXXBaseSpecifier &Base : D->bases()) {
+ if (Base.isVirtual()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::VBase << Base.getType()
+ << Base.getSourceRange();
+ }
+ if (!Base.getType()->isTriviallyDefaultConstructibleType()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::NTDCBase << Base.getType()
+ << Base.getSourceRange();
+ }
+ }
+
+ // Check non-static data members
+ for (const FieldDecl *Field : D->fields()) {
+ if (!Field->getType()->isTriviallyDefaultConstructibleType()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::NTDCField << Field
+ << Field->getType() << Field->getSourceRange();
+ }
+ }
+
+ // Check if it's a union with non-trivial constructor members
+ if (D->isUnion()) {
+ bool HasNonTrivialMember = false;
+ for (const FieldDecl *Field : D->fields()) {
+ if (!Field->getType()->isTriviallyDefaultConstructibleType()) {
+ HasNonTrivialMember = true;
+ break;
+ }
+ }
+ if (HasNonTrivialMember) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << /*Constructor*/ 0
+ << D->getSourceRange();
+ }
+ }
+
+ SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;
+}
+
+static void DiagnoseNonTriviallyDefaultConstructibleReason(Sema &SemaRef,
+ SourceLocation Loc,
+ QualType T) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait)
+ << T << diag::TraitName::TriviallyDefaultConstructible;
+
+ // Check type-level exclusion first.
+ if (T->isVariablyModifiedType()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::VLA;
+ return;
+ }
+
+ if (T->isReferenceType()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::Ref;
+ return;
+ }
+ T = T.getNonReferenceType();
+ const CXXRecordDecl *D = T->getAsCXXRecordDecl();
+ if (!D || D->isInvalidDecl())
+ return;
+
+ if (D->hasDefinition())
+ DiagnoseNonTriviallyDefaultConstructibleReason(SemaRef, Loc, D);
+}
+
void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
E = E->IgnoreParenImpCasts();
if (E->containsErrors())
@@ -2621,6 +2724,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
case UTT_IsStandardLayout:
DiagnoseNonStandardLayoutReason(*this, E->getBeginLoc(), Args[0]);
break;
+ case UTT_HasTrivialDefaultConstructor:
+ DiagnoseNonTriviallyDefaultConstructibleReason(*this, E->getBeginLoc(), Args[0]);
+ break;
case TT_IsConstructible:
DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args);
break;
diff --git a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp
index 135865c8450f5..c70deca4e7abc 100644
--- a/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp
+++ b/clang/test/SemaCXX/overload-resolution-deferred-templates.cpp
@@ -105,6 +105,51 @@ static_assert(__is_constructible(Movable, int));
// expected-note@#err-self-constraint-1 4{{}}
// expected-note@#Movable {{'Movable' defined here}}
+// Test trivially default constructible type traits
+struct TriviallyDefaultConstructible {
+ // Trivial default constructor
+};
+
+struct NonTriviallyDefaultConstructible {
+ NonTriviallyDefaultConstructible() {} // User-provided constructor
+};
+
+struct VirtualBase {
+ virtual ~VirtualBase() {} // Virtual destructor
+};
+
+struct UnionWithNonTrivial {
+ UnionWithNonTrivial() {} // User-provided constructor
+};
+
+union UnionType {
+ int i;
+ UnionWithNonTrivial u; // Non-trivial member
+};
+
+static_assert(__is_trivially_default_constructible(TriviallyDefaultConstructible));
+static_assert(!__is_trivially_default_constructible(NonTriviallyDefaultConstructible));
+static_assert(!__is_trivially_default_constructible(VirtualBase));
+static_assert(!__is_trivially_default_constructible(UnionType));
+
+// Test in template constraints
+struct TriviallyDefaultConstructibleWrapper {
+ template <typename T>
+ requires __is_trivially_default_constructible(T)
+ explicit TriviallyDefaultConstructibleWrapper(T op) noexcept; // #1
+ TriviallyDefaultConstructibleWrapper() noexcept = default; // #2
+};
+
+static_assert(__is_trivially_default_constructible(TriviallyDefaultConstructibleWrapper));
+
+struct NonTriviallyDefaultConstructibleWrapper {
+ template <typename T>
+ requires __is_trivially_default_constructible(T)
+ explicit NonTriviallyDefaultConstructibleWrapper(T op) = delete; // #1
+};
+
+static_assert(!__is_trivially_default_constructible(NonTriviallyDefaultConstructibleWrapper));
+
template <typename T>
struct Members {
constexpr auto f(auto) {
diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
index f3ddbbfe15bdc..aeb54f631c1aa 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
@@ -43,6 +43,14 @@ static constexpr bool value = __is_standard_layout(T);
template <typename T>
constexpr bool is_standard_layout_v = __is_standard_layout(T);
+template <typename T>
+struct is_trivially_default_constructible {
+ static constexpr bool value = __is_trivially_default_constructible(T);
+};
+
+template <typename T>
+constexpr bool is_trivially_default_constructible_v = __is_trivially_default_constructible(T);
+
template <typename... Args>
struct is_constructible {
static constexpr bool value = __is_constructible(Args...);
@@ -106,6 +114,17 @@ using is_standard_layout = __details_is_standard_layout<T>;
template <typename T>
constexpr bool is_standard_layout_v = __is_standard_layout(T);
+template <typename T>
+struct __details_is_trivially_default_constructible {
+ static constexpr bool value = __is_trivially_default_constructible(T);
+};
+
+template <typename T>
+using is_trivially_default_constructible = __details_is_trivially_default_constructible<T>;
+
+template <typename T>
+constexpr bool is_trivially_default_constructible_v = __is_trivially_default_constructible(T);
+
template <typename... Args>
struct __details_is_constructible{
static constexpr bool value = __is_constructible(Args...);
@@ -146,6 +165,15 @@ using is_trivially_copyable = __details_is_trivially_copyable<T>;
template <typename T>
constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
+template <typename T>
+struct __details_is_trivially_default_constructible : bool_constant<__is_trivially_default_constructible(T)> {};
+
+template <typename T>
+using is_trivially_default_constructible = __details_is_trivially_default_constructible<T>;
+
+template <typename T>
+constexpr bool is_trivially_default_constructible_v = is_trivially_default_constructible<T>::value;
+
template <typename T, typename U>
struct __details_is_assignable : bool_constant<__is_assignable(T, U)> {};
@@ -300,6 +328,15 @@ namespace test_namespace {
static_assert(is_constructible_v<void>);
// expected-error at -1 {{static assertion failed due to requirement 'is_constructible_v<void>'}} \
// expected-note at -1 {{because it is a cv void type}}
+
+ static_assert(is_trivially_default_constructible<int&>::value);
+ // expected-error-re at -1 {{static assertion failed due to requirement '{{.*}}is_trivially_default_constructible<int &>::value'}} \
+ // expected-note at -1 {{'int &' is not trivially default constructible}} \
+ // expected-note at -1 {{because it is a reference type}}
+ static_assert(is_trivially_default_constructible_v<int&>);
+ // expected-error at -1 {{static assertion failed due to requirement 'is_trivially_default_constructible_v<int &>'}} \
+ // expected-note at -1 {{'int &' is not trivially default constructible}} \
+ // expected-note at -1 {{because it is a reference type}}
}
@@ -320,6 +357,14 @@ concept C2 = std::is_trivially_copyable_v<T>; // #concept4
template <C2 T> void g2(); // #cand4
+template <typename T>
+requires std::is_trivially_default_constructible<T>::value void f5(); // #cand5
+
+template <typename T>
+concept C5 = std::is_trivially_default_constructible_v<T>; // #concept6
+
+template <C5 T> void g5(); // #cand6
+
template <typename T, typename U>
requires std::is_assignable<T, U>::value void f4(); // #cand7
@@ -390,9 +435,24 @@ void test() {
g3<void>();
// expected-error at -1 {{no matching function for call to 'g3'}} \
// expected-note@#cand6 {{candidate template ignored: constraints not satisfied [with T = void]}} \
- // expected-note@#cand6 {{because 'void' does not satisfy 'C3'}} \
+ // expected-note@#concept6 {{because 'void' does not satisfy 'C3'}} \
// expected-note@#concept6 {{because 'std::is_constructible_v<void>' evaluated to false}} \
// expected-note@#concept6 {{because it is a cv void type}}
+
+ f5<void>();
+ // expected-error at -1 {{no matching function for call to 'f5'}} \
+ // expected-note@#cand5 {{candidate template ignored: constraints not satisfied [with T = void]}} \
+ // expected-note-re@#cand5 {{because '{{.*}}is_trivially_default_constructible<void>::value' evaluated to false}} \
+ // expected-note@#cand5 {{'void' is not trivially default constructible}} \
+ // expected-note@#cand5 {{because it is a cv void type}}
+
+ g5<void>();
+ // expected-error at -1 {{no matching function for call to 'g5'}} \
+ // expected-note@#cand6 {{candidate template ignored: constraints not satisfied [with T = void]}} \
+ // expected-note@#cand6 {{because 'void' does not satisfy 'C5'}} \
+ // expected-note@#concept6 {{because 'std::is_trivially_default_constructible_v<void>' evaluated to false}} \
+ // expected-note@#cand6 {{'void' is not trivially default constructible}} \
+ // expected-note@#cand6 {{because it is a cv void type}}
}
}
diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
index 54806a93ddf80..0822948abffc5 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
@@ -489,6 +489,125 @@ static_assert(__is_trivially_copyable(S12));
// expected-note@#tc-S12 {{'S12' defined here}}
}
+namespace trivially_default_constructible {
+
+struct TrivialBase {
+ // Trivial default constructor
+};
+
+struct NonTrivialBase {
+ NonTrivialBase() {} // User-provided constructor
+};
+
+struct VirtualBase {
+ virtual ~VirtualBase() {} // Virtual destructor
+};
+
+struct UnionWithNonTrivial {
+ UnionWithNonTrivial() {} // User-provided constructor
+};
+
+union UnionType {
+ int i;
+ UnionWithNonTrivial u; // Non-trivial member
+};
+
+struct S1 { // #tdc-S1
+ S1() {} // User-provided constructor
+};
+static_assert(__is_trivially_default_constructible(S1));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S1)'}} \
+// expected-note at -1 {{'S1' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a user-provided constructor}} \
+// expected-note@#tdc-S1 {{'S1' defined here}}
+
+struct S2 { // #tdc-S2
+ S2() = delete; // Deleted constructor
+};
+static_assert(__is_trivially_default_constructible(S2));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S2)'}} \
+// expected-note at -1 {{'S2' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a deleted constructor}} \
+// expected-note@#tdc-S2 {{'S2' defined here}}
+
+struct S3 : NonTrivialBase { // #tdc-S3
+ // Inherits non-trivial base
+};
+static_assert(__is_trivially_default_constructible(S3));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S3)'}} \
+// expected-note at -1 {{'S3' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a non-trivially-default-constructible base 'NonTrivialBase'}} \
+// expected-note@#tdc-S3 {{'S3' defined here}}
+
+struct S4 { // #tdc-S4
+ NonTrivialBase member; // Non-trivial member
+};
+static_assert(__is_trivially_default_constructible(S4));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S4)'}} \
+// expected-note at -1 {{'S4' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a non-trivially-default-constructible member 'member' of type 'NonTrivialBase'}} \
+// expected-note@#tdc-S4 {{'S4' defined here}}
+
+struct S5 : VirtualBase { // #tdc-S5
+ // Has virtual base class
+};
+static_assert(__is_trivially_default_constructible(S5));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S5)'}} \
+// expected-note at -1 {{'S5' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a virtual base 'VirtualBase'}} \
+// expected-note@#tdc-S5 {{'S5' defined here}}
+
+struct S6 { // #tdc-S6
+ UnionType member; // Union with non-trivial member
+};
+static_assert(__is_trivially_default_constructible(S6));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S6)'}} \
+// expected-note at -1 {{'S6' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a non-trivially-default-constructible member 'member' of type 'UnionType'}} \
+// expected-note@#tdc-S6 {{'S6' defined here}}
+
+struct S7 { // #tdc-S7
+ virtual void f() {} // Virtual function
+};
+static_assert(__is_trivially_default_constructible(S7));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(trivially_default_constructible::S7)'}} \
+// expected-note at -1 {{'S7' is not trivially default constructible}} \
+// expected-note at -1 {{because it has a virtual function 'f'}} \
+// expected-note@#tdc-S7 {{'S7' defined here}}
+
+// Test reference types
+static_assert(__is_trivially_default_constructible(int&));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(int &)'}} \
+// expected-note at -1 {{'int &' is not trivially default constructible}} \
+// expected-note at -1 {{because it is a reference type}}
+
+// Test variably modified types
+extern int vla_size;
+static_assert(__is_trivially_default_constructible(int[vla_size]));
+// expected-error at -1 {{static assertion failed due to requirement '__is_trivially_default_constructible(int[vla_size])'}} \
+// expected-note at -1 {{'int[vla_size]' is not trivially default constructible}} \
+// expected-note at -1 {{because it is a variably-modified type}}
+
+// Test incomplete types
+struct S8; // expected-note {{forward declaration of 'trivially_default_constructible::S8'}}
+static_assert(__is_trivially_default_constructible(S8));
+// expected-error at -1 {{incomplete type 'S8' used in type trait expression}}
+
+// Test valid cases
+static_assert(__is_trivially_default_constructible(int));
+static_assert(__is_trivially_default_constructible(TrivialBase));
+static_assert(__is_trivially_default_constructible(int[5]));
+static_assert(__is_trivially_default_constructible(int*));
+
+struct ValidClass {
+ int x;
+ // No user-provided constructor, no virtual functions, no virtual bases
+ // All members are trivially default constructible
+};
+static_assert(__is_trivially_default_constructible(ValidClass));
+
+}
+
namespace constructible {
struct S1 { // #c-S1
>From b6dbd1dca8ff809375b54a05be7efec794b75386 Mon Sep 17 00:00:00 2001
From: Abhijeet Sharma <abhijeetsharma2002 at gmail.com>
Date: Sun, 10 Aug 2025 06:45:32 +0200
Subject: [PATCH 2/2] Fixed constructor method
---
clang/lib/Sema/SemaTypeTraits.cpp | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index 79f6b5ff3e380..ac1a000d66c2d 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -2519,7 +2519,7 @@ static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,
<< diag::TraitNotSatisfiedReason::MultipleDataBase;
}
if (D->isPolymorphic()) {
- // Find the best location to point “defined here” at.
+ // Find the best location to point "defined here" at.
const CXXMethodDecl *VirtualMD = nullptr;
// First, look for a virtual method.
for (const auto *M : D->methods()) {
@@ -2607,7 +2607,7 @@ static void DiagnoseNonTriviallyDefaultConstructibleReason(Sema &SemaRef,
}
// Check if the class has a deleted constructor
- if (D->hasDeletedDefaultConstructor()) {
+ if (D->hasDefaultConstructor() && !D->hasTrivialDefaultConstructor()) {
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
<< diag::TraitNotSatisfiedReason::DeletedCtr << /*Copy*/ 0
<< D->getLocation();
@@ -2633,7 +2633,8 @@ static void DiagnoseNonTriviallyDefaultConstructibleReason(Sema &SemaRef,
<< diag::TraitNotSatisfiedReason::VBase << Base.getType()
<< Base.getSourceRange();
}
- if (!Base.getType()->isTriviallyDefaultConstructibleType()) {
+ const CXXRecordDecl *BaseDecl = Base.getType()->getAsCXXRecordDecl();
+ if (BaseDecl && !BaseDecl->hasTrivialDefaultConstructor()) {
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
<< diag::TraitNotSatisfiedReason::NTDCBase << Base.getType()
<< Base.getSourceRange();
@@ -2642,7 +2643,8 @@ static void DiagnoseNonTriviallyDefaultConstructibleReason(Sema &SemaRef,
// Check non-static data members
for (const FieldDecl *Field : D->fields()) {
- if (!Field->getType()->isTriviallyDefaultConstructibleType()) {
+ const CXXRecordDecl *FieldDecl = Field->getType()->getAsCXXRecordDecl();
+ if (FieldDecl && !FieldDecl->hasTrivialDefaultConstructor()) {
SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
<< diag::TraitNotSatisfiedReason::NTDCField << Field
<< Field->getType() << Field->getSourceRange();
@@ -2653,7 +2655,8 @@ static void DiagnoseNonTriviallyDefaultConstructibleReason(Sema &SemaRef,
if (D->isUnion()) {
bool HasNonTrivialMember = false;
for (const FieldDecl *Field : D->fields()) {
- if (!Field->getType()->isTriviallyDefaultConstructibleType()) {
+ const CXXRecordDecl *FieldDecl = Field->getType()->getAsCXXRecordDecl();
+ if (FieldDecl && !FieldDecl->hasTrivialDefaultConstructor()) {
HasNonTrivialMember = true;
break;
}
More information about the cfe-commits
mailing list