[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-02-06 Thread Mariya Podchishchaeva via cfe-commits

Fznamznon wrote:

@cor3ntin , perhaps a dumb question, but 
https://github.com/llvm/llvm-project/pull/77753 should only help in post C++20 
modes since only there destructor can be `constexpr`. How about older versions? 
Clang will still emit an error that the type from 
https://github.com/llvm/llvm-project/pull/78195#issuecomment-1895950521 is not 
literal in C++17 for example.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits

https://github.com/cor3ntin created 
https://github.com/llvm/llvm-project/pull/78195

A union is considered a literal type unless it has no non-literal member.

This resolves CWG2096 (which makes unions with literal members literal) and 
CWG2598 (empty unions are literal types).

Fixes #77924

>From f354ca458c1fa3cebb375f756f1a87fcf0586c3c Mon Sep 17 00:00:00 2001
From: Corentin Jabot 
Date: Mon, 15 Jan 2024 18:09:48 +0100
Subject: [PATCH] [Clang] Implement CWG2598: Union of non-literal types

A union is considered a literal type unless it has no
non-literal member.

This resolves CWG2096 (which makes unions with literal members literal)
and CWG2598 (empty unions are literal types).

Fixes #77924
---
 clang/docs/ReleaseNotes.rst |  5 +++
 clang/include/clang/AST/DeclCXX.h   | 37 ---
 clang/lib/AST/DeclCXX.cpp   | 28 +
 clang/test/CXX/drs/dr20xx.cpp   |  2 ++
 clang/test/CXX/drs/dr25xx.cpp   | 47 +
 clang/test/SemaCXX/literal-type.cpp | 33 
 clang/www/cxx_dr_status.html|  4 +--
 7 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f..d967d904ba3fce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,11 @@ C++2c Feature Support
 Resolutions to C++ Defect Reports
 ^
 
+- Implemented `CWG2598 `_ and `CWG2096 
`_,
+  making unions (that have either no members or at least one literal member) 
literal types.
+  (`#77924: `_).
+
+
 C Language Changes
 --
 - ``structs``, ``unions``, and ``arrays`` that are const may now be used as
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 648f5f94640870..75b73700c44d67 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1439,31 +1439,20 @@ class CXXRecordDecl : public RecordDecl {
 
   /// Determine whether this class is a literal type.
   ///
-  /// C++11 [basic.types]p10:
+  /// C++20 [basic.types]p10:
   ///   A class type that has all the following properties:
-  /// - it has a trivial destructor
-  /// - every constructor call and full-expression in the
-  ///   brace-or-equal-intializers for non-static data members (if any) is
-  ///   a constant expression.
-  /// - it is an aggregate type or has at least one constexpr constructor
-  ///   or constructor template that is not a copy or move constructor, and
-  /// - all of its non-static data members and base classes are of literal
-  ///   types
-  ///
-  /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
-  /// treating types with trivial default constructors as literal types.
-  ///
-  /// Only in C++17 and beyond, are lambdas literal types.
-  bool isLiteral() const {
-const LangOptions &LangOpts = getLangOpts();
-return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
-  : hasTrivialDestructor()) &&
-   (!isLambda() || LangOpts.CPlusPlus17) &&
-   !hasNonLiteralTypeFieldsOrBases() &&
-   (isAggregate() || isLambda() ||
-hasConstexprNonCopyMoveConstructor() ||
-hasTrivialDefaultConstructor());
-  }
+  /// - it has a constexpr destructor
+  /// - all of its non-static non-variant data members and base classes
+  ///   are of non-volatile literal types, and it:
+  ///- is a closure type
+  ///- is an aggregate union type that has either no variant members
+  ///  or at least one variant member of non-volatile literal type
+  ///- is a non-union aggregate type for which each of its anonymous
+  ///  union members satisfies the above requirements for an aggregate
+  ///  union type, or
+  ///- has at least one constexpr constructor or constructor template
+  ///  that is not a copy or move constructor.
+  bool isLiteral() const;
 
   /// Determine whether this is a structural type.
   bool isStructural() const {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 98b0a6dc28ea2f..0d49d54fd64197 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile liter

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: cor3ntin (cor3ntin)


Changes

A union is considered a literal type unless it has no non-literal member.

This resolves CWG2096 (which makes unions with literal members literal) and 
CWG2598 (empty unions are literal types).

Fixes #77924

---
Full diff: https://github.com/llvm/llvm-project/pull/78195.diff


7 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+5) 
- (modified) clang/include/clang/AST/DeclCXX.h (+13-24) 
- (modified) clang/lib/AST/DeclCXX.cpp (+28) 
- (modified) clang/test/CXX/drs/dr20xx.cpp (+2) 
- (modified) clang/test/CXX/drs/dr25xx.cpp (+47) 
- (modified) clang/test/SemaCXX/literal-type.cpp (+33) 
- (modified) clang/www/cxx_dr_status.html (+2-2) 


``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f..d967d904ba3fce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,11 @@ C++2c Feature Support
 Resolutions to C++ Defect Reports
 ^
 
+- Implemented `CWG2598 `_ and `CWG2096 
`_,
+  making unions (that have either no members or at least one literal member) 
literal types.
+  (`#77924: `_).
+
+
 C Language Changes
 --
 - ``structs``, ``unions``, and ``arrays`` that are const may now be used as
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 648f5f94640870..75b73700c44d67 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1439,31 +1439,20 @@ class CXXRecordDecl : public RecordDecl {
 
   /// Determine whether this class is a literal type.
   ///
-  /// C++11 [basic.types]p10:
+  /// C++20 [basic.types]p10:
   ///   A class type that has all the following properties:
-  /// - it has a trivial destructor
-  /// - every constructor call and full-expression in the
-  ///   brace-or-equal-intializers for non-static data members (if any) is
-  ///   a constant expression.
-  /// - it is an aggregate type or has at least one constexpr constructor
-  ///   or constructor template that is not a copy or move constructor, and
-  /// - all of its non-static data members and base classes are of literal
-  ///   types
-  ///
-  /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
-  /// treating types with trivial default constructors as literal types.
-  ///
-  /// Only in C++17 and beyond, are lambdas literal types.
-  bool isLiteral() const {
-const LangOptions &LangOpts = getLangOpts();
-return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
-  : hasTrivialDestructor()) &&
-   (!isLambda() || LangOpts.CPlusPlus17) &&
-   !hasNonLiteralTypeFieldsOrBases() &&
-   (isAggregate() || isLambda() ||
-hasConstexprNonCopyMoveConstructor() ||
-hasTrivialDefaultConstructor());
-  }
+  /// - it has a constexpr destructor
+  /// - all of its non-static non-variant data members and base classes
+  ///   are of non-volatile literal types, and it:
+  ///- is a closure type
+  ///- is an aggregate union type that has either no variant members
+  ///  or at least one variant member of non-volatile literal type
+  ///- is a non-union aggregate type for which each of its anonymous
+  ///  union members satisfies the above requirements for an aggregate
+  ///  union type, or
+  ///- has at least one constexpr constructor or constructor template
+  ///  that is not a copy or move constructor.
+  bool isLiteral() const;
 
   /// Determine whether this is a structural type.
   bool isStructural() const {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 98b0a6dc28ea2f..0d49d54fd64197 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolatileQualified() &&
+ D->getType().isTrivialType(getASTContext());
+});
+if (!HasAtLeastOneTrivialMember)
+  return false;
+  }
+
+  return isAggregate() || isLambda() || h

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Mital Ashok via cfe-commits


