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 | a2fb98bfdae228cb6efb2d439524464cdcc6769d (patch) | |
| tree | 81156ca322f57211318eee1f101b06ae60acb1c4 /clang/lib/Sema | |
| parent | a55b8877e60258c4c983845a5999e26e7ede7bc8 (diff) | |
| download | bcm5719-llvm-a2fb98bfdae228cb6efb2d439524464cdcc6769d.tar.gz bcm5719-llvm-a2fb98bfdae228cb6efb2d439524464cdcc6769d.zip | |
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.
llvm-svn: 105992
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 40 |
1 files changed, 21 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7dcda884076..aa2be178249 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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 |

