Diagnose misordered initializers in constructor templates immediately instead of
when they're instantiated.  Merge the note into the -Wreorder warning;  it
doesn't really contribute much, and it was splitting a thought across diagnostics
anyway.  Don't crash in the parser when a constructor's initializers end in a
comma and there's no body;  the recovery here is still terrible, but anything's
better than a crash.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100922 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 87e22fa..5b54524 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -217,12 +217,17 @@
              "ParseFunctionTryBlock left tokens in the token stream!");
       continue;
     }
-    if (Tok.is(tok::colon))
+    if (Tok.is(tok::colon)) {
       ParseConstructorInitializer(LM.D);
-    else
+
+      // Error recovery.
+      if (!Tok.is(tok::l_brace)) {
+        Actions.ActOnFinishFunctionBody(LM.D, Action::StmtArg(Actions));
+        continue;
+      }
+    } else
       Actions.ActOnDefaultCtorInitializers(LM.D);
 
-    // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??
     ParseFunctionStatementBody(LM.D);
     assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc,
                                                            Tok.getLocation()) &&
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index 5c31c1d..6dbb99e 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -668,9 +668,15 @@
 
   // If we have a colon, then we're probably parsing a C++
   // ctor-initializer.
-  if (Tok.is(tok::colon))
+  if (Tok.is(tok::colon)) {
     ParseConstructorInitializer(Res);
-  else
+
+    // Recover from error.
+    if (!Tok.is(tok::l_brace)) {
+      Actions.ActOnFinishFunctionBody(Res, Action::StmtArg(Actions));
+      return Res;
+    }
+  } else
     Actions.ActOnDefaultCtorInitializers(Res);
 
   return ParseFunctionStatementBody(Res);
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 3eb8713..bc8b7d6 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1433,7 +1433,7 @@
                                   CXXBaseOrMemberInitializer **Initializers,
                                   unsigned NumInitializers,
                                   bool AnyErrors) {
-  if (Constructor->isDependentContext()) {
+  if (Constructor->getDeclContext()->isDependentContext()) {
     // Just store the initializers as written, they will be checked during
     // instantiation.
     if (NumInitializers > 0) {
@@ -1672,86 +1672,85 @@
 static void
 DiagnoseBaseOrMemInitializerOrder(Sema &SemaRef,
                                   const CXXConstructorDecl *Constructor,
-                                  CXXBaseOrMemberInitializer **MemInits,
-                                  unsigned NumMemInits) {
-  if (Constructor->isDependentContext())
+                                  CXXBaseOrMemberInitializer **Inits,
+                                  unsigned NumInits) {
+  if (Constructor->getDeclContext()->isDependentContext())
     return;
 
-  if (SemaRef.Diags.getDiagnosticLevel(diag::warn_base_initialized) ==
-      Diagnostic::Ignored &&
-      SemaRef.Diags.getDiagnosticLevel(diag::warn_field_initialized) ==
-      Diagnostic::Ignored)
+  if (SemaRef.Diags.getDiagnosticLevel(diag::warn_initializer_out_of_order)
+        == Diagnostic::Ignored)
     return;
   
-  // Also issue warning if order of ctor-initializer list does not match order
-  // of 1) base class declarations and 2) order of non-static data members.
-  llvm::SmallVector<const void*, 32> AllBaseOrMembers;
+  // Build the list of bases and members in the order that they'll
+  // actually be initialized.  The explicit initializers should be in
+  // this same order but may be missing things.
+  llvm::SmallVector<const void*, 32> IdealInitKeys;
 
   const CXXRecordDecl *ClassDecl = Constructor->getParent();
 
-  // Push virtual bases before others.
+  // 1. Virtual bases.
   for (CXXRecordDecl::base_class_const_iterator VBase =
        ClassDecl->vbases_begin(),
        E = ClassDecl->vbases_end(); VBase != E; ++VBase)
-    AllBaseOrMembers.push_back(GetKeyForBase(SemaRef.Context,
-                                             VBase->getType()));
+    IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, VBase->getType()));
 
+  // 2. Non-virtual bases.
   for (CXXRecordDecl::base_class_const_iterator Base = ClassDecl->bases_begin(),
        E = ClassDecl->bases_end(); Base != E; ++Base) {
-    // Virtuals are alread in the virtual base list and are constructed
-    // first.
     if (Base->isVirtual())
       continue;
-    AllBaseOrMembers.push_back(GetKeyForBase(SemaRef.Context,
-                                             Base->getType()));
+    IdealInitKeys.push_back(GetKeyForBase(SemaRef.Context, Base->getType()));
   }
 
+  // 3. Direct fields.
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
        E = ClassDecl->field_end(); Field != E; ++Field)
-    AllBaseOrMembers.push_back(GetKeyForTopLevelField(*Field));
+    IdealInitKeys.push_back(GetKeyForTopLevelField(*Field));
 
-  int Last = AllBaseOrMembers.size();
-  int curIndex = 0;
-  CXXBaseOrMemberInitializer *PrevMember = 0;
-  for (unsigned i = 0; i < NumMemInits; i++) {
-    CXXBaseOrMemberInitializer *Member = MemInits[i];
-    void *MemberInCtorList = GetKeyForMember(SemaRef.Context, Member, true);
+  unsigned NumIdealInits = IdealInitKeys.size();
+  unsigned IdealIndex = 0;
 
-    for (; curIndex < Last; curIndex++)
-      if (MemberInCtorList == AllBaseOrMembers[curIndex])
+  CXXBaseOrMemberInitializer *PrevInit = 0;
+  for (unsigned InitIndex = 0; InitIndex != NumInits; ++InitIndex) {
+    CXXBaseOrMemberInitializer *Init = Inits[InitIndex];
+    void *InitKey = GetKeyForMember(SemaRef.Context, Init, true);
+
+    // Scan forward to try to find this initializer in the idealized
+    // initializers list.
+    for (; IdealIndex != NumIdealInits; ++IdealIndex)
+      if (InitKey == IdealInitKeys[IdealIndex])
         break;
-    if (curIndex == Last) {
-      assert(PrevMember && "Member not in member list?!");
-      // Initializer as specified in ctor-initializer list is out of order.
-      // Issue a warning diagnostic.
-      if (PrevMember->isBaseInitializer()) {
-        // Diagnostics is for an initialized base class.
-        Type *BaseClass = PrevMember->getBaseClass();
-        SemaRef.Diag(PrevMember->getSourceLocation(),
-                     diag::warn_base_initialized)
-          << QualType(BaseClass, 0);
-      } else {
-        FieldDecl *Field = PrevMember->getMember();
-        SemaRef.Diag(PrevMember->getSourceLocation(),
-                     diag::warn_field_initialized)
-          << Field->getNameAsString();
-      }
-      // Also the note!
-      if (FieldDecl *Field = Member->getMember())
-        SemaRef.Diag(Member->getSourceLocation(),
-                     diag::note_fieldorbase_initialized_here) << 0
-          << Field->getNameAsString();
-      else {
-        Type *BaseClass = Member->getBaseClass();
-        SemaRef.Diag(Member->getSourceLocation(),
-             diag::note_fieldorbase_initialized_here) << 1
-          << QualType(BaseClass, 0);
-      }
-      for (curIndex = 0; curIndex < Last; curIndex++)
-        if (MemberInCtorList == AllBaseOrMembers[curIndex])
+
+    // If we didn't find this initializer, it must be because we
+    // scanned past it on a previous iteration.  That can only
+    // happen if we're out of order;  emit a warning.
+    if (IdealIndex == NumIdealInits) {
+      assert(PrevInit && "initializer not found in initializer list");
+
+      Sema::SemaDiagnosticBuilder D =
+        SemaRef.Diag(PrevInit->getSourceLocation(),
+                     diag::warn_initializer_out_of_order);
+
+      if (PrevInit->isMemberInitializer())
+        D << 0 << PrevInit->getMember()->getDeclName();
+      else
+        D << 1 << PrevInit->getBaseClassInfo()->getType();
+      
+      if (Init->isMemberInitializer())
+        D << 0 << Init->getMember()->getDeclName();
+      else
+        D << 1 << Init->getBaseClassInfo()->getType();
+
+      // Move back to the initializer's location in the ideal list.
+      for (IdealIndex = 0; IdealIndex != NumIdealInits; ++IdealIndex)
+        if (InitKey == IdealInitKeys[IdealIndex])
           break;
+
+      assert(IdealIndex != NumIdealInits &&
+             "initializer not found in initializer list");
     }
-    PrevMember = Member;
+
+    PrevInit = Init;
   }
 }