leoetlino updated this revision to Diff 386622.
leoetlino added a comment.

Fix Clang.CodeGenCXX::mangle-class-nttp.cpp test


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D113694/new/

https://reviews.llvm.org/D113694

Files:
  clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
  clang/include/clang/AST/DeclCXX.h
  clang/lib/AST/DeclCXX.cpp
  clang/test/CXX/basic/basic.types/p10.cpp

Index: clang/test/CXX/basic/basic.types/p10.cpp
===================================================================
--- clang/test/CXX/basic/basic.types/p10.cpp
+++ clang/test/CXX/basic/basic.types/p10.cpp
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s -DCXX1Y
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -DCXX11 -DCXX11_OR_LATER
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1y %s -DCXX1Y -DCXX11_OR_LATER -DCXX1Y_OR_LATER
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s -DCXX17 -DCXX11_OR_LATER -DCXX1Y_OR_LATER -DCXX17_OR_LATER
 
 struct NonLiteral { NonLiteral(); };
 
@@ -7,7 +8,7 @@
 
 // [C++1y] - void
 constexpr void f() {}
-#ifndef CXX1Y
+#ifdef CXX11
 // expected-error@-2 {{'void' is not a literal type}}
 #endif
 
@@ -20,7 +21,7 @@
 
 struct BeingDefined;
 extern BeingDefined beingdefined;
-struct BeingDefined { 
+struct BeingDefined {
   static constexpr BeingDefined& t = beingdefined;
 };
 
@@ -64,8 +65,14 @@
 };
 constexpr int f(TrivDefaultedDtor) { return 0; }
 
-//  - it is an aggregate type or has at least one constexpr constructor or
+//  - it is [a closure type [C++17]], an aggregate type or has at least one constexpr constructor or
 //    constexpr constructor template that is not a copy or move constructor
+#ifndef CXX17_OR_LATER
+// expected-error@+4 {{not a literal type}}
+// expected-note@+2 {{lambda closure types are non-literal types before C++17}}
+#endif
+auto closure = [] {};
+constexpr int f(decltype(closure)) { return 0; }
 struct Agg {
   int a;
   char *b;
@@ -101,7 +108,8 @@
 template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {}
 constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // expected-error {{constant expression}} expected-note {{cannot construct object of type 'DerivedFromVBase<HasVBase>' with virtual base class in a constant expression}}
 
-//  - it has all non-static data members and base classes of literal types
+//  - [C++17] if it is a union, at least one of its non-static data members is of non-volatile literal type, and
+//  - [if it is not a union [C++17]] it has all non-static data members and base classes of literal types
 struct NonLitMember {
   S s; // expected-note {{has data member 's' of non-literal type 'S'}}
 };
@@ -122,6 +130,19 @@
 constexpr int f(MemberType<int>) { return 0; }
 constexpr int f(MemberType<NonLiteral>) { return 0; } // expected-error {{not a literal type}}
 
+template<typename T>
+union UnionType {
+  char c;
+  T t;
+  constexpr UnionType() : c{} {}
+};
+constexpr int f(UnionType<int>) { return 0; }
+#ifndef CXX17_OR_LATER
+// expected-error@+3 {{not a literal type}}
+// expected-note@-6 {{'UnionType<NonLiteral>' is not literal because it has data member 't' of non-literal type 'NonLiteral'}}
+#endif
+constexpr int f(UnionType<NonLiteral>) { return 0; }
+
 // - an array of literal type [C++1y] other than an array of runtime bound
 struct ArrGood {
   Agg agg[24];
Index: clang/lib/AST/DeclCXX.cpp
===================================================================
--- clang/lib/AST/DeclCXX.cpp
+++ clang/lib/AST/DeclCXX.cpp
@@ -102,7 +102,8 @@
       DefaultedDefaultConstructorIsConstexpr(true),
       HasConstexprDefaultConstructor(false),
       DefaultedDestructorIsConstexpr(true),
-      HasNonLiteralTypeFieldsOrBases(false), StructuralIfLiteral(true),
+      HasNonLiteralTypeFieldsOrBases(false),
+      HasNonVolatileLiteralTypeFields(false), StructuralIfLiteral(true),
       UserProvidedDefaultConstructor(false), DeclaredSpecialMembers(0),
       ImplicitCopyConstructorCanHaveConstParamForVBase(true),
       ImplicitCopyConstructorCanHaveConstParamForNonVBase(true),
@@ -1103,8 +1104,12 @@
       }
     }
 
+    const bool IsNonVolatileLiteralTypeField =
+        T->isLiteralType(Context) && !T.isVolatileQualified();
     // Record if this field is the first non-literal or volatile field or base.
-    if (!T->isLiteralType(Context) || T.isVolatileQualified())
+    if (IsNonVolatileLiteralTypeField)
+      data().HasNonVolatileLiteralTypeFields = true;
+    else
       data().HasNonLiteralTypeFieldsOrBases = true;
 
     if (Field->hasInClassInitializer() ||
Index: clang/include/clang/AST/DeclCXX.h
===================================================================
--- clang/include/clang/AST/DeclCXX.h
+++ clang/include/clang/AST/DeclCXX.h
@@ -1354,6 +1354,12 @@
     return data().HasNonLiteralTypeFieldsOrBases;
   }
 
+  /// Determine whether this class has a non-volatile literal type
+  /// non-static data member.
+  bool hasNonVolatileLiteralTypeFields() const {
+    return data().HasNonVolatileLiteralTypeFields;
+  }
+
   /// Determine whether this class has a using-declaration that names
   /// a user-declared base class constructor.
   bool hasInheritedConstructor() const {
@@ -1396,12 +1402,20 @@
   /// treating types with trivial default constructors as literal types.
   ///
   /// Only in C++17 and beyond, are lambdas literal types.
+  /// A union is a literal type if at least one of its non-static data members
+  /// is of non-volatile literal type.
   bool isLiteral() const {
     const LangOptions &LangOpts = getLangOpts();
+
+    bool FieldsOk = !hasNonLiteralTypeFieldsOrBases();
+    if (LangOpts.CPlusPlus17 && isUnion()) {
+      FieldsOk = !hasDirectFields() || hasNonVolatileLiteralTypeFields();
+    }
+
     return (LangOpts.CPlusPlus20 ? hasConstexprDestructor()
                                           : hasTrivialDestructor()) &&
            (!isLambda() || LangOpts.CPlusPlus17) &&
-           !hasNonLiteralTypeFieldsOrBases() &&
+           FieldsOk &&
            (isAggregate() || isLambda() ||
             hasConstexprNonCopyMoveConstructor() ||
             hasTrivialDefaultConstructor());
Index: clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
===================================================================
--- clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
+++ clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
@@ -214,6 +214,10 @@
 /// member or base class of non-literal or volatile type.
 FIELD(HasNonLiteralTypeFieldsOrBases, 1, NO_MERGE)
 
+/// True when this class contains at least one non-static data
+/// member of non-volatile literal type.
+FIELD(HasNonVolatileLiteralTypeFields, 1, NO_MERGE)
+
 /// True if this class is a structural type, assuming it is a literal type.
 FIELD(StructuralIfLiteral, 1, NO_MERGE)
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to