]> granicus.if.org Git - clang/commitdiff
When analyzing for member self-assignment, don't attempt to dereference null
authorNick Lewycky <nicholas@mxc.ca>
Tue, 15 Jun 2010 07:32:55 +0000 (07:32 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Tue, 15 Jun 2010 07:32:55 +0000 (07:32 +0000)
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

lib/Sema/SemaDeclCXX.cpp

index 7dcda884076a04fc0738b68fa5fed68aaf2d39f1..aa2be178249639750e9bb3a6d623d2deec2f87b0 100644 (file)
@@ -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 Exprbase = 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