|  | // RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-linux -ast-dump=json %s | FileCheck %s --check-prefixes=CHECK,LIN | 
|  | // RUN: %clang_cc1 -std=c++20 -triple x86_64-pc-win32 -ast-dump=json %s | FileCheck %s | 
|  |  | 
|  | // This test validates that we compute correct AST properties of classes with | 
|  | // conditionally trivial special member functions. | 
|  |  | 
|  | template <int N> | 
|  | struct DefaultConstructorCheck { | 
|  | DefaultConstructorCheck() requires(N == 1) = default; | 
|  | DefaultConstructorCheck() requires(N == 2) = delete; | 
|  | DefaultConstructorCheck() requires(N == 3); | 
|  | DefaultConstructorCheck(); | 
|  | }; | 
|  |  | 
|  |  | 
|  | template struct DefaultConstructorCheck<1>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "defaultCtor": { | 
|  | // CHECK-NEXT:            "defaultedIsConstexpr": true, | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "isConstexpr": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userProvided": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT:          "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isLiteral": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTrivial": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  |  | 
|  | template struct DefaultConstructorCheck<2>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "defaultCtor": { | 
|  | // CHECK-NEXT:            "defaultedIsConstexpr": true, | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "isConstexpr": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userProvided": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT:          "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isLiteral": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTrivial": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  |  | 
|  |  | 
|  | template struct DefaultConstructorCheck<3>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "defaultCtor": { | 
|  | // CHECK-NEXT:            "defaultedIsConstexpr": true, | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "isConstexpr": true, | 
|  | // CHECK-NEXT:            "nonTrivial": true, | 
|  | // CHECK-NEXT:            "userProvided": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT:          "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isLiteral": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  |  | 
|  | template <int N> | 
|  | struct CopyConstructorCheck { | 
|  | CopyConstructorCheck(const CopyConstructorCheck&) requires(N == 1) = default; | 
|  | CopyConstructorCheck(const CopyConstructorCheck&) requires(N == 2) = delete; | 
|  | CopyConstructorCheck(const CopyConstructorCheck&) requires(N == 3); | 
|  | CopyConstructorCheck(const CopyConstructorCheck&); | 
|  | }; | 
|  |  | 
|  |  | 
|  | template struct CopyConstructorCheck<1>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "copyCtor": { | 
|  | // CHECK-NEXT:            "hasConstParam": true, | 
|  | // CHECK-NEXT:            "implicitHasConstParam": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | // CHECK:               "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT:          "moveAssign": {}, | 
|  |  | 
|  | template struct CopyConstructorCheck<2>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "copyCtor": { | 
|  | // CHECK-NEXT:            "hasConstParam": true, | 
|  | // CHECK-NEXT:            "implicitHasConstParam": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | // CHECK:               "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT:          "moveAssign": {}, | 
|  |  | 
|  | template struct CopyConstructorCheck<3>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "copyCtor": { | 
|  | // CHECK-NEXT:            "hasConstParam": true, | 
|  | // CHECK-NEXT:            "implicitHasConstParam": true, | 
|  | // CHECK-NEXT:            "nonTrivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | // CHECK:               "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "moveAssign": {}, | 
|  |  | 
|  | template <int N> | 
|  | struct MoveConstructorCheck { | 
|  | MoveConstructorCheck(MoveConstructorCheck&&) requires(N == 1) = default; | 
|  | MoveConstructorCheck(MoveConstructorCheck&&) requires(N == 2) = delete; | 
|  | MoveConstructorCheck(MoveConstructorCheck&&) requires(N == 3); | 
|  | MoveConstructorCheck(MoveConstructorCheck&&); | 
|  | }; | 
|  |  | 
|  |  | 
|  | template struct MoveConstructorCheck<1>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // LIN-NEXT:            "canPassInRegisters": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT:          "moveAssign": {}, | 
|  | // CHECK-NEXT:          "moveCtor": { | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          } | 
|  |  | 
|  | template struct MoveConstructorCheck<2>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT:          "moveAssign": {}, | 
|  | // CHECK-NEXT:          "moveCtor": { | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          } | 
|  |  | 
|  | template struct MoveConstructorCheck<3>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "hasUserDeclaredConstructor": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "moveAssign": {}, | 
|  | // CHECK-NEXT:          "moveCtor": { | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "nonTrivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          } | 
|  |  | 
|  | template <int N> | 
|  | struct CopyAssignmentCheck { | 
|  | CopyAssignmentCheck& operator=(const CopyAssignmentCheck&) requires(N == 1) = default; | 
|  | CopyAssignmentCheck& operator=(const CopyAssignmentCheck&) requires(N == 2) = delete; | 
|  | CopyAssignmentCheck& operator=(const CopyAssignmentCheck&) requires(N == 3); | 
|  | CopyAssignmentCheck& operator=(const CopyAssignmentCheck&); | 
|  | }; | 
|  |  | 
|  |  | 
|  | template struct CopyAssignmentCheck<1>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT           "copyAssign": { | 
|  | // CHECK-NEXT             "hasConstParam": true, | 
|  | // CHECK-NEXT             "implicitHasConstParam": true, | 
|  | // CHECK-NEXT             "trivial": true, | 
|  | // CHECK-NEXT             "userDeclared": true | 
|  | // CHECK-NEXT           }, | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT           "isAggregate": true, | 
|  | // CHECK-NEXT           "isEmpty": true, | 
|  | // CHECK-NEXT           "isLiteral": true, | 
|  | // CHECK-NEXT           "isStandardLayout": true, | 
|  | // CHECK-NEXT           "isTrivial": true, | 
|  | // CHECK-NEXT           "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT           "moveAssign": {}, | 
|  |  | 
|  | template struct CopyAssignmentCheck<2>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT           "copyAssign": { | 
|  | // CHECK-NEXT             "hasConstParam": true, | 
|  | // CHECK-NEXT             "implicitHasConstParam": true, | 
|  | // CHECK-NEXT             "trivial": true, | 
|  | // CHECK-NEXT             "userDeclared": true | 
|  | // CHECK-NEXT           }, | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT           "isAggregate": true, | 
|  | // CHECK-NEXT           "isEmpty": true, | 
|  | // CHECK-NEXT           "isLiteral": true, | 
|  | // CHECK-NEXT           "isStandardLayout": true, | 
|  | // CHECK-NEXT           "isTrivial": true, | 
|  | // CHECK-NEXT           "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT           "moveAssign": {}, | 
|  |  | 
|  | template struct CopyAssignmentCheck<3>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "canPassInRegisters": true, | 
|  | // CHECK-NEXT           "copyAssign": { | 
|  | // CHECK-NEXT             "hasConstParam": true, | 
|  | // CHECK-NEXT             "implicitHasConstParam": true, | 
|  | // CHECK-NEXT             "trivial": true, | 
|  | // CHECK-NEXT             "userDeclared": true | 
|  | // CHECK-NEXT           }, | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT           "isAggregate": true, | 
|  | // CHECK-NEXT           "isEmpty": true, | 
|  | // CHECK-NEXT           "isLiteral": true, | 
|  | // CHECK-NEXT           "isStandardLayout": true, | 
|  | // CHECK-NEXT           "moveAssign": {}, | 
|  |  | 
|  | template <int N> | 
|  | struct MoveAssignmentCheck { | 
|  | MoveAssignmentCheck& operator=(MoveAssignmentCheck&&) requires(N == 1) = default; | 
|  | MoveAssignmentCheck& operator=(MoveAssignmentCheck&&) requires(N == 2) = delete; | 
|  | MoveAssignmentCheck& operator=(MoveAssignmentCheck&&) requires(N == 3); | 
|  | MoveAssignmentCheck& operator=(MoveAssignmentCheck&&); | 
|  | }; | 
|  |  | 
|  |  | 
|  | template struct MoveAssignmentCheck<1>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT:          "isAggregate": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isLiteral": true, | 
|  | // CHECK-NEXT:          "isPOD": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTrivial": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT:          "moveAssign": { | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | template struct MoveAssignmentCheck<2>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT:          "isAggregate": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isLiteral": true, | 
|  | // CHECK-NEXT:          "isPOD": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "isTrivial": true, | 
|  | // CHECK-NEXT:          "isTriviallyCopyable": true, | 
|  | // CHECK-NEXT:          "moveAssign": { | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "trivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          }, | 
|  |  | 
|  | template struct MoveAssignmentCheck<3>; | 
|  | // CHECK:             "kind": "ClassTemplateSpecializationDecl", | 
|  | // CHECK:             "definitionData": { | 
|  | // CHECK-NEXT:          "canConstDefaultInit": true, | 
|  | // CHECK-NEXT:          "copyAssign": { | 
|  |  | 
|  | // CHECK:               "hasConstexprNonCopyMoveConstructor": true, | 
|  | // CHECK-NEXT:          "isAggregate": true, | 
|  | // CHECK-NEXT:          "isEmpty": true, | 
|  | // CHECK-NEXT:          "isLiteral": true, | 
|  | // CHECK-NEXT:          "isPOD": true, | 
|  | // CHECK-NEXT:          "isStandardLayout": true, | 
|  | // CHECK-NEXT:          "moveAssign": { | 
|  | // CHECK-NEXT:            "exists": true, | 
|  | // CHECK-NEXT:            "nonTrivial": true, | 
|  | // CHECK-NEXT:            "userDeclared": true | 
|  | // CHECK-NEXT:          }, |