diff options
author | Nick Lewycky <nicholas@mxc.ca> | 2010-06-15 07:32:55 +0000 |
---|---|---|
committer | Nick Lewycky <nicholas@mxc.ca> | 2010-06-15 07:32:55 +0000 |
commit | 43ad182474fac1e9d68ea4d1bcb80f8f9720245d (patch) | |
tree | d4ab4cf4f6cdc4060d5c156b656ae54236901d58 | |
parent | 88318139c94cef1a77cce969613bbc0745d7e99f (diff) |
When analyzing for member self-assignment, don't attempt to dereference null
Stmt* such as those which occur in ?: . Fixes PR7378.
Also, generally whip the code into shape fixing several coding style violations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105992 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 7dcda88407..aa2be17824 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1217,18 +1217,25 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, /// containing the field that is being initialized. Returns true if there is an /// uninitialized field was used an updates the SourceLocation parameter; false /// otherwise. -static bool InitExprContainsUninitializedFields(const Stmt* S, - const FieldDecl* LhsField, - SourceLocation* L) { - const MemberExpr* ME = dyn_cast<MemberExpr>(S); - if (ME) { - const NamedDecl* RhsField = ME->getMemberDecl(); +static bool InitExprContainsUninitializedFields(const Stmt *S, + const FieldDecl *LhsField, + SourceLocation *L) { + if (isa<CallExpr>(S)) { + // Do not descend into function calls or constructors, as the use + // of an uninitialized field may be valid. One would have to inspect + // the contents of the function/ctor to determine if it is safe or not. + // i.e. Pass-by-value is never safe, but pass-by-reference and pointers + // may be safe, depending on what the function/ctor does. + return false; + } + if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) { + const NamedDecl *RhsField = ME->getMemberDecl(); if (RhsField == LhsField) { // Initializing a field with itself. Throw a warning. // But wait; there are exceptions! // Exception #1: The field may not belong to this record. // e.g. Foo(const Foo& rhs) : A(rhs.A) {} - const Expr* base = ME->getBase(); + const Expr *base = ME->getBase(); if (base != NULL && !isa<CXXThisExpr>(base->IgnoreParenCasts())) { // Even though the field matches, it does not belong to this record. return false; @@ -1239,21 +1246,16 @@ static bool InitExprContainsUninitializedFields(const Stmt* S, return true; } } - bool found = false; - for (Stmt::const_child_iterator it = S->child_begin(); - it != S->child_end() && found == false; - ++it) { - if (isa<CallExpr>(S)) { - // Do not descend into function calls or constructors, as the use - // of an uninitialized field may be valid. One would have to inspect - // the contents of the function/ctor to determine if it is safe or not. - // i.e. Pass-by-value is never safe, but pass-by-reference and pointers - // may be safe, depending on what the function/ctor does. + for (Stmt::const_child_iterator it = S->child_begin(), e = S->child_end(); + it != e; ++it) { + if (!*it) { + // An expression such as 'member(arg ?: "")' may trigger this. continue; } - found = InitExprContainsUninitializedFields(*it, LhsField, L); + if (InitExprContainsUninitializedFields(*it, LhsField, L)) + return true; } - return found; + return false; } Sema::MemInitResult |