]> granicus.if.org Git - clang/commitdiff
Move the uninitialized field check to after all the field initializers are added
authorRichard Trieu <rtrieu@google.com>
Mon, 16 Sep 2013 21:54:53 +0000 (21:54 +0000)
committerRichard Trieu <rtrieu@google.com>
Mon, 16 Sep 2013 21:54:53 +0000 (21:54 +0000)
to the CXXConstructorDecl so that information from the constructor can be used.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190810 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp

index d9279533b43ef59d5733afdb1ec5ab3064a114e9..dc33f2faf657ef8c88f853b50fca00b8c3be16cd 100644 (file)
@@ -2624,23 +2624,6 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init,
     Init = MemberInit.get();
   }
 
-  // Diagnose value-uses of fields to initialize themselves, e.g.
-  //   foo(foo)
-  // where foo is not also a parameter to the constructor.
-  // TODO: implement -Wuninitialized and fold this into that framework.
-  // FIXME: Warn about the case when other fields are used before being
-  // initialized. For example, let this field be the i'th field. When
-  // initializing the i'th field, throw a warning if any of the >= i'th
-  // fields are used, as they are not yet initialized.
-  // Right now we are only handling the case where the i'th field uses
-  // itself in its initializer.
-  // Also need to take into account that some fields may be initialized by
-  // in-class initializers, see C++11 [class.base.init]p9.
-  if (getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit, IdLoc)
-      != DiagnosticsEngine::Ignored) {
-    CheckInitExprContainsUninitializedFields(*this, Init, Member);
-  }
-
   if (DirectMember) {
     return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc,
                                             InitRange.getBegin(), Init,
@@ -3707,6 +3690,43 @@ bool CheckRedundantUnionInit(Sema &S,
 }
 }
 
+// Diagnose value-uses of fields to initialize themselves, e.g.
+//   foo(foo)
+// where foo is not also a parameter to the constructor.
+// TODO: implement -Wuninitialized and fold this into that framework.
+// FIXME: Warn about the case when other fields are used before being
+// initialized. For example, let this field be the i'th field. When
+// initializing the i'th field, throw a warning if any of the >= i'th
+// fields are used, as they are not yet initialized.
+// Right now we are only handling the case where the i'th field uses
+// itself in its initializer.
+// Also need to take into account that some fields may be initialized by
+// in-class initializers, see C++11 [class.base.init]p9.
+static void DiagnoseUnitializedFields(
+    Sema &SemaRef, const CXXConstructorDecl *Constructor) {
+
+  if (SemaRef.getDiagnostics().getDiagnosticLevel(diag::warn_field_is_uninit,
+                                                  Constructor->getLocation())
+      == DiagnosticsEngine::Ignored) {
+    return;
+  }
+
+  for (CXXConstructorDecl::init_const_iterator
+           FieldInit = Constructor->init_begin(),
+           FieldInitEnd = Constructor->init_end();
+       FieldInit != FieldInitEnd; ++FieldInit) {
+
+    FieldDecl *FD = (*FieldInit)->getAnyMember();
+    if (!FD)
+      continue;
+    Expr *InitExpr = (*FieldInit)->getInit();
+
+    if (!isa<CXXDefaultInitExpr>(InitExpr)) {
+      CheckInitExprContainsUninitializedFields(SemaRef, InitExpr, FD);
+    }
+  }
+}
+
 /// ActOnMemInitializers - Handle the member initializers for a constructor.
 void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
                                 SourceLocation ColonLoc,
@@ -3771,6 +3791,8 @@ void Sema::ActOnMemInitializers(Decl *ConstructorDecl,
   DiagnoseBaseOrMemInitializerOrder(*this, Constructor, MemInits);
 
   SetCtorInitializers(Constructor, AnyErrors, MemInits);
+
+  DiagnoseUnitializedFields(*this, Constructor);
 }
 
 void