From f3ebc866c88b31ab393637e30189d41ddb7f84f0 Mon Sep 17 00:00:00 2001
From: Dimitri van Heesch <doxygen@gmail.com>
Date: Fri, 17 Apr 2020 21:39:13 +0200
Subject: [PATCH] issue #7706: Md5 hash does not match for two different runs

---
 src/memberlist.cpp | 79 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 42 insertions(+), 37 deletions(-)

diff --git a/src/memberlist.cpp b/src/memberlist.cpp
index 8a76a1d..b5377a4 100644
--- a/src/memberlist.cpp
+++ b/src/memberlist.cpp
@@ -1,12 +1,12 @@
 /******************************************************************************
  *
- * 
+ *
  *
  * Copyright (C) 1997-2015 by Dimitri van Heesch.
  *
  * Permission to use, copy, modify, and distribute this software and its
- * documentation under the terms of the GNU General Public License is hereby 
- * granted. No representations are made about the suitability of this software 
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
  * for any purpose. It is provided "as is" without express or implied warranty.
  * See the GNU General Public License for more details.
  *
@@ -63,10 +63,11 @@ MemberList::~MemberList()
   delete memberGroupList;
 }
 
-int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
+static int genericCompareMembers(const MemberDef *c1,const MemberDef *c2)
 {
-  static bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST);
-  if (sortConstructorsFirst) {
+  bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST);
+  if (sortConstructorsFirst)
+  {
     int ord1 = c1->isConstructor() ? 2 : (c1->isDestructor() ? 1 : 0);
     int ord2 = c2->isConstructor() ? 2 : (c2->isDestructor() ? 1 : 0);
     if (ord1 > ord2)
@@ -74,11 +75,19 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
     else if (ord2 > ord1)
       return 1;
   }
+  // sort on name
   int cmp = qstricmp(c1->name(),c2->name());
+  // then on argument list
   if (cmp==0 && c1->argsString() && c2->argsString())
   {
     cmp = qstricmp(c1->argsString(),c2->argsString());
   }
+  // then on file in which the item is defined
+  if (cmp==0)
+  {
+    cmp = qstricmp(c1->getDefFileName(),c2->getDefFileName());
+  }
+  // then on line number at which the member is defined
   if (cmp==0)
   {
     cmp = c1->getDefLine()-c2->getDefLine();
@@ -86,6 +95,11 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
   return cmp;
 }
 
+int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const
+{
+  return genericCompareMembers(c1,c2);
+}
+
 int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const
 {
   int count=0;
@@ -295,7 +309,7 @@ MemberDef *MemberList::take(uint index)
 }
 
 MemberListIterator::MemberListIterator(const MemberList &l) :
-  QListIterator<MemberDef>(l) 
+  QListIterator<MemberDef>(l)
 {
 }
 
@@ -385,9 +399,9 @@ bool MemberList::declVisible() const
         case MemberType_Service:    // fall through
         case MemberType_Sequence:   // fall through
         case MemberType_Dictionary: // fall through
-        case MemberType_Event:  
+        case MemberType_Event:
           return TRUE;
-        case MemberType_Enumeration: 
+        case MemberType_Enumeration:
           {
             // if this is an anonymous enum and there are variables of this
             // enum type (i.e. enumVars>0), then we do not show the enum here.
@@ -399,7 +413,7 @@ bool MemberList::declVisible() const
           break;
         case MemberType_Friend:
           return TRUE;
-        case MemberType_EnumValue: 
+        case MemberType_EnumValue:
           {
             if (m_inGroup)
             {
@@ -431,7 +445,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
   }
   //printf("  --> writePlainDeclaration() numDecMembers()=%d\n",
   //    numDecMembers());
-  
+
   ol.pushGeneratorState();
 
   bool first=TRUE;
@@ -460,13 +474,13 @@ void MemberList::writePlainDeclarations(OutputList &ol,
         case MemberType_Service:     // fall through
         case MemberType_Sequence:    // fall through
         case MemberType_Dictionary:  // fall through
-        case MemberType_Event:  
+        case MemberType_Event:
           {
             if (first) ol.startMemberList(),first=FALSE;
             md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
             break;
           }
-        case MemberType_Enumeration: 
+        case MemberType_Enumeration:
           {
             // if this is an anonymous enum and there are variables of this
             // enum type (i.e. enumVars>0), then we do not show the enum here.
@@ -531,7 +545,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
         case MemberType_Friend:
           if (inheritedFrom==0)
           {
-            if (first) 
+            if (first)
             {
               ol.startMemberList();
               first=FALSE;
@@ -539,7 +553,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
             md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup,inheritedFrom,inheritId);
             break;
           }
-        case MemberType_EnumValue: 
+        case MemberType_EnumValue:
           {
             if (m_inGroup)
             {
@@ -565,7 +579,7 @@ void MemberList::writePlainDeclarations(OutputList &ol,
         //printf("anonymous compound members\n");
         if (md->isBriefSectionVisible())
         {
-          if (first) 
+          if (first)
           {
             ol.startMemberList();
             first=FALSE;
@@ -576,10 +590,10 @@ void MemberList::writePlainDeclarations(OutputList &ol,
       }
     }
   }
- 
-  if (!first) 
+
+  if (!first)
   {
-    ol.endMemberList(); 
+    ol.endMemberList();
   }
 
   ol.popGeneratorState();
@@ -635,7 +649,7 @@ void MemberList::writeDeclarations(OutputList &ol,
       if (title)
       {
         ol.writeInheritedSectionTitle(inheritId,cd->getReference(),
-                                      cd->getOutputFileBase(), 
+                                      cd->getOutputFileBase(),
                                       cd->anchor(),title,cd->displayName());
       }
       ol.popGeneratorState();
@@ -643,7 +657,7 @@ void MemberList::writeDeclarations(OutputList &ol,
   }
   else if (num>numEnumValues)
   {
-    if (title) 
+    if (title)
     {
       if (showInline)
       {
@@ -663,7 +677,7 @@ void MemberList::writeDeclarations(OutputList &ol,
         ol.endMemberHeader();
       }
     }
-    if (subtitle) 
+    if (subtitle)
     {
       QCString st=subtitle;
       st = st.stripWhiteSpace();
@@ -728,7 +742,7 @@ void MemberList::writeDeclarations(OutputList &ol,
       }
     }
   }
-  if (inheritedFrom && cd) 
+  if (inheritedFrom && cd)
   {
     // also add members that of this list type, that are grouped together
     // in a separate list in class 'inheritedFrom'
@@ -772,7 +786,7 @@ void MemberList::writeDocumentation(OutputList &ol,
   overloadCountDict.setAutoDelete(TRUE);
   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
   {
-    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && 
+    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) &&
         !(md->isEnumValue() && !showInline))
     {
       uint *pCount = overloadTotalDict.find(md->name());
@@ -790,7 +804,7 @@ void MemberList::writeDocumentation(OutputList &ol,
 
   for (mli.toFirst() ; (md=mli.current()) ; ++mli)
   {
-    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) && 
+    if (md->isDetailedSectionVisible(m_inGroup,container->definitionType()==Definition::TypeFile) &&
         !(md->isEnumValue() && !showInline))
     {
       uint overloadCount = *overloadTotalDict.find(md->name());
@@ -949,7 +963,7 @@ void MemberList::addListReferences(Definition *def)
         MemberDef *vmd;
         for ( ; (vmd=vmli.current()) ; ++vmli)
         {
-          //printf("   adding %s\n",vmd->name().data());  
+          //printf("   adding %s\n",vmd->name().data());
           vmd->addListReference(def);
         }
       }
@@ -990,7 +1004,7 @@ void MemberList::setNeedsSorting(bool b)
   m_needsSorting = b;
 }
 
-QCString MemberList::listTypeAsString(MemberListType type) 
+QCString MemberList::listTypeAsString(MemberListType type)
 {
   switch(type)
   {
@@ -1087,16 +1101,7 @@ void MemberList::writeTagFile(FTextStream &tagFile)
 
 int MemberSDict::compareValues(const MemberDef *c1, const MemberDef *c2) const
 {
-  //printf("MemberSDict::compareValues(%s,%s)\n",c1->name().data(),c2->name().data());
-  int cmp = qstricmp(c1->name(),c2->name());
-  if (cmp)
-  {
-    return cmp;
-  }
-  else
-  {
-    return c1->getDefLine()-c2->getDefLine();
-  }
+  return genericCompareMembers(c1,c2);
 }
 
 
-- 
1.8.3.1

