diff options
author | Richard Trieu <rtrieu@google.com> | 2014-09-23 22:52:42 +0000 |
---|---|---|
committer | Richard Trieu <rtrieu@google.com> | 2014-09-23 22:52:42 +0000 |
commit | e396ba6bb0807e29c5b058b350ff00b181076626 (patch) | |
tree | 78f9ecc375b3203ebe92a8e8f36c760d9332d7be /clang/lib/Sema/SemaDecl.cpp | |
parent | df2e4218453706c1720d28d342dc20e3507b73ee (diff) | |
download | bcm5719-llvm-e396ba6bb0807e29c5b058b350ff00b181076626.tar.gz bcm5719-llvm-e396ba6bb0807e29c5b058b350ff00b181076626.zip |
Improve -Wuninitialized to take into account field ordering with initializer
lists. Since the fields are inititalized one at a time, using a field with
lower index to initialize a higher indexed field should not be warned on.
llvm-svn: 218339
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 88 |
1 files changed, 87 insertions, 1 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ae79720e383..b3098abbb09 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8240,6 +8240,8 @@ namespace { bool isPODType; bool isReferenceType; + bool isInitList; + llvm::SmallVector<unsigned, 4> InitFieldIndex; public: typedef EvaluatedExprVisitor<SelfReferenceChecker> Inherited; @@ -8248,6 +8250,7 @@ namespace { isPODType = false; isRecordType = false; isReferenceType = false; + isInitList = false; if (ValueDecl *VD = dyn_cast<ValueDecl>(OrigDecl)) { isPODType = VD->getType().isPODType(S.Context); isRecordType = VD->getType()->isRecordType(); @@ -8255,6 +8258,78 @@ namespace { } } + // For most expressions, just call the visitor. For initializer lists, + // track the index of the field being initialized since fields are + // initialized in order allowing use of previously initialized fields. + void CheckExpr(Expr *E) { + InitListExpr *InitList = dyn_cast<InitListExpr>(E); + if (!InitList) { + Visit(E); + return; + } + + // Track and increment the index here. + isInitList = true; + InitFieldIndex.push_back(0); + for (auto Child : InitList->children()) { + CheckExpr(cast<Expr>(Child)); + ++InitFieldIndex.back(); + } + InitFieldIndex.pop_back(); + } + + // Returns true if MemberExpr is checked and no futher checking is needed. + // Returns false if additional checking is required. + bool CheckInitListMemberExpr(MemberExpr *E, bool CheckReference) { + llvm::SmallVector<FieldDecl*, 4> Fields; + Expr *Base = E; + bool ReferenceField = false; + + // Get the field memebers used. + while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) { + FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()); + if (!FD) + return false; + Fields.push_back(FD); + if (FD->getType()->isReferenceType()) + ReferenceField = true; + Base = ME->getBase()->IgnoreParenImpCasts(); + } + + // Keep checking only if the base Decl is the same. + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base); + if (!DRE || DRE->getDecl() != OrigDecl) + return false; + + // A reference field can be bound to an unininitialized field. + if (CheckReference && !ReferenceField) + return true; + + // Convert FieldDecls to their index number. + llvm::SmallVector<unsigned, 4> UsedFieldIndex; + for (auto I = Fields.rbegin(), E = Fields.rend(); I != E; ++I) { + UsedFieldIndex.push_back((*I)->getFieldIndex()); + } + + // See if a warning is needed by checking the first difference in index + // numbers. If field being used has index less than the field being + // initialized, then the use is safe. + for (auto UsedIter = UsedFieldIndex.begin(), + UsedEnd = UsedFieldIndex.end(), + OrigIter = InitFieldIndex.begin(), + OrigEnd = InitFieldIndex.end(); + UsedIter != UsedEnd && OrigIter != OrigEnd; ++UsedIter, ++OrigIter) { + if (*UsedIter < *OrigIter) + return true; + if (*UsedIter > *OrigIter) + break; + } + + // TODO: Add a different warning which will print the field names. + HandleDeclRefExpr(DRE); + return true; + } + // For most expressions, the cast is directly above the DeclRefExpr. // For conditional operators, the cast can be outside the conditional // operator if both expressions are DeclRefExpr's. @@ -8290,6 +8365,12 @@ namespace { } if (isa<MemberExpr>(E)) { + if (isInitList) { + if (CheckInitListMemberExpr(cast<MemberExpr>(E), + false /*CheckReference*/)) + return; + } + Expr *Base = E->IgnoreParenImpCasts(); while (MemberExpr *ME = dyn_cast<MemberExpr>(Base)) { // Check for static member variables and don't warn on them. @@ -8323,6 +8404,11 @@ namespace { } void VisitMemberExpr(MemberExpr *E) { + if (isInitList) { + if (CheckInitListMemberExpr(E, true /*CheckReference*/)) + return; + } + // Don't warn on arrays since they can be treated as pointers. if (E->getType()->canDecayToPointerType()) return; @@ -8439,7 +8525,7 @@ namespace { if (DRE->getDecl() == OrigDecl) return; - SelfReferenceChecker(S, OrigDecl).Visit(E); + SelfReferenceChecker(S, OrigDecl).CheckExpr(E); } } |