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/SemaDeclCXX.cpp | |
| 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/SemaDeclCXX.cpp')
| -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 | 

