|
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/DiagnosticAST.h" |
32 | 33 | #include "clang/Basic/IdentifierTable.h" |
33 | 34 | #include "clang/Basic/LLVM.h" |
34 | 35 | #include "clang/Basic/LangOptions.h" |
@@ -457,6 +458,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, |
457 | 458 | if (BaseClassDecl->hasMutableFields()) |
458 | 459 | data().HasMutableFields = true; |
459 | 460 |
|
| 461 | + if (BaseClassDecl->hasUninitializedExplicitInitFields() && |
| 462 | + BaseClassDecl->isAggregate()) |
| 463 | + setHasUninitializedExplicitInitFields(true); |
| 464 | + |
460 | 465 | if (BaseClassDecl->hasUninitializedReferenceMember()) |
461 | 466 | data().HasUninitializedReferenceMember = true; |
462 | 467 |
|
@@ -1113,6 +1118,9 @@ void CXXRecordDecl::addedMember(Decl *D) { |
1113 | 1118 | } else if (!T.isCXX98PODType(Context)) |
1114 | 1119 | data().PlainOldData = false; |
1115 | 1120 |
|
| 1121 | + if (Field->hasAttr<ExplicitInitAttr>()) |
| 1122 | + setHasUninitializedExplicitInitFields(true); |
| 1123 | + |
1116 | 1124 | if (T->isReferenceType()) { |
1117 | 1125 | if (!Field->hasInClassInitializer()) |
1118 | 1126 | data().HasUninitializedReferenceMember = true; |
@@ -1372,6 +1380,10 @@ void CXXRecordDecl::addedMember(Decl *D) { |
1372 | 1380 | if (!FieldRec->hasCopyAssignmentWithConstParam()) |
1373 | 1381 | data().ImplicitCopyAssignmentHasConstParam = false; |
1374 | 1382 |
|
| 1383 | + if (FieldRec->hasUninitializedExplicitInitFields() && |
| 1384 | + FieldRec->isAggregate()) |
| 1385 | + setHasUninitializedExplicitInitFields(true); |
| 1386 | + |
1375 | 1387 | if (FieldRec->hasUninitializedReferenceMember() && |
1376 | 1388 | !Field->hasInClassInitializer()) |
1377 | 1389 | data().HasUninitializedReferenceMember = true; |
@@ -2188,6 +2200,33 @@ void CXXRecordDecl::completeDefinition(CXXFinalOverriderMap *FinalOverriders) { |
2188 | 2200 | for (conversion_iterator I = conversion_begin(), E = conversion_end(); |
2189 | 2201 | I != E; ++I) |
2190 | 2202 | I.setAccess((*I)->getAccess()); |
| 2203 | + |
| 2204 | + ASTContext &Context = getASTContext(); |
| 2205 | + |
| 2206 | + if (isAggregate() && hasUserDeclaredConstructor() && |
| 2207 | + !Context.getLangOpts().CPlusPlus20) { |
| 2208 | + // Diagnose any aggregate behavior changes in C++20 |
| 2209 | + for (const FieldDecl *FD : fields()) { |
| 2210 | + if (const auto *AT = FD->getAttr<ExplicitInitAttr>()) |
| 2211 | + Context.getDiagnostics().Report( |
| 2212 | + AT->getLocation(), |
| 2213 | + diag::warn_cxx20_compat_requires_explicit_init_non_aggregate) |
| 2214 | + << AT << FD << Context.getRecordType(this); |
| 2215 | + } |
| 2216 | + } |
| 2217 | + |
| 2218 | + if (!isAggregate() && hasUninitializedExplicitInitFields()) { |
| 2219 | + // Diagnose any fields that required explicit initialization in a |
| 2220 | + // non-aggregate type. (Note that the fields may not be directly in this |
| 2221 | + // type, but in a subobject. In such cases we don't emit diagnoses here.) |
| 2222 | + for (const FieldDecl *FD : fields()) { |
| 2223 | + if (const auto *AT = FD->getAttr<ExplicitInitAttr>()) |
| 2224 | + Context.getDiagnostics().Report(AT->getLocation(), |
| 2225 | + diag::warn_attribute_needs_aggregate) |
| 2226 | + << AT << Context.getRecordType(this); |
| 2227 | + } |
| 2228 | + setHasUninitializedExplicitInitFields(false); |
| 2229 | + } |
2191 | 2230 | } |
2192 | 2231 |
|
2193 | 2232 | bool CXXRecordDecl::mayBeAbstract() const { |
|
0 commit comments