patch 8.2.4702: C++ scope labels are hard-coded

Problem:    C++ scope labels are hard-coded.
Solution:   Add 'cinscopedecls' to define the labels. (Rom Praschan,
            closes #10109)
diff --git a/src/buffer.c b/src/buffer.c
index bd37830..5f8b1ad 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -2353,6 +2353,7 @@
 #ifdef FEAT_CINDENT
     clear_string_option(&buf->b_p_cink);
     clear_string_option(&buf->b_p_cino);
+    clear_string_option(&buf->b_p_cinsd);
 #endif
 #if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
     clear_string_option(&buf->b_p_cinw);
diff --git a/src/cindent.c b/src/cindent.c
index ca21c12..a22db95 100644
--- a/src/cindent.c
+++ b/src/cindent.c
@@ -423,20 +423,34 @@
  * Recognize a "public/private/protected" scope declaration label.
  */
     static int
-cin_isscopedecl(char_u *s)
+cin_isscopedecl(char_u *p)
 {
-    int		i;
+    size_t cinsd_len;
+    char_u *cinsd_buf;
+    char_u *cinsd;
+    size_t len;
+    char_u *skip;
+    char_u *s = cin_skipcomment(p);
 
-    s = cin_skipcomment(s);
-    if (STRNCMP(s, "public", 6) == 0)
-	i = 6;
-    else if (STRNCMP(s, "protected", 9) == 0)
-	i = 9;
-    else if (STRNCMP(s, "private", 7) == 0)
-	i = 7;
-    else
-	return FALSE;
-    return (*(s = cin_skipcomment(s + i)) == ':' && s[1] != ':');
+    cinsd_len = STRLEN(curbuf->b_p_cinsd) + 1;
+    cinsd_buf = alloc(cinsd_len);
+    if (cinsd_buf != NULL)
+    {
+	for (cinsd = curbuf->b_p_cinsd; *cinsd; )
+	{
+	    len = copy_option_part(&cinsd, cinsd_buf, cinsd_len, ",");
+	    if (STRNCMP(s, cinsd_buf, len) == 0)
+	    {
+		skip = cin_skipcomment(s + len);
+		if (*skip == ':' && skip[1] != ':')
+		    return TRUE;
+	    }
+	}
+
+	vim_free(cinsd_buf);
+    }
+
+    return FALSE;
 }
 
 /*
diff --git a/src/option.c b/src/option.c
index 4d50a64..49123aa 100644
--- a/src/option.c
+++ b/src/option.c
@@ -5449,6 +5449,7 @@
 	case PV_CIN:	return (char_u *)&(curbuf->b_p_cin);
 	case PV_CINK:	return (char_u *)&(curbuf->b_p_cink);
 	case PV_CINO:	return (char_u *)&(curbuf->b_p_cino);
+	case PV_CINSD:	return (char_u *)&(curbuf->b_p_cinsd);
 #endif
 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
 	case PV_CINW:	return (char_u *)&(curbuf->b_p_cinw);
@@ -6020,6 +6021,8 @@
 	    COPY_OPT_SCTX(buf, BV_CINK);
 	    buf->b_p_cino = vim_strsave(p_cino);
 	    COPY_OPT_SCTX(buf, BV_CINO);
+	    buf->b_p_cinsd = vim_strsave(p_cinsd);
+	    COPY_OPT_SCTX(buf, BV_CINSD);
 #endif
 	    // Don't copy 'filetype', it must be detected
 	    buf->b_p_ft = empty_option;
diff --git a/src/option.h b/src/option.h
index 85f2fa8..4c583a4 100644
--- a/src/option.h
+++ b/src/option.h
@@ -400,6 +400,7 @@
 #ifdef FEAT_CINDENT
 EXTERN int	p_cin;		// 'cindent'
 EXTERN char_u	*p_cink;	// 'cinkeys'
+EXTERN char_u	*p_cinsd;	// 'cinscopedecls'
 #endif
 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
 EXTERN char_u	*p_cinw;	// 'cinwords'
@@ -1126,6 +1127,7 @@
     , BV_CIN
     , BV_CINK
     , BV_CINO
+    , BV_CINSD
 #endif
 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
     , BV_CINW
diff --git a/src/optiondefs.h b/src/optiondefs.h
index 4f2ec4d..54cccf8 100644
--- a/src/optiondefs.h
+++ b/src/optiondefs.h
@@ -44,6 +44,7 @@
 # define PV_CIN		OPT_BUF(BV_CIN)
 # define PV_CINK	OPT_BUF(BV_CINK)
 # define PV_CINO	OPT_BUF(BV_CINO)
+# define PV_CINSD	OPT_BUF(BV_CINSD)
 #endif
 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
 # define PV_CINW	OPT_BUF(BV_CINW)
@@ -603,6 +604,15 @@
 			    (char_u *)NULL, PV_NONE,
 #endif
 			    {(char_u *)"", (char_u *)0L} SCTX_INIT},
+    {"cinscopedecls", "cinsd", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
+#ifdef FEAT_CINDENT
+			    (char_u *)&p_cinsd, PV_CINSD,
+			    {(char_u *)"public,protected,private", (char_u *)0L}
+#else
+			    (char_u *)NULL, PV_NONE,
+			    {(char_u *)0L, (char_u *)0L}
+#endif
+			    SCTX_INIT},
     {"cinwords",    "cinw", P_STRING|P_ALLOCED|P_VI_DEF|P_ONECOMMA|P_NODUP,
 #if defined(FEAT_SMARTINDENT) || defined(FEAT_CINDENT)
 			    (char_u *)&p_cinw, PV_CINW,
diff --git a/src/optionstr.c b/src/optionstr.c
index 09e6d8a..fd72da4 100644
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -260,6 +260,7 @@
 #ifdef FEAT_CINDENT
     check_string_option(&buf->b_p_cink);
     check_string_option(&buf->b_p_cino);
+    check_string_option(&buf->b_p_cinsd);
     parse_cino(buf);
 #endif
     check_string_option(&buf->b_p_ft);
diff --git a/src/structs.h b/src/structs.h
index 5a76a59..a1dbfbe 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -2881,6 +2881,7 @@
     int		b_p_cin;	// 'cindent'
     char_u	*b_p_cino;	// 'cinoptions'
     char_u	*b_p_cink;	// 'cinkeys'
+    char_u	*b_p_cinsd;	// 'cinscopedecls'
 #endif
 #if defined(FEAT_CINDENT) || defined(FEAT_SMARTINDENT)
     char_u	*b_p_cinw;	// 'cinwords'
diff --git a/src/testdir/test_cindent.vim b/src/testdir/test_cindent.vim
index d8ea4e7..dbd4aa0 100644
--- a/src/testdir/test_cindent.vim
+++ b/src/testdir/test_cindent.vim
@@ -5319,6 +5319,49 @@
   close!
 endfunc
 
+func Test_cindent_scopedecls()
+  new
+  setl cindent ts=4 sw=4
+  setl cino=g0
+  setl cinsd+=public\ slots,signals
+
+  let code =<< trim [CODE]
+  class Foo
+  {
+  public:
+  virtual void foo() = 0;
+  public slots:
+  void onBar();
+  signals:
+  void baz();
+  private:
+  int x;
+  };
+  [CODE]
+
+  call append(0, code)
+  normal gg
+  normal ]]=][
+
+  let expected =<< trim [CODE]
+  class Foo
+  {
+  public:
+	virtual void foo() = 0;
+  public slots:
+	void onBar();
+  signals:
+	void baz();
+  private:
+	int x;
+  };
+
+  [CODE]
+
+  call assert_equal(expected, getline(1, '$'))
+  enew! | close
+endfunc
+
 func Test_cindent_pragma()
   new
   setl cindent ts=4 sw=4
diff --git a/src/version.c b/src/version.c
index f00fbcb..3cf9d18 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4702,
+/**/
     4701,
 /**/
     4700,