From a7bb8edbadced902a3e5a934773c7cae725811d2 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Thu, 19 Oct 2023 10:38:11 +0200
Subject: [PATCH] COMP: avoid issues with new compilers and/or new C++
 standards

- prevent automatic comparison rewriting (c++20)
- no bitwise operations between different enumerations
- template instantiation

ENH: add DimensionedField Internal typedef (simplifies handling)
---
 .../db/IOstreams/memory/ISpanStream.H         |  2 +-
 .../DimensionedField/DimensionedField.H       |  5 +-
 .../GeometricField/GeometricBoundaryField.H   |  5 +
 .../GeometricField/GeometricField.H           | 20 ++--
 .../basic/value/valuePointPatchField.H        | 37 +++-----
 .../pointPatchField/pointPatchField.H         | 11 ++-
 .../faPatchFields/faPatchField/faPatchField.H |  5 +
 .../faePatchField/faePatchField.H             |  5 +
 .../scaledFixedValueFvPatchField.H            | 15 ++-
 .../fvPatchFields/fvPatchField/fvPatchField.H |  5 +
 .../fvsPatchField/fvsPatchField.H             |  5 +
 .../surfaceFieldValue/surfaceFieldValue.H     | 18 ++--
 .../surfaceFieldValueTemplates.C              |  5 +-
 .../fieldValues/volFieldValue/volFieldValue.H | 18 ++--
 .../volFieldValue/volFieldValueTemplates.C    |  5 +-
 .../icoUncoupledKinematicCloud.H              |  2 +-
 .../MeshedSurfaceProxy/MeshedSurfaceProxy.H   | 94 ++++++++-----------
 .../MeshedSurfaceProxy/MeshedSurfaceProxys.C  |  5 +-
 18 files changed, 139 insertions(+), 123 deletions(-)

diff --git a/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H b/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H
index f2debfeb69c..8f89db282c3 100644
--- a/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H
+++ b/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H
@@ -122,7 +122,7 @@ public:
         explicit ispanstream(std::string_view s)
         {
             buffer_type(const_cast<char*>(s.data()), s.size()),
-            stream_type(static_cast<buffer_type*>(this))
+            stream_type(static_cast<buffer_type*>(this));
         }
         #endif
 
diff --git a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H
index 1fa77ed1ed7..e18bd871605 100644
--- a/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H
+++ b/src/OpenFOAM/fields/DimensionedFields/DimensionedField/DimensionedField.H
@@ -83,9 +83,12 @@ public:
 
     // Public Typedefs
 
-        //- Type of mesh on which this DimensionedField is instantiated
+        //- The mesh type for the DimensionedField
         typedef typename GeoMesh::Mesh Mesh;
 
+        //- The DimensionedField is usually synonymous with an internal field
+        typedef DimensionedField<Type, GeoMesh> Internal;
+
         //- Type of the field from which this DimensionedField is derived
         typedef Field<Type> FieldType;
 
diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricBoundaryField.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricBoundaryField.H
index e2b52abb9e1..1af12e769d4 100644
--- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricBoundaryField.H
+++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricBoundaryField.H
@@ -214,6 +214,11 @@ public:
 
         //- Forced assignment to uniform value
         void operator==(const Type& val);
+
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const GeometricBoundaryField&) = delete;
+        bool operator!=(const FieldField<PatchField, Type>&) = delete;
+        bool operator!=(const Type&) = delete;
 };
 
 
diff --git a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H
index 51aaaab9930..eb35edbb999 100644
--- a/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H
+++ b/src/OpenFOAM/fields/GeometricFields/GeometricField/GeometricField.H
@@ -758,6 +758,17 @@ public:
         void operator*=(const dimensioned<scalar>&);
         void operator/=(const dimensioned<scalar>&);
 
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=
+        (
+            const GeometricField<Type, PatchField, GeoMesh>&
+        ) = delete;
+        bool operator!=
+        (
+            const tmp<GeometricField<Type, PatchField, GeoMesh>>&
+        ) = delete;
+        bool operator!=(const dimensioned<Type>&) = delete;
+
 
     // Ostream Operators
 
@@ -810,15 +821,6 @@ public:
 };
 
 
-template<class Type, template<class> class PatchField, class GeoMesh>
-Ostream& operator<<
-(
-    Ostream&,
-    const typename GeometricField<Type, PatchField, GeoMesh>::
-    Boundary&
-);
-
-
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 } // End namespace Foam
diff --git a/src/OpenFOAM/fields/pointPatchFields/basic/value/valuePointPatchField.H b/src/OpenFOAM/fields/pointPatchFields/basic/value/valuePointPatchField.H
index 15c65146966..2bd1a9e993c 100644
--- a/src/OpenFOAM/fields/pointPatchFields/basic/value/valuePointPatchField.H
+++ b/src/OpenFOAM/fields/pointPatchFields/basic/value/valuePointPatchField.H
@@ -227,34 +227,23 @@ public:
 
         // Assignment operators
 
-            virtual void operator=
-            (
-                const valuePointPatchField<Type>&
-            );
-
-            virtual void operator=
-            (
-                const pointPatchField<Type>&
-            );
-
-            virtual void operator=(const Field<Type>&);
-            virtual void operator=(const Type&);
-
+        virtual void operator=(const valuePointPatchField<Type>&);
+        virtual void operator=(const pointPatchField<Type>&);
+        virtual void operator=(const Field<Type>&);
+        virtual void operator=(const Type&);
 
         // Force an assignment irrespective of form of patch
 
-            virtual void operator==
-            (
-                const valuePointPatchField<Type>&
-            );
-
-            virtual void operator==
-            (
-                const pointPatchField<Type>&
-            );
+        virtual void operator==(const valuePointPatchField<Type>&);
+        virtual void operator==(const pointPatchField<Type>&);
+        virtual void operator==(const Field<Type>&);
+        virtual void operator==(const Type&);
 
-            virtual void operator==(const Field<Type>&);
-            virtual void operator==(const Type&);
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const valuePointPatchField<Type>&) const = delete;
+        bool operator!=(const pointPatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
 };
 
 
diff --git a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointPatchField.H b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointPatchField.H
index 85d2b582c74..d8dc29076e1 100644
--- a/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointPatchField.H
+++ b/src/OpenFOAM/fields/pointPatchFields/pointPatchField/pointPatchField.H
@@ -560,9 +560,14 @@ public:
         // By generic these do nothing unless the patch actually has boundary
         // values
 
-        virtual void operator==(const pointPatchField<Type>&){}
-        virtual void operator==(const Field<Type>&){}
-        virtual void operator==(const Type&){}
+        virtual void operator==(const pointPatchField<Type>&) {}
+        virtual void operator==(const Field<Type>&) {}
+        virtual void operator==(const Type&) {}
+
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const pointPatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
 
 
     // Ostream Operator
diff --git a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H
index 35a6ef29e56..525291b598c 100644
--- a/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H
+++ b/src/finiteArea/fields/faPatchFields/faPatchField/faPatchField.H
@@ -613,6 +613,11 @@ public:
         virtual void operator==(const Field<Type>&);
         virtual void operator==(const Type&);
 
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const faPatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
+
 
     // Ostream Operator
 
diff --git a/src/finiteArea/fields/faePatchFields/faePatchField/faePatchField.H b/src/finiteArea/fields/faePatchFields/faePatchField/faePatchField.H
index 0271bea5e57..df1c2dfab57 100644
--- a/src/finiteArea/fields/faePatchFields/faePatchField/faePatchField.H
+++ b/src/finiteArea/fields/faePatchFields/faePatchField/faePatchField.H
@@ -516,6 +516,11 @@ public:
         virtual void operator==(const Field<Type>&);
         virtual void operator==(const Type&);
 
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const faePatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
+
 
     // Ostream Operator
 
diff --git a/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H b/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H
index caaa5a8e74e..43c95445d2b 100644
--- a/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/derived/scaledFixedValue/scaledFixedValueFvPatchField.H
@@ -198,11 +198,18 @@ public:
         virtual void write(Ostream&) const;
 
 
-        // Force an assignment irrespective of form of patch
+    // Member Operators
 
-            virtual void operator==(const fvPatchField<Type>& ptf);
-            virtual void operator==(const Field<Type>& tf);
-            virtual void operator==(const Type& t);
+        // Force an assignment, applying scaling to refValue
+
+        virtual void operator==(const fvPatchField<Type>&);
+        virtual void operator==(const Field<Type>&);
+        virtual void operator==(const Type&);
+
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const fvPatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
 };
 
 
diff --git a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H
index 0bacf8304db..9509b52e7d6 100644
--- a/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H
+++ b/src/finiteVolume/fields/fvPatchFields/fvPatchField/fvPatchField.H
@@ -734,6 +734,11 @@ public:
         virtual void operator==(const Field<Type>&);
         virtual void operator==(const Type&);
 
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const fvPatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
+
 
     // Ostream Operator
 
diff --git a/src/finiteVolume/fields/fvsPatchFields/fvsPatchField/fvsPatchField.H b/src/finiteVolume/fields/fvsPatchFields/fvsPatchField/fvsPatchField.H
index c302023d45b..1224dd8d60c 100644
--- a/src/finiteVolume/fields/fvsPatchFields/fvsPatchField/fvsPatchField.H
+++ b/src/finiteVolume/fields/fvsPatchFields/fvsPatchField/fvsPatchField.H
@@ -530,6 +530,11 @@ public:
         virtual void operator==(const Field<Type>&);
         virtual void operator==(const Type&);
 
+        // Prevent automatic comparison rewriting (c++20)
+        bool operator!=(const fvsPatchField<Type>&) const = delete;
+        bool operator!=(const Field<Type>&) const = delete;
+        bool operator!=(const Type&) const = delete;
+
 
     // Ostream Operator
 
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
index efda52462a8..6c6048eaa27 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValue.H
@@ -262,15 +262,6 @@ public:
         //- Region type names
         static const Enum<regionTypes> regionTypeNames_;
 
-        //- Bitmask values for operation variants
-        enum operationVariant
-        {
-            typeBase = 0,         //!< Base operation
-            typeScalar = 0x100,   //!< Operation returns a scalar
-            typeWeighted = 0x200, //!< Operation using weighting
-            typeAbsolute = 0x400, //!< Operation using mag (eg, for weighting)
-        };
-
         //- Operation type enumeration
         enum operationType
         {
@@ -291,10 +282,11 @@ public:
             opAreaIntegrate,        //!< Area integral
             opCoV,                  //!< Coefficient of variation
 
-            // Scalar return values
+            // Operations returning scalar - bitmask value
+            typeScalar = 0x100,
 
             //! Area average in normal direction (output is always scalar)
-            opAreaNormalAverage = typeScalar,
+            opAreaNormalAverage = (1 | typeScalar),
 
             //! Area integral in normal direction (output is always scalar)
             opAreaNormalIntegrate,
@@ -303,6 +295,8 @@ public:
             opUniformity,
 
             // Weighted variants
+            // Operations using weighting - bitmask value
+            typeWeighted = 0x200,
 
             //! Weighted sum
             opWeightedSum = (opSum | typeWeighted),
@@ -320,6 +314,8 @@ public:
             opWeightedUniformity = (opUniformity | typeWeighted),
 
             // Variants using absolute weighting
+            // Operation using mag (eg, for weighting) - bitmask value
+            typeAbsolute = 0x400,
 
             //! Sum using abs weighting
             opAbsWeightedSum = (opWeightedSum | typeAbsolute),
diff --git a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C
index 3455b2de978..9916defbb19 100644
--- a/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C
+++ b/src/functionObjects/field/fieldValues/surfaceFieldValue/surfaceFieldValueTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2015-2022 OpenCFD Ltd.
+    Copyright (C) 2015-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -147,6 +147,9 @@ processSameTypeValues
     switch (operation_)
     {
         case opNone:
+        case typeScalar:
+        case typeWeighted:
+        case typeAbsolute:
         {
             break;
         }
diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H
index 8d3e578ca46..37596383594 100644
--- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H
+++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValue.H
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2016-2021 OpenCFD Ltd.
+    Copyright (C) 2016-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -148,15 +148,6 @@ public:
 
     // Public Data Types
 
-        //- Bitmask values for operation variants
-        enum operationVariant
-        {
-            typeBase = 0,         //!< Base operation
-            typeScalar = 0x100,   //!< Operation returns a scalar
-            typeWeighted = 0x200, //!< Operation using weighting
-            typeAbsolute = 0x400, //!< Operation using mag (eg, for weighting)
-        };
-
         //- Operation type enumeration
         enum operationType
         {
@@ -172,7 +163,12 @@ public:
             opVolIntegrate,         //!< Volume integral
             opCoV,                  //!< Coefficient of variation
 
+            // Operations returning scalar - bitmask value
+            typeScalar = 0x100,
+
             // Weighted variants
+            // Operations using weighting - bitmask value
+            typeWeighted = 0x200,
 
             //! Weighted sum
             opWeightedSum = (opSum | typeWeighted),
@@ -187,6 +183,8 @@ public:
             opWeightedVolIntegrate = (opVolIntegrate | typeWeighted),
 
             // Variants using absolute weighting
+            // Operation using mag (eg, for weighting) - bitmask value
+            typeAbsolute = 0x400,
         };
 
         //- Operation type names
diff --git a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C
index 58ac73178e1..968bdb84ced 100644
--- a/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C
+++ b/src/functionObjects/field/fieldValues/volFieldValue/volFieldValueTemplates.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2017 OpenFOAM Foundation
-    Copyright (C) 2015-2021 OpenCFD Ltd.
+    Copyright (C) 2015-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -91,6 +91,9 @@ Type Foam::functionObjects::fieldValues::volFieldValue::processValues
     switch (operation_)
     {
         case opNone:
+        case typeScalar:
+        case typeWeighted:
+        case typeAbsolute:
         {
             break;
         }
diff --git a/src/functionObjects/lagrangian/icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.H b/src/functionObjects/lagrangian/icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.H
index 9beeec8d775..df5944200b5 100644
--- a/src/functionObjects/lagrangian/icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.H
+++ b/src/functionObjects/lagrangian/icoUncoupledKinematicCloud/icoUncoupledKinematicCloud.H
@@ -131,7 +131,7 @@ class icoUncoupledKinematicCloud
         icoUncoupledKinematicCloud(const icoUncoupledKinematicCloud&) = delete;
 
         //- No copy assignment
-        void operator==(const icoUncoupledKinematicCloud&) = delete;
+        void operator=(const icoUncoupledKinematicCloud&) = delete;
 
 
 public:
diff --git a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H
index 1da08c85da5..031fa43e446 100644
--- a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H
+++ b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxy.H
@@ -40,8 +40,8 @@ SourceFiles
 
 \*---------------------------------------------------------------------------*/
 
-#ifndef MeshedSurfaceProxy_H
-#define MeshedSurfaceProxy_H
+#ifndef Foam_MeshedSurfaceProxy_H
+#define Foam_MeshedSurfaceProxy_H
 
 #include "pointField.H"
 #include "surfZoneList.H"
@@ -160,60 +160,42 @@ public:
 
     // Member Functions
 
-        // Access
-
-            //- The surface size is the number of faces
-            label size() const
-            {
-                return faces_.size();
-            }
-
-            //- Return const access to the points
-            const pointField& points() const
-            {
-                return points_;
-            }
-
-            //- Return const access to the faces
-            const UList<Face>& surfFaces() const
-            {
-                return faces_;
-            }
-
-            //- Const access to the surface zones.
-            //  If zones are defined, they must be contiguous and cover the
-            //  entire surface
-            const UList<surfZone>& surfZones() const
-            {
-                return zones_;
-            }
-
-            //- Const access to the faceMap, zero-sized when unused
-            const labelUList& faceMap() const
-            {
-                return faceMap_;
-            }
-
-            //- Const access to the faceIds, zero-sized when unused
-            const labelUList& faceIds() const
-            {
-                return faceIds_;
-            }
-
-            //- Can/should use faceMap?
-            bool useFaceMap() const
-            {
-                return faceMap_.size() == faces_.size();
-            }
-
-            //- Possible to use faceIds?
-            bool useFaceIds() const
-            {
-                return faceIds_.size() == faces_.size();
-            }
-
-            //- Count number of triangles.
-            inline label nTriangles() const;
+    // Access
+
+        //- The surface size is the number of faces
+        label size() const noexcept { return faces_.size(); }
+
+        //- Return const access to the points
+        const pointField& points() const noexcept { return points_; }
+
+        //- Return const access to the faces
+        const UList<Face>& surfFaces() const noexcept { return faces_; }
+
+        //- Const access to the surface zones.
+        //  If zones are defined, they must be contiguous and cover the
+        //  entire surface
+        const UList<surfZone>& surfZones() const noexcept { return zones_; }
+
+        //- Const access to the faceMap, zero-sized when unused
+        const labelUList& faceMap() const noexcept { return faceMap_; }
+
+        //- Const access to the faceIds, zero-sized when unused
+        const labelUList& faceIds() const noexcept { return faceIds_; }
+
+        //- Can/should use faceMap?
+        bool useFaceMap() const noexcept
+        {
+            return faceMap_.size() == faces_.size();
+        }
+
+        //- Possible to use faceIds?
+        bool useFaceIds() const noexcept
+        {
+            return faceIds_.size() == faces_.size();
+        }
+
+        //- Count number of triangles.
+        inline label nTriangles() const;
 
 
     // Write
diff --git a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxys.C b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxys.C
index 0687a2d76bf..557565f7871 100644
--- a/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxys.C
+++ b/src/surfMesh/MeshedSurfaceProxy/MeshedSurfaceProxys.C
@@ -6,7 +6,7 @@
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
     Copyright (C) 2011-2016 OpenFOAM Foundation
-    Copyright (C) 2016 OpenCFD Ltd.
+    Copyright (C) 2016-2023 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -27,6 +27,9 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "MeshedSurfaceProxy.H"
+#include "face.H"
+#include "triFace.H"
+#include "labelledTri.H"
 #include "addToRunTimeSelectionTable.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-- 
GitLab