|
29 | 29 | #include "clang/AST/TypeLoc.h" |
30 | 30 | #include "clang/AST/UnresolvedSet.h" |
31 | 31 | #include "clang/Basic/Diagnostic.h" |
| 32 | +#include "clang/Basic/DiagnosticSema.h" |
32 | 33 | #include "clang/Basic/IdentifierTable.h" |
33 | 34 | #include "clang/Basic/LLVM.h" |
34 | 35 | #include "clang/Basic/LangOptions.h" |
@@ -81,6 +82,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) |
81 | 82 | HasPrivateFields(false), HasProtectedFields(false), |
82 | 83 | HasPublicFields(false), HasMutableFields(false), HasVariantMembers(false), |
83 | 84 | HasOnlyCMembers(true), HasInitMethod(false), HasInClassInitializer(false), |
| 85 | + HasUninitializedExplicitInitFields(false), |
84 | 86 | HasUninitializedReferenceMember(false), HasUninitializedFields(false), |
85 | 87 | HasInheritedConstructor(false), HasInheritedDefaultConstructor(false), |
86 | 88 | HasInheritedAssignment(false), |
@@ -1111,6 +1113,10 @@ void CXXRecordDecl::addedMember(Decl *D) { |
1111 | 1113 | } else if (!T.isCXX98PODType(Context)) |
1112 | 1114 | data().PlainOldData = false; |
1113 | 1115 |
|
| 1116 | + if (Field->hasAttr<ExplicitInitAttr>() && !Field->hasInClassInitializer()) { |
| 1117 | + data().HasUninitializedExplicitInitFields = true; |
| 1118 | + } |
| 1119 | + |
1114 | 1120 | if (T->isReferenceType()) { |
1115 | 1121 | if (!Field->hasInClassInitializer()) |
1116 | 1122 | data().HasUninitializedReferenceMember = true; |
@@ -1362,6 +1368,10 @@ void CXXRecordDecl::addedMember(Decl *D) { |
1362 | 1368 | if (!FieldRec->hasCopyAssignmentWithConstParam()) |
1363 | 1369 | data().ImplicitCopyAssignmentHasConstParam = false; |
1364 | 1370 |
|
| 1371 | + if (FieldRec->hasUninitializedExplicitInitFields() && |
| 1372 | + FieldRec->isAggregate() && !Field->hasInClassInitializer()) |
| 1373 | + data().HasUninitializedExplicitInitFields = true; |
| 1374 | + |
1365 | 1375 | if (FieldRec->hasUninitializedReferenceMember() && |
1366 | 1376 | !Field->hasInClassInitializer()) |
1367 | 1377 | data().HasUninitializedReferenceMember = true; |
@@ -2148,6 +2158,19 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { |
2148 | 2158 | for (conversion_iterator I = conversion_begin(), E = conversion_end(); |
2149 | 2159 | I != E; ++I) |
2150 | 2160 | I.setAccess((*I)->getAccess()); |
| 2161 | + |
| 2162 | + ASTContext &Context = getASTContext(); |
| 2163 | + if (!Context.getLangOpts().CPlusPlus20 && hasUserDeclaredConstructor()) { |
| 2164 | + // Diagnose any aggregate behavior changes in C++20 |
| 2165 | + for (field_iterator I = field_begin(), E = field_end(); I != E; ++I) { |
| 2166 | + if (const auto *attr = I->getAttr<ExplicitInitAttr>()) { |
| 2167 | + Context.getDiagnostics().Report( |
| 2168 | + getLocation(), |
| 2169 | + diag::warn_cxx20_compat_requires_explicit_init_non_aggregate) |
| 2170 | + << attr->getRange() << Context.getRecordType(this); |
| 2171 | + } |
| 2172 | + } |
| 2173 | + } |
2151 | 2174 | } |
2152 | 2175 |
|
2153 | 2176 | bool CXXRecordDecl::mayBeAbstract() const { |
|
0 commit comments