@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolatileQualified() &&
+ D->getType().isTrivialType(getASTContext());

MitalAshok wrote:

What about literal non-trivial types (e.g. `struct Literal { constexpr 
Literal() {} }; union union6 { NonLiteral NL; Literal L; };`?

`.isLiteralType` should work here

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits


@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolatileQualified() &&
+ D->getType().isTrivialType(getASTContext());

cor3ntin wrote:

Autocompletion blunder, Nice catch!

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits

https://github.com/cor3ntin updated 
https://github.com/llvm/llvm-project/pull/78195

>From f354ca458c1fa3cebb375f756f1a87fcf0586c3c Mon Sep 17 00:00:00 2001
From: Corentin Jabot 
Date: Mon, 15 Jan 2024 18:09:48 +0100
Subject: [PATCH 1/2] [Clang] Implement CWG2598: Union of non-literal types

A union is considered a literal type unless it has no
non-literal member.

This resolves CWG2096 (which makes unions with literal members literal)
and CWG2598 (empty unions are literal types).

Fixes #77924
---
 clang/docs/ReleaseNotes.rst |  5 +++
 clang/include/clang/AST/DeclCXX.h   | 37 ---
 clang/lib/AST/DeclCXX.cpp   | 28 +
 clang/test/CXX/drs/dr20xx.cpp   |  2 ++
 clang/test/CXX/drs/dr25xx.cpp   | 47 +
 clang/test/SemaCXX/literal-type.cpp | 33 
 clang/www/cxx_dr_status.html|  4 +--
 7 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f..d967d904ba3fce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,11 @@ C++2c Feature Support
 Resolutions to C++ Defect Reports
 ^
 
+- Implemented `CWG2598 `_ and `CWG2096 
`_,
+  making unions (that have either no members or at least one literal member) 
literal types.
+  (`#77924: `_).
+
+
 C Language Changes
 --
 - ``structs``, ``unions``, and ``arrays`` that are const may now be used as
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 648f5f94640870..75b73700c44d67 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1439,31 +1439,20 @@ class CXXRecordDecl : public RecordDecl {
 
   /// Determine whether this class is a literal type.
   ///
-  /// C++11 [basic.types]p10:
+  /// C++20 [basic.types]p10:
   ///   A class type that has all the following properties:
-  /// - it has a trivial destructor
-  /// - every constructor call and full-expression in the
-  ///   brace-or-equal-intializers for non-static data members (if any) is
-  ///   a constant expression.
-  /// - it is an aggregate type or has at least one constexpr constructor
-  ///   or constructor template that is not a copy or move constructor, and
-  /// - all of its non-static data members and base classes are of literal
-  ///   types
-  ///
-  /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
-  /// treating types with trivial default constructors as literal types.
-  ///
-  /// Only in C++17 and beyond, are lambdas literal types.
-  bool isLiteral() const {
-const LangOptions &LangOpts = getLangOpts();
-return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
-  : hasTrivialDestructor()) &&
-   (!isLambda() || LangOpts.CPlusPlus17) &&
-   !hasNonLiteralTypeFieldsOrBases() &&
-   (isAggregate() || isLambda() ||
-hasConstexprNonCopyMoveConstructor() ||
-hasTrivialDefaultConstructor());
-  }
+  /// - it has a constexpr destructor
+  /// - all of its non-static non-variant data members and base classes
+  ///   are of non-volatile literal types, and it:
+  ///- is a closure type
+  ///- is an aggregate union type that has either no variant members
+  ///  or at least one variant member of non-volatile literal type
+  ///- is a non-union aggregate type for which each of its anonymous
+  ///  union members satisfies the above requirements for an aggregate
+  ///  union type, or
+  ///- has at least one constexpr constructor or constructor template
+  ///  that is not a copy or move constructor.
+  bool isLiteral() const;
 
   /// Determine whether this is a structural type.
   bool isStructural() const {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 98b0a6dc28ea2f..0d49d54fd64197 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolati

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik commented:

Is this a potentially breaking change since we have expanded what types are 
considered literals and already existing code may observe this fix?

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik edited https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits


@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =

shafik wrote:

Why use trivial here? The DRs don't refer to trivial it refers to non-volatile 
literal type.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits


@@ -208,3 +208,54 @@ namespace dr2565 { // dr2565: 16 open
 
 #endif
 }
+
+
+namespace dr2598 { // dr2598: 18
+#if __cplusplus >= 201103L
+struct NonLiteral {
+NonLiteral();
+};
+
+struct anonymous1 {
+union {} a;
+};
+static_assert(__is_literal(anonymous1), "");
+
+struct anonymous2 {
+union { char c; };
+};
+static_assert(__is_literal(anonymous2), "");
+
+struct anonymous3 {
+union { char c; NonLiteral NL; };
+};
+static_assert(__is_literal(anonymous3), "");
+
+struct anonymous4 {
+union { NonLiteral NL; };
+};
+static_assert(!__is_literal(anonymous4), "");
+
+union empty {};
+static_assert(__is_literal(empty), "");
+
+union union1 { char c; };
+static_assert(__is_literal(union1), "");
+
+union union2 { char c; NonLiteral NL;};
+static_assert(__is_literal(union2), "");
+
+union union3 { NonLiteral NL;};
+static_assert(!__is_literal(union3), "");
+
+union union4 { union4(); };
+static_assert(!__is_literal(union4), "");
+
+union union5 { static NonLiteral NL; };
+static_assert(__is_literal(union5), "");
+
+struct Literal { constexpr Literal() {} };
+union union6 { NonLiteral NL; Literal L; };

shafik wrote:

Also should we have a `static_assert` after this line?

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits


@@ -208,3 +208,54 @@ namespace dr2565 { // dr2565: 16 open
 
 #endif
 }
+
+
+namespace dr2598 { // dr2598: 18
+#if __cplusplus >= 201103L
+struct NonLiteral {
+NonLiteral();
+};
+
+struct anonymous1 {
+union {} a;
+};
+static_assert(__is_literal(anonymous1), "");
+
+struct anonymous2 {
+union { char c; };
+};
+static_assert(__is_literal(anonymous2), "");
+
+struct anonymous3 {
+union { char c; NonLiteral NL; };
+};
+static_assert(__is_literal(anonymous3), "");
+
+struct anonymous4 {
+union { NonLiteral NL; };
+};
+static_assert(!__is_literal(anonymous4), "");
+
+union empty {};
+static_assert(__is_literal(empty), "");
+
+union union1 { char c; };
+static_assert(__is_literal(union1), "");
+
+union union2 { char c; NonLiteral NL;};
+static_assert(__is_literal(union2), "");
+
+union union3 { NonLiteral NL;};
+static_assert(!__is_literal(union3), "");
+
+union union4 { union4(); };
+static_assert(!__is_literal(union4), "");
+
+union union5 { static NonLiteral NL; };
+static_assert(__is_literal(union5), "");
+
+struct Literal { constexpr Literal() {} };
+union union6 { NonLiteral NL; Literal L; };

shafik wrote:

Can we also include the exact example from CWG2598 as well, just to be complete.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits


@@ -208,3 +208,54 @@ namespace dr2565 { // dr2565: 16 open
 
 #endif
 }
+
+
+namespace dr2598 { // dr2598: 18
+#if __cplusplus >= 201103L
+struct NonLiteral {
+NonLiteral();
+};
+
+struct anonymous1 {
+union {} a;
+};
+static_assert(__is_literal(anonymous1), "");
+
+struct anonymous2 {
+union { char c; };
+};
+static_assert(__is_literal(anonymous2), "");
+
+struct anonymous3 {
+union { char c; NonLiteral NL; };
+};
+static_assert(__is_literal(anonymous3), "");
+
+struct anonymous4 {
+union { NonLiteral NL; };
+};
+static_assert(!__is_literal(anonymous4), "");
+
+union empty {};
+static_assert(__is_literal(empty), "");
+
+union union1 { char c; };
+static_assert(__is_literal(union1), "");
+
+union union2 { char c; NonLiteral NL;};
+static_assert(__is_literal(union2), "");
+
+union union3 { NonLiteral NL;};
+static_assert(!__is_literal(union3), "");
+
+union union4 { union4(); };
+static_assert(!__is_literal(union4), "");
+
+union union5 { static NonLiteral NL; };
+static_assert(__is_literal(union5), "");
+
+struct Literal { constexpr Literal() {} };
+union union6 { NonLiteral NL; Literal L; };

shafik wrote:

I also noticed that gcc does not seem to support `__is_literal` only 
`__is_literal_type`

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread Shafik Yaghmour via cfe-commits

https://github.com/shafik commented:

Mostly looks good but I would like a second set of eyes.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits

https://github.com/cor3ntin updated 
https://github.com/llvm/llvm-project/pull/78195

>From f354ca458c1fa3cebb375f756f1a87fcf0586c3c Mon Sep 17 00:00:00 2001
From: Corentin Jabot 
Date: Mon, 15 Jan 2024 18:09:48 +0100
Subject: [PATCH 1/3] [Clang] Implement CWG2598: Union of non-literal types

A union is considered a literal type unless it has no
non-literal member.

This resolves CWG2096 (which makes unions with literal members literal)
and CWG2598 (empty unions are literal types).

Fixes #77924
---
 clang/docs/ReleaseNotes.rst |  5 +++
 clang/include/clang/AST/DeclCXX.h   | 37 ---
 clang/lib/AST/DeclCXX.cpp   | 28 +
 clang/test/CXX/drs/dr20xx.cpp   |  2 ++
 clang/test/CXX/drs/dr25xx.cpp   | 47 +
 clang/test/SemaCXX/literal-type.cpp | 33 
 clang/www/cxx_dr_status.html|  4 +--
 7 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f8..d967d904ba3fce4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,11 @@ C++2c Feature Support
 Resolutions to C++ Defect Reports
 ^
 
+- Implemented `CWG2598 `_ and `CWG2096 
`_,
+  making unions (that have either no members or at least one literal member) 
literal types.
+  (`#77924: `_).
+
+
 C Language Changes
 --
 - ``structs``, ``unions``, and ``arrays`` that are const may now be used as
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 648f5f946408700..75b73700c44d671 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1439,31 +1439,20 @@ class CXXRecordDecl : public RecordDecl {
 
   /// Determine whether this class is a literal type.
   ///
-  /// C++11 [basic.types]p10:
+  /// C++20 [basic.types]p10:
   ///   A class type that has all the following properties:
-  /// - it has a trivial destructor
-  /// - every constructor call and full-expression in the
-  ///   brace-or-equal-intializers for non-static data members (if any) is
-  ///   a constant expression.
-  /// - it is an aggregate type or has at least one constexpr constructor
-  ///   or constructor template that is not a copy or move constructor, and
-  /// - all of its non-static data members and base classes are of literal
-  ///   types
-  ///
-  /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
-  /// treating types with trivial default constructors as literal types.
-  ///
-  /// Only in C++17 and beyond, are lambdas literal types.
-  bool isLiteral() const {
-const LangOptions &LangOpts = getLangOpts();
-return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
-  : hasTrivialDestructor()) &&
-   (!isLambda() || LangOpts.CPlusPlus17) &&
-   !hasNonLiteralTypeFieldsOrBases() &&
-   (isAggregate() || isLambda() ||
-hasConstexprNonCopyMoveConstructor() ||
-hasTrivialDefaultConstructor());
-  }
+  /// - it has a constexpr destructor
+  /// - all of its non-static non-variant data members and base classes
+  ///   are of non-volatile literal types, and it:
+  ///- is a closure type
+  ///- is an aggregate union type that has either no variant members
+  ///  or at least one variant member of non-volatile literal type
+  ///- is a non-union aggregate type for which each of its anonymous
+  ///  union members satisfies the above requirements for an aggregate
+  ///  union type, or
+  ///- has at least one constexpr constructor or constructor template
+  ///  that is not a copy or move constructor.
+  bool isLiteral() const;
 
   /// Determine whether this is a structural type.
   bool isStructural() const {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 98b0a6dc28ea2f0..0d49d54fd641977 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().is

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits


@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =

cor3ntin wrote:

Yes, that makes no sense

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits


@@ -208,3 +208,54 @@ namespace dr2565 { // dr2565: 16 open
 
 #endif
 }
+
+
+namespace dr2598 { // dr2598: 18
+#if __cplusplus >= 201103L
+struct NonLiteral {
+NonLiteral();
+};
+
+struct anonymous1 {
+union {} a;
+};
+static_assert(__is_literal(anonymous1), "");
+
+struct anonymous2 {
+union { char c; };
+};
+static_assert(__is_literal(anonymous2), "");
+
+struct anonymous3 {
+union { char c; NonLiteral NL; };
+};
+static_assert(__is_literal(anonymous3), "");
+
+struct anonymous4 {
+union { NonLiteral NL; };
+};
+static_assert(!__is_literal(anonymous4), "");
+
+union empty {};
+static_assert(__is_literal(empty), "");
+
+union union1 { char c; };
+static_assert(__is_literal(union1), "");
+
+union union2 { char c; NonLiteral NL;};
+static_assert(__is_literal(union2), "");
+
+union union3 { NonLiteral NL;};
+static_assert(!__is_literal(union3), "");
+
+union union4 { union4(); };
+static_assert(!__is_literal(union4), "");
+
+union union5 { static NonLiteral NL; };
+static_assert(__is_literal(union5), "");
+
+struct Literal { constexpr Literal() {} };
+union union6 { NonLiteral NL; Literal L; };

cor3ntin wrote:

Yup, both are synnym in clang

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits

https://github.com/cor3ntin edited 
https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-15 Thread via cfe-commits

cor3ntin wrote:

> Is this a potentially breaking change since we have expanded what types are 
> considered literals and already existing code may observe this fix?

Some expression will become constant expressions and presumably that can be 
SFINAE upon, but given that this is a DR, I don't think we are affecting 
conformance and I don't think we make strong sfinae guarantee.

GCC is conforming with that DR in all language mode since 10.0 
https://compiler-explorer.com/z/hKnThPx1T

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread Erich Keane via cfe-commits


@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneLiteralMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolatileQualified() &&
+ D->getType()->isLiteralType(getASTContext());
+});
+if (!HasAtLeastOneLiteralMember)
+  return false;
+  }
+
+  return isAggregate() || isLambda() || hasConstexprNonCopyMoveConstructor() ||

erichkeane wrote:

Should these conditions be moved 'above' the union stuff?  I would think they 
are 'cheaper'.  Also, I see the 'isLambda' here, despite it only being in C++17 
mode on line 1392.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread via cfe-commits

https://github.com/cor3ntin updated 
https://github.com/llvm/llvm-project/pull/78195

>From f354ca458c1fa3cebb375f756f1a87fcf0586c3c Mon Sep 17 00:00:00 2001
From: Corentin Jabot 
Date: Mon, 15 Jan 2024 18:09:48 +0100
Subject: [PATCH 1/4] [Clang] Implement CWG2598: Union of non-literal types

A union is considered a literal type unless it has no
non-literal member.

This resolves CWG2096 (which makes unions with literal members literal)
and CWG2598 (empty unions are literal types).

Fixes #77924
---
 clang/docs/ReleaseNotes.rst |  5 +++
 clang/include/clang/AST/DeclCXX.h   | 37 ---
 clang/lib/AST/DeclCXX.cpp   | 28 +
 clang/test/CXX/drs/dr20xx.cpp   |  2 ++
 clang/test/CXX/drs/dr25xx.cpp   | 47 +
 clang/test/SemaCXX/literal-type.cpp | 33 
 clang/www/cxx_dr_status.html|  4 +--
 7 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f8..d967d904ba3fce4 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,11 @@ C++2c Feature Support
 Resolutions to C++ Defect Reports
 ^
 
+- Implemented `CWG2598 `_ and `CWG2096 
`_,
+  making unions (that have either no members or at least one literal member) 
literal types.
+  (`#77924: `_).
+
+
 C Language Changes
 --
 - ``structs``, ``unions``, and ``arrays`` that are const may now be used as
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 648f5f946408700..75b73700c44d671 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1439,31 +1439,20 @@ class CXXRecordDecl : public RecordDecl {
 
   /// Determine whether this class is a literal type.
   ///
-  /// C++11 [basic.types]p10:
+  /// C++20 [basic.types]p10:
   ///   A class type that has all the following properties:
-  /// - it has a trivial destructor
-  /// - every constructor call and full-expression in the
-  ///   brace-or-equal-intializers for non-static data members (if any) is
-  ///   a constant expression.
-  /// - it is an aggregate type or has at least one constexpr constructor
-  ///   or constructor template that is not a copy or move constructor, and
-  /// - all of its non-static data members and base classes are of literal
-  ///   types
-  ///
-  /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
-  /// treating types with trivial default constructors as literal types.
-  ///
-  /// Only in C++17 and beyond, are lambdas literal types.
-  bool isLiteral() const {
-const LangOptions &LangOpts = getLangOpts();
-return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
-  : hasTrivialDestructor()) &&
-   (!isLambda() || LangOpts.CPlusPlus17) &&
-   !hasNonLiteralTypeFieldsOrBases() &&
-   (isAggregate() || isLambda() ||
-hasConstexprNonCopyMoveConstructor() ||
-hasTrivialDefaultConstructor());
-  }
+  /// - it has a constexpr destructor
+  /// - all of its non-static non-variant data members and base classes
+  ///   are of non-volatile literal types, and it:
+  ///- is a closure type
+  ///- is an aggregate union type that has either no variant members
+  ///  or at least one variant member of non-volatile literal type
+  ///- is a non-union aggregate type for which each of its anonymous
+  ///  union members satisfies the above requirements for an aggregate
+  ///  union type, or
+  ///- has at least one constexpr constructor or constructor template
+  ///  that is not a copy or move constructor.
+  bool isLiteral() const;
 
   /// Determine whether this is a structural type.
   bool isStructural() const {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 98b0a6dc28ea2f0..0d49d54fd641977 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().is

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread Erich Keane via cfe-commits


@@ -1389,7 +1389,11 @@ bool CXXRecordDecl::isLiteral() const {
  : hasTrivialDestructor()))
 return false;
 
-  if (isLambda() && !LangOpts.CPlusPlus17)
+  // Lambdas are literal types since C++17.

erichkeane wrote:

So why is `isAggregate` or `hasConstexprNonCopyMoveConstructor`/etc not just 
`return true` here?  Am I missing something? 

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread via cfe-commits


@@ -1389,7 +1389,11 @@ bool CXXRecordDecl::isLiteral() const {
  : hasTrivialDestructor()))
 return false;
 
-  if (isLambda() && !LangOpts.CPlusPlus17)
+  // Lambdas are literal types since C++17.

cor3ntin wrote:

And aggregate can have non literal members

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread Erich Keane via cfe-commits


@@ -1389,7 +1389,11 @@ bool CXXRecordDecl::isLiteral() const {
  : hasTrivialDestructor()))
 return false;
 
-  if (isLambda() && !LangOpts.CPlusPlus17)
+  // Lambdas are literal types since C++17.

erichkeane wrote:

Hmm... this is worse then.  Other than the concern about 'isLambda', I think 
you should revert the suggested change here.  Its not worth the awkward 
inversions here.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread via cfe-commits

https://github.com/cor3ntin updated 
https://github.com/llvm/llvm-project/pull/78195

>From f354ca458c1fa3cebb375f756f1a87fcf0586c3c Mon Sep 17 00:00:00 2001
From: Corentin Jabot 
Date: Mon, 15 Jan 2024 18:09:48 +0100
Subject: [PATCH 1/5] [Clang] Implement CWG2598: Union of non-literal types

A union is considered a literal type unless it has no
non-literal member.

This resolves CWG2096 (which makes unions with literal members literal)
and CWG2598 (empty unions are literal types).

Fixes #77924
---
 clang/docs/ReleaseNotes.rst |  5 +++
 clang/include/clang/AST/DeclCXX.h   | 37 ---
 clang/lib/AST/DeclCXX.cpp   | 28 +
 clang/test/CXX/drs/dr20xx.cpp   |  2 ++
 clang/test/CXX/drs/dr25xx.cpp   | 47 +
 clang/test/SemaCXX/literal-type.cpp | 33 
 clang/www/cxx_dr_status.html|  4 +--
 7 files changed, 130 insertions(+), 26 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7e130304c5c08f..d967d904ba3fce 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -227,6 +227,11 @@ C++2c Feature Support
 Resolutions to C++ Defect Reports
 ^
 
+- Implemented `CWG2598 `_ and `CWG2096 
`_,
+  making unions (that have either no members or at least one literal member) 
literal types.
+  (`#77924: `_).
+
+
 C Language Changes
 --
 - ``structs``, ``unions``, and ``arrays`` that are const may now be used as
diff --git a/clang/include/clang/AST/DeclCXX.h 
b/clang/include/clang/AST/DeclCXX.h
index 648f5f94640870..75b73700c44d67 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1439,31 +1439,20 @@ class CXXRecordDecl : public RecordDecl {
 
   /// Determine whether this class is a literal type.
   ///
-  /// C++11 [basic.types]p10:
+  /// C++20 [basic.types]p10:
   ///   A class type that has all the following properties:
-  /// - it has a trivial destructor
-  /// - every constructor call and full-expression in the
-  ///   brace-or-equal-intializers for non-static data members (if any) is
-  ///   a constant expression.
-  /// - it is an aggregate type or has at least one constexpr constructor
-  ///   or constructor template that is not a copy or move constructor, and
-  /// - all of its non-static data members and base classes are of literal
-  ///   types
-  ///
-  /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by
-  /// treating types with trivial default constructors as literal types.
-  ///
-  /// Only in C++17 and beyond, are lambdas literal types.
-  bool isLiteral() const {
-const LangOptions &LangOpts = getLangOpts();
-return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
-  : hasTrivialDestructor()) &&
-   (!isLambda() || LangOpts.CPlusPlus17) &&
-   !hasNonLiteralTypeFieldsOrBases() &&
-   (isAggregate() || isLambda() ||
-hasConstexprNonCopyMoveConstructor() ||
-hasTrivialDefaultConstructor());
-  }
+  /// - it has a constexpr destructor
+  /// - all of its non-static non-variant data members and base classes
+  ///   are of non-volatile literal types, and it:
+  ///- is a closure type
+  ///- is an aggregate union type that has either no variant members
+  ///  or at least one variant member of non-volatile literal type
+  ///- is a non-union aggregate type for which each of its anonymous
+  ///  union members satisfies the above requirements for an aggregate
+  ///  union type, or
+  ///- has at least one constexpr constructor or constructor template
+  ///  that is not a copy or move constructor.
+  bool isLiteral() const;
 
   /// Determine whether this is a structural type.
   bool isStructural() const {
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 98b0a6dc28ea2f..0d49d54fd64197 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -1383,6 +1383,34 @@ void CXXRecordDecl::addedMember(Decl *D) {
   }
 }
 
+bool CXXRecordDecl::isLiteral() const {
+  const LangOptions &LangOpts = getLangOpts();
+  if (!(LangOpts.CPlusPlus20 ? hasConstexprDestructor()
+ : hasTrivialDestructor()))
+return false;
+
+  if (isLambda() && !LangOpts.CPlusPlus17)
+return false;
+
+  if (hasNonLiteralTypeFieldsOrBases()) {
+// CWG2598
+// is an aggregate union type that has either no variant
+// members or at least one variant member of non-volatile literal type,
+if (!isUnion())
+  return false;
+bool HasAtLeastOneTrivialMember =
+fields().empty() || any_of(fields(), [this](const FieldDecl *D) {
+  return !D->getType().isVolati

[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.


https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-16 Thread via cfe-commits

https://github.com/cor3ntin closed 
https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-17 Thread via cfe-commits

groundswellaudio wrote:

Thanks for the fix @cor3ntin. There is still a problem however with 
`std::optional`, which I think boils down to implicit destructor and anonymous 
union : 

```cpp
struct A {
  A ();
  ~A();
};

template 
struct opt
{
  union {
char c;
T data;
  };
  
  constexpr opt() {}
  
  constexpr ~opt() {
if (engaged)
  data.~T();
  }
  
  bool engaged = false;
};

consteval void foo()
{
  opt a;
}
```

This fails with `non-literal type 'opt' cannot be used in a constant 
expression`, but compiles if A has no destructor (or if that destructor is 
constexpr). 

I suspect that the culprit is here : 
https://github.com/llvm/llvm-project/blob/fca6992be1f272f5e997bd510ca03c9389550c13/clang/lib/AST/DeclCXX.cpp#L550

The implicit destructor of the anonymous union is not constexpr because one of 
its subobjects has a non-constexpr destructor. 

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-17 Thread via cfe-commits

cor3ntin wrote:

@groundswellaudio Thanks for letting me know. can you create a separate issue ?


https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-17 Thread via cfe-commits

cor3ntin wrote:

@groundswellaudio actually, that should be fixed by 
https://github.com/llvm/llvm-project/pull/77753
@Fznamznon Can you confirm?

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-17 Thread Mariya Podchishchaeva via cfe-commits

Fznamznon wrote:

> @groundswellaudio actually, that should be fixed by 
> https://github.com/llvm/llvm-project/pull/77753
@Fznamznon Can you confirm?

Yes, it does make an error to go away. However the function `foo` from the 
[code](https://github.com/llvm/llvm-project/pull/78195#issuecomment-1895950521) 
won't be callable. If it is `constexpr` instead of `consteval`, then it is 
callable outside of constexpr context.

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-18 Thread via cfe-commits

groundswellaudio wrote:

@Fznamznon 
@cor3ntin 
So https://github.com/llvm/llvm-project/pull/77753 doesn't solve the problem of 
an anonymous union not being literal when it should be, right? 

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-18 Thread via cfe-commits

cor3ntin wrote:

Looking at that again, i suspect I did not handle indirect fields properly. 
I'll try to get to that. Sorry!

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-18 Thread via cfe-commits

groundswellaudio wrote:

By looking at your tests on anonymous unions, I'd say that indirect fields are 
handled correctly (perhaps they're not included in the fields range?, otherwise 
the union-like class would not be considered literal) and that rather the 
implicitly generated special member functions of the anonymous union are the 
problems (and it's unclear to me why these would be needed at all, but perhaps 
it's simpler to generate them that to make a special case anonymous unions). 

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] Implement CWG2598: Union of non-literal types (PR #78195)

2024-01-18 Thread via cfe-commits

cor3ntin wrote:

> @Fznamznon @cor3ntin So #77753 doesn't solve the problem of the enclosing 
> class of an anonymous union not being literal when it should be, right?

It should actually, CF comments in that PR (I got your code working locally)

https://github.com/llvm/llvm-project/pull/78195
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits