diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -216,6 +216,7 @@ BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") BENIGN_LANGOPT(AccessControl , 1, 1, "C++ access control") +LANGOPT(DefaultedSMFArePOD, 1, 0, "Defaulted Special Members are allowed on POD types") LANGOPT(CharIsSigned , 1, 1, "signed char") LANGOPT(WCharSize , 4, 0, "width of wchar_t") LANGOPT(WCharIsSigned , 1, 0, "signed or unsigned wchar_t") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1113,6 +1113,10 @@ LangOpts<"AccessControl">, DefaultTrue, NegFlag, PosFlag>; +defm defaulted_smf_are_pod : BoolFOption<"defaulted-smf-are-pod", + LangOpts<"DefaultedSMFArePOD">, DefaultFalse, + NegFlag, + PosFlag>; def falign_functions : Flag<["-"], "falign-functions">, Group; def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group; def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group, Flags<[CC1Option]>, MetaVarName<"">, diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -768,12 +768,14 @@ // Note that we have a user-declared constructor. data().UserDeclaredConstructor = true; - // C++ [class]p4: - // A POD-struct is an aggregate class [...] - // Since the POD bit is meant to be C++03 POD-ness, clear it even if - // the type is technically an aggregate in C++0x since it wouldn't be - // in 03. - data().PlainOldData = false; + if ((!Constructor->isDeleted() && !Constructor->isDefaulted()) || !getLangOpts().DefaultedSMFArePOD) { + // C++ [class]p4: + // A POD-struct is an aggregate class [...] + // Since the POD bit is meant to be C++03 POD-ness, clear it even if + // the type is technically an aggregate in C++0x since it wouldn't be + // in 03. + data().PlainOldData = false; + } } if (Constructor->isDefaultConstructor()) { @@ -921,18 +923,23 @@ if (!Method->isImplicit()) { data().UserDeclaredSpecialMembers |= SMKind; - // C++03 [class]p4: - // A POD-struct is an aggregate class that has [...] no user-defined - // copy assignment operator and no user-defined destructor. - // - // Since the POD bit is meant to be C++03 POD-ness, and in C++03, - // aggregates could not have any constructors, clear it even for an - // explicitly defaulted or deleted constructor. - // type is technically an aggregate in C++0x since it wouldn't be in 03. - // - // Also, a user-declared move assignment operator makes a class non-POD. - // This is an extension in C++03. - data().PlainOldData = false; + if ((!Method->isDeleted() && !Method->isDefaulted() && + SMKind != SMF_MoveAssignment) || + !getLangOpts().DefaultedSMFArePOD) { + // C++03 [class]p4: + // A POD-struct is an aggregate class that has [...] no user-defined + // copy assignment operator and no user-defined destructor. + // + // Since the POD bit is meant to be C++03 POD-ness, and in C++03, + // aggregates could not have any constructors, clear it even for an + // explicitly defaulted or deleted constructor. + // type is technically an aggregate in C++0x since it wouldn't be in + // 03. + // + // Also, a user-declared move assignment operator makes a class + // non-POD. This is an extension in C++03. + data().PlainOldData = false; + } } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5585,6 +5585,25 @@ if (!Triple.isNVPTX() && !Triple.isAMDGCN()) addPGOAndCoverageFlags(TC, C, D, Output, Args, SanitizeArgs, CmdArgs); + bool DefaultedSMFArePOD = !RawTriple.isPS() && !RawTriple.isOSDarwin(); + + if (Arg *A = Args.getLastArg(options::OPT_fclang_abi_compat_EQ)) { + StringRef Ver = A->getValue(); + CmdArgs.push_back(Args.MakeArgString("-fclang-abi-compat=" + Ver)); + unsigned Num; + if (!Ver.consumeInteger(10, Num) && Num <= 13) + DefaultedSMFArePOD = false; + } + + if (Arg *DefaultedSMFArePODArg = + Args.getLastArg(options::OPT_fdefaulted_smf_are_pod, + options::OPT_fno_defaulted_smf_are_pod)) + DefaultedSMFArePOD = DefaultedSMFArePODArg->getOption().matches( + options::OPT_fdefaulted_smf_are_pod); + + if (DefaultedSMFArePOD) + CmdArgs.push_back("-fdefaulted-smf-are-pod"); + Args.AddLastArg(CmdArgs, options::OPT_fclang_abi_compat_EQ); // Add runtime flag for PS4/PS5 when PGO, coverage, or sanitizers are enabled. diff --git a/clang/test/AST/ast-dump-record-definition-data-json.cpp b/clang/test/AST/ast-dump-record-definition-data-json.cpp --- a/clang/test/AST/ast-dump-record-definition-data-json.cpp +++ b/clang/test/AST/ast-dump-record-definition-data-json.cpp @@ -772,6 +772,7 @@ // CHECK-NEXT: "isAggregate": true, // CHECK-NEXT: "isEmpty": true, // CHECK-NEXT: "isLiteral": true, +// CHECK-NEXT: "isPOD": true, // CHECK-NEXT: "isStandardLayout": true, // CHECK-NEXT: "isTriviallyCopyable": true, // CHECK-NEXT: "moveAssign": {}, @@ -2460,6 +2461,7 @@ // 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, @@ -3665,6 +3667,7 @@ // 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, diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -597,6 +597,16 @@ // CHECK_DISABLE_DIRECT: -fobjc-disable-direct-methods-for-testing // CHECK_NO_DISABLE_DIRECT-NOT: -fobjc-disable-direct-methods-for-testing +// RUN: %clang -### %s -fno-defaulted-smf-are-pod 2>&1 | FileCheck --check-prefix=CHECK-NO-DEFAULTED-SMF-ARE-POD %s +// RUN: %clang -### %s 2>&1 | FileCheck --check-prefix=CHECK-DEFAULTED-SMF-ARE-POD %s +// RUN: %clang -### %s -target x86_64-scei-ps4 2>&1 | FileCheck --check-prefix=CHECK-NO-DEFAULTED-SMF-ARE-POD %s +// RUN: %clang -### %s -target x86_64-scei-ps5 2>&1 | FileCheck --check-prefix=CHECK-NO-DEFAULTED-SMF-ARE-POD %s +// RUN: %clang -### %s -target x86_64-scei-ps4 -fdefaulted-smf-are-pod 2>&1 | FileCheck --check-prefix=CHECK-DEFAULTED-SMF-ARE-POD %s +// RUN: %clang -### %s -target x86_64-unknown-darwin 2>&1 | FileCheck --check-prefix=CHECK-NO-DEFAULTED-SMF-ARE-POD %s +// RUN: %clang -### %s -target x86_64-unknown-darwin -fdefaulted-smf-are-pod 2>&1 | FileCheck --check-prefix=CHECK-DEFAULTED-SMF-ARE-POD %s +// CHECK-NO-DEFAULTED-SMF-ARE-POD-NOT: defaulted-smf-are-pod +// CHECK-DEFAULTED-SMF-ARE-POD: -fdefaulted-smf-are-pod + // RUN: %clang -### -S -fjmc -target x86_64-unknown-linux %s 2>&1 | FileCheck -check-prefixes=CHECK_JMC_WARN,CHECK_NOJMC %s // RUN: %clang -### -S -fjmc -target x86_64-pc-windows-msvc %s 2>&1 | FileCheck -check-prefixes=CHECK_JMC_WARN_NOT_ELF,CHECK_NOJMC %s // RUN: %clang -### -S -fjmc -g -target x86_64-unknown-linux %s 2>&1 | FileCheck -check-prefix=CHECK_JMC %s diff --git a/clang/test/SemaCXX/class-layout.cpp b/clang/test/SemaCXX/class-layout.cpp --- a/clang/test/SemaCXX/class-layout.cpp +++ b/clang/test/SemaCXX/class-layout.cpp @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=14 -// RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6 -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6 -// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-c++11-extensions +// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-c++11-extensions -DCLANG_ABI_COMPAT=14 +// RUN: %clang_cc1 -triple x86_64-scei-ps4 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-c++11-extensions -DCLANG_ABI_COMPAT=6 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-c++11-extensions -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6 +// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -Wno-c++11-extensions -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14 // expected-no-diagnostics #define SA(n, p) int a##n[(p) ? 1 : -1] @@ -641,3 +641,21 @@ _Static_assert(_Alignof(t1) == 1, ""); _Static_assert(_Alignof(t2) == 1, ""); } // namespace non_pod_packed + +namespace cxx11_pod { +struct t1 { + t1() = default; + t1(const t1&) = delete; + ~t1() = delete; + t1(t1&&) = default; + int a; +}; +struct t2 { + t1 v1; +} __attribute__((packed)); +#ifdef NO_DEFAULTED_SMF_ARE_POD +_Static_assert(_Alignof(t2) == 4, ""); +#else +_Static_assert(_Alignof(t2) == 1, ""); +#endif +}