@@ -2237,6 +2237,9 @@ namespace {
2237
2237
// List of Decls to generate a warning on. Also remove Decls that become
2238
2238
// initialized.
2239
2239
llvm::SmallPtrSetImpl<ValueDecl*> &Decls;
2240
+ // List of base classes of the record. Classes are removed after their
2241
+ // initializers.
2242
+ llvm::SmallPtrSetImpl<QualType> &BaseClasses;
2240
2243
// Vector of decls to be removed from the Decl set prior to visiting the
2241
2244
// nodes. These Decls may have been initialized in the prior initializer.
2242
2245
llvm::SmallVector<ValueDecl*, 4> DeclsToRemove;
@@ -2252,9 +2255,10 @@ namespace {
2252
2255
public:
2253
2256
typedef EvaluatedExprVisitor<UninitializedFieldVisitor> Inherited;
2254
2257
UninitializedFieldVisitor(Sema &S,
2255
- llvm::SmallPtrSetImpl<ValueDecl*> &Decls)
2256
- : Inherited(S.Context), S(S), Decls(Decls), Constructor(nullptr),
2257
- InitList(false), InitListFieldDecl(nullptr) {}
2258
+ llvm::SmallPtrSetImpl<ValueDecl*> &Decls,
2259
+ llvm::SmallPtrSetImpl<QualType> &BaseClasses)
2260
+ : Inherited(S.Context), S(S), Decls(Decls), BaseClasses(BaseClasses),
2261
+ Constructor(nullptr), InitList(false), InitListFieldDecl(nullptr) {}
2258
2262
2259
2263
// Returns true if the use of ME is not an uninitialized use.
2260
2264
bool IsInitListMemberExprInitialized(MemberExpr *ME,
@@ -2309,7 +2313,8 @@ namespace {
2309
2313
bool AllPODFields = FieldME->getType().isPODType(S.Context);
2310
2314
2311
2315
Expr *Base = ME;
2312
- while (MemberExpr *SubME = dyn_cast<MemberExpr>(Base)) {
2316
+ while (MemberExpr *SubME =
2317
+ dyn_cast<MemberExpr>(Base->IgnoreParenImpCasts())) {
2313
2318
2314
2319
if (isa<VarDecl>(SubME->getMemberDecl()))
2315
2320
return;
@@ -2321,17 +2326,32 @@ namespace {
2321
2326
if (!FieldME->getType().isPODType(S.Context))
2322
2327
AllPODFields = false;
2323
2328
2324
- Base = SubME->getBase()->IgnoreParenImpCasts() ;
2329
+ Base = SubME->getBase();
2325
2330
}
2326
2331
2327
- if (!isa<CXXThisExpr>(Base))
2332
+ if (!isa<CXXThisExpr>(Base->IgnoreParenImpCasts() ))
2328
2333
return;
2329
2334
2330
2335
if (AddressOf && AllPODFields)
2331
2336
return;
2332
2337
2333
2338
ValueDecl* FoundVD = FieldME->getMemberDecl();
2334
2339
2340
+ if (ImplicitCastExpr *BaseCast = dyn_cast<ImplicitCastExpr>(Base)) {
2341
+ while (isa<ImplicitCastExpr>(BaseCast->getSubExpr())) {
2342
+ BaseCast = cast<ImplicitCastExpr>(BaseCast->getSubExpr());
2343
+ }
2344
+
2345
+ if (BaseCast->getCastKind() == CK_UncheckedDerivedToBase) {
2346
+ QualType T = BaseCast->getType();
2347
+ if (T->isPointerType() &&
2348
+ BaseClasses.count(T->getPointeeType())) {
2349
+ S.Diag(FieldME->getExprLoc(), diag::warn_base_class_is_uninit)
2350
+ << T->getPointeeType() << FoundVD;
2351
+ }
2352
+ }
2353
+ }
2354
+
2335
2355
if (!Decls.count(FoundVD))
2336
2356
return;
2337
2357
@@ -2420,7 +2440,7 @@ namespace {
2420
2440
}
2421
2441
2422
2442
void CheckInitializer(Expr *E, const CXXConstructorDecl *FieldConstructor,
2423
- FieldDecl *Field) {
2443
+ FieldDecl *Field, const Type *BaseClass ) {
2424
2444
// Remove Decls that may have been initialized in the previous
2425
2445
// initializer.
2426
2446
for (ValueDecl* VD : DeclsToRemove)
@@ -2442,6 +2462,8 @@ namespace {
2442
2462
2443
2463
if (Field)
2444
2464
Decls.erase(Field);
2465
+ if (BaseClass)
2466
+ BaseClasses.erase(BaseClass->getCanonicalTypeInternal());
2445
2467
}
2446
2468
2447
2469
void VisitMemberExpr(MemberExpr *ME) {
@@ -2578,14 +2600,19 @@ namespace {
2578
2600
}
2579
2601
}
2580
2602
2581
- if (UninitializedFields.empty())
2603
+ llvm::SmallPtrSet<QualType, 4> UninitializedBaseClasses;
2604
+ for (auto I : RD->bases())
2605
+ UninitializedBaseClasses.insert(I.getType().getCanonicalType());
2606
+
2607
+ if (UninitializedFields.empty() && UninitializedBaseClasses.empty())
2582
2608
return;
2583
2609
2584
2610
UninitializedFieldVisitor UninitializedChecker(SemaRef,
2585
- UninitializedFields);
2611
+ UninitializedFields,
2612
+ UninitializedBaseClasses);
2586
2613
2587
2614
for (const auto *FieldInit : Constructor->inits()) {
2588
- if (UninitializedFields.empty())
2615
+ if (UninitializedFields.empty() && UninitializedBaseClasses.empty() )
2589
2616
break;
2590
2617
2591
2618
Expr *InitExpr = FieldInit->getInit();
@@ -2599,10 +2626,12 @@ namespace {
2599
2626
continue;
2600
2627
// In class initializers will point to the constructor.
2601
2628
UninitializedChecker.CheckInitializer(InitExpr, Constructor,
2602
- FieldInit->getAnyMember());
2629
+ FieldInit->getAnyMember(),
2630
+ FieldInit->getBaseClass());
2603
2631
} else {
2604
2632
UninitializedChecker.CheckInitializer(InitExpr, nullptr,
2605
- FieldInit->getAnyMember());
2633
+ FieldInit->getAnyMember(),
2634
+ FieldInit->getBaseClass());
2606
2635
}
2607
2636
}
2608
2637
}
0 commit comments