Repository: sphinx-doc/sphinx

Issue:
BUG: numpydoc + autosumarry broken
#4611 broke rendering for me of a `numpydoc` + `autosummary` `html` build where the input is like:
```
...
    Parameters
    ----------
    data : array, shape (n_chan,)
        The data values to plot.
...
```
Which `numpydoc` turns into something like:
```
...
:Parameters:

    **data** : array, shape (n_chan,)
        The data values to plot.
...
```
On the commit in `master` before this (b04bfcfab7b4a47dca1a5c9dda88e810ffc81bcd) I get the correct output with `:` between items:

![screenshot from 2019-01-15 15-03-42](https://user-images.githubusercontent.com/2365790/51206714-c6452900-18d6-11e9-8044-fe1d1a9a67c1.png)

On `master` after this PR (on commit 7459d8771af1afaf6c2342b689fb70a56ba00efa) the colon is gone (`<span>` missing in output):

![screenshot from 2019-01-15 14-57-04](https://user-images.githubusercontent.com/2365790/51206359-dad4f180-18d5-11e9-8ca6-a0f5170c1888.png)

I'm not sure how to fix this because I'm out of my depth, though :(

Discussion:

Patch:
diff --git a/CHANGES b/CHANGES
index aa9715134..fc85ceb21 100644
--- a/CHANGES
+++ b/CHANGES
@@ -58,8 +58,6 @@ Incompatible changes
   to insert custom user definitions.  See :ref:`latex-macros`.
 * quickstart: Simplify generated ``conf.py``
 * websupport: unbundled from sphinx core. Please use sphinxcontrib-websupport
-* C++, the visibility of base classes is now always rendered as present in the
-  input. That is, ``private`` is now shown, where it was ellided before.
 
 Deprecated
 ----------
@@ -162,7 +160,6 @@ Features added
 * #5841: apidoc: Add --extensions option to sphinx-apidoc
 * #4981: C++, added an alias directive for inserting lists of declarations,
   that references existing declarations (e.g., for making a synopsis).
-* C++: add ``cpp:struct`` to complement ``cpp:class``.
 
 Bugs fixed
 ----------
@@ -223,7 +220,6 @@ Bugs fixed
   in an admonition
 * #5231: "make html" does not read and build "po" files in "locale" dir
 * #5954: ``:scale:`` image option may break PDF build if image in an admonition
-* #5966: mathjax has not been loaded on incremental build
 
 Testing
 --------
diff --git a/doc/usage/restructuredtext/domains.rst b/doc/usage/restructuredtext/domains.rst
index 3ac90b5fb..621713264 100644
--- a/doc/usage/restructuredtext/domains.rst
+++ b/doc/usage/restructuredtext/domains.rst
@@ -548,16 +548,11 @@ The following directives are available. All declarations can start with a
 visibility statement (``public``, ``private`` or ``protected``).
 
 .. rst:directive:: .. cpp:class:: class specifier
-                   .. cpp:struct:: class specifier
 
    Describe a class/struct, possibly with specification of inheritance, e.g.,::
 
       .. cpp:class:: MyClass : public MyBase, MyOtherBase
 
-   The difference between :rst:dir:`cpp:class` and :rst:dir:`cpp:struct` is
-   only cosmetic: the prefix rendered in the output, and the specifier shown
-   in the index.
-
    The class can be directly declared inside a nested scope, e.g.,::
 
       .. cpp:class:: OuterScope::MyClass : public MyBase, MyOtherBase
@@ -579,9 +574,6 @@ visibility statement (``public``, ``private`` or ``protected``).
       .. cpp:class:: template<typename T> \
                      std::array<T, 42>
 
-   .. versionadded:: 2.0
-      The :rst:dir:`cpp:struct` directive.
-
 .. rst:directive:: .. cpp:function:: (member) function prototype
 
    Describe a function or member function, e.g.,::
@@ -714,8 +706,6 @@ visibility statement (``public``, ``private`` or ``protected``).
 
    Describe a union.
 
-   .. versionadded:: 1.8
-
 .. rst:directive:: .. cpp:concept:: template-parameter-list name
 
    .. warning:: The support for concepts is experimental. It is based on the
@@ -760,9 +750,6 @@ visibility statement (``public``, ``private`` or ``protected``).
       - :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r`
         is incrementable.
 
-   .. versionadded:: 1.5
-
-
 Options
 ^^^^^^^
 
@@ -772,8 +759,6 @@ Some directives support options:
 - ``:tparam-line-spec:``, for templated declarations.
   If specified, each template parameter will be rendered on a separate line.
 
-  .. versionadded:: 1.6
-
 Anonymous Entities
 ~~~~~~~~~~~~~~~~~~
 
@@ -808,8 +793,6 @@ This will be rendered as:
 
 Explicit ref: :cpp:var:`Data::@data::a`. Short-hand ref: :cpp:var:`Data::a`.
 
-.. versionadded:: 1.8
-
 
 Aliasing Declarations
 ~~~~~~~~~~~~~~~~~~~~~
@@ -842,10 +825,8 @@ The following directive can be used for this purpose.
 
    becomes
 
-   .. cpp:alias:: void overload_example::C::f(double d) const
-                  void overload_example::C::f(double d)
-
-   .. versionadded:: 2.0
+    .. cpp:alias:: void overload_example::C::f(double d) const
+                   void overload_example::C::f(double d)
 
 
 Constrained Templates
@@ -933,11 +914,6 @@ Inline Expressions and Types
    A type: :cpp:expr:`const MySortedContainer<int>&`
    (or as text :cpp:texpr:`const MySortedContainer<int>&`).
 
-   .. versionadded:: 1.7
-      The :rst:role:`cpp:expr` role.
-
-   .. versionadded:: 1.8
-      The :rst:role:`cpp:texpr` role.
 
 Namespacing
 ~~~~~~~~~~~
@@ -1000,8 +976,6 @@ The ``cpp:namespace-pop`` directive undoes the most recent
 
    the current scope will be ``A::B::C::D``.
 
-   .. versionadded:: 1.4
-
 .. rst:directive:: .. cpp:namespace-pop::
 
    Undo the previous ``cpp:namespace-push`` directive (*not* just pop a scope).
@@ -1023,8 +997,6 @@ The ``cpp:namespace-pop`` directive undoes the most recent
 
       .. cpp:namespace-push:: A::B
 
-   .. versionadded:: 1.4
-
 Info field lists
 ~~~~~~~~~~~~~~~~~
 
@@ -1045,7 +1017,6 @@ These roles link to the given declaration types:
 
 .. rst:role:: cpp:any
               cpp:class
-              cpp:struct
               cpp:func
               cpp:member
               cpp:var
@@ -1057,9 +1028,6 @@ These roles link to the given declaration types:
    Reference a C++ declaration by name (see below for details).  The name must
    be properly qualified relative to the position of the link.
 
-   .. versionadded:: 2.0
-      The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class` role.
-
 .. admonition:: Note on References with Templates Parameters/Arguments
 
    These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index ff5487598..43e89ab7d 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -577,7 +577,7 @@
 
 
 class NoOldIdError(Exception):
-    # Used to avoid implementing unneeded id generation for old id schemes.
+    # Used to avoid implementing unneeded id generation for old id schmes.
     @property
     def description(self):
         # type: () -> str
@@ -626,7 +626,7 @@ def __eq__(self, other):
     __hash__ = None  # type: Callable[[], int]
 
     def clone(self):
-        # type: () -> Any
+        # type: () -> ASTBase
         """Clone a definition expression node."""
         return deepcopy(self)
 
@@ -2626,7 +2626,6 @@ def _add(modifiers, text):
 
 class ASTDeclSpecs(ASTBase):
     def __init__(self, outer, leftSpecs, rightSpecs, trailing):
-        # type: (Any, ASTDeclSpecsSimple, ASTDeclSpecsSimple, Any) -> None
         # leftSpecs and rightSpecs are used for output
         # allSpecs are used for id generation
         self.outer = outer
@@ -2664,6 +2663,8 @@ def _stringify(self, transform):
         res = []  # type: List[str]
         l = transform(self.leftSpecs)
         if len(l) > 0:
+            if len(res) > 0:
+                res.append(" ")
             res.append(l)
         if self.trailingTypeSpec:
             if len(res) > 0:
@@ -3462,7 +3463,7 @@ def describe_signature(self, signode, mode, env, symbol):
 
 class ASTBaseClass(ASTBase):
     def __init__(self, name, visibility, virtual, pack):
-        # type: (ASTNestedName, str, bool, bool) -> None
+        # type: (Any, str, bool, bool) -> None
         self.name = name
         self.visibility = visibility
         self.virtual = virtual
@@ -3471,8 +3472,7 @@ def __init__(self, name, visibility, virtual, pack):
     def _stringify(self, transform):
         # type: (Callable[[Any], str]) -> str
         res = []
-
-        if self.visibility is not None:
+        if self.visibility != 'private':
             res.append(self.visibility)
             res.append(' ')
         if self.virtual:
@@ -3485,7 +3485,7 @@ def _stringify(self, transform):
     def describe_signature(self, signode, mode, env, symbol):
         # type: (addnodes.desc_signature, str, BuildEnvironment, Symbol) -> None
         _verify_description_mode(mode)
-        if self.visibility is not None:
+        if self.visibility != 'private':
             signode += addnodes.desc_annotation(self.visibility,
                                                 self.visibility)
             signode += nodes.Text(' ')
@@ -3499,7 +3499,7 @@ def describe_signature(self, signode, mode, env, symbol):
 
 class ASTClass(ASTBase):
     def __init__(self, name, final, bases):
-        # type: (ASTNestedName, bool, List[ASTBaseClass]) -> None
+        # type: (Any, bool, List[Any]) -> None
         self.name = name
         self.final = final
         self.bases = bases
@@ -3625,17 +3625,16 @@ def describe_signature(self, signode, mode, env, symbol):
 
 
 class ASTDeclaration(ASTBase):
-    def __init__(self, objectType, directiveType, visibility, templatePrefix, declaration):
-        # type: (str, str, str, ASTTemplateDeclarationPrefix, Any) -> None
+    def __init__(self, objectType, visibility, templatePrefix, declaration):
+        # type: (str, str, Any, Any) -> None
         self.objectType = objectType
-        self.directiveType = directiveType
         self.visibility = visibility
         self.templatePrefix = templatePrefix
         self.declaration = declaration
 
         self.symbol = None  # type: Symbol
         # set by CPPObject._add_enumerator_to_parent
-        self.enumeratorScopedSymbol = None  # type: Symbol
+        self.enumeratorScopedSymbol = None  # type: Any
 
     def clone(self):
         # type: () -> ASTDeclaration
@@ -3643,8 +3642,8 @@ def clone(self):
             templatePrefixClone = self.templatePrefix.clone()
         else:
             templatePrefixClone = None
-        return ASTDeclaration(self.objectType, self.directiveType,
-                              self.visibility, templatePrefixClone,
+        return ASTDeclaration(self.objectType, self.visibility,
+                              templatePrefixClone,
                               self.declaration.clone())
 
     @property
@@ -3725,20 +3724,14 @@ def describe_signature(self, signode, mode, env, options):
         elif self.objectType == 'function':
             pass
         elif self.objectType == 'class':
-            assert self.directiveType in ('class', 'struct')
-            prefix = self.directiveType + ' '
-            mainDeclNode += addnodes.desc_annotation(prefix, prefix)
+            mainDeclNode += addnodes.desc_annotation('class ', 'class ')
         elif self.objectType == 'union':
             mainDeclNode += addnodes.desc_annotation('union ', 'union ')
         elif self.objectType == 'enum':
-            if self.directiveType == 'enum':
-                prefix = 'enum '
-            elif self.directiveType == 'enum-class':
-                prefix = 'enum class '
-            elif self.directiveType == 'enum-struct':
-                prefix = 'enum struct '
-            else:
-                assert False  # wrong directiveType used
+            prefix = 'enum '
+            if self.scoped:  # type: ignore
+                prefix += self.scoped  # type: ignore
+                prefix += ' '
             mainDeclNode += addnodes.desc_annotation(prefix, prefix)
         elif self.objectType == 'enumerator':
             mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
@@ -3850,7 +3843,7 @@ def _add_template_and_function_params(self):
                     continue
                 # only add a declaration if we our self are from a declaration
                 if self.declaration:
-                    decl = ASTDeclaration('templateParam', None, None, None, p)
+                    decl = ASTDeclaration('templateParam', None, None, p)
                 else:
                     decl = None
                 nne = ASTNestedNameElement(p.get_identifier(), None)
@@ -3865,7 +3858,7 @@ def _add_template_and_function_params(self):
                 if nn is None:
                     continue
                 # (comparing to the template params: we have checked that we are a declaration)
-                decl = ASTDeclaration('functionParam', None, None, None, p)
+                decl = ASTDeclaration('functionParam', None, None, p)
                 assert not nn.rooted
                 assert len(nn.names) == 1
                 self._add_symbols(nn, [], decl, self.docname)
@@ -6003,7 +5996,7 @@ def _parse_class(self):
         if self.skip_string(':'):
             while 1:
                 self.skip_ws()
-                visibility = None
+                visibility = 'private'
                 virtual = False
                 pack = False
                 if self.skip_word_and_ws('virtual'):
@@ -6237,15 +6230,11 @@ def _check_template_consistency(self,
             templatePrefix = ASTTemplateDeclarationPrefix(newTemplates)
         return templatePrefix
 
-    def parse_declaration(self, objectType, directiveType):
-        # type: (str, str) -> ASTDeclaration
-        if objectType not in ('class', 'union', 'function', 'member', 'type',
-                              'concept', 'enum', 'enumerator'):
+    def parse_declaration(self, objectType):
+        # type: (str) -> ASTDeclaration
+        if objectType not in ('type', 'concept', 'member',
+                              'function', 'class', 'union', 'enum', 'enumerator'):
             raise Exception('Internal error, unknown objectType "%s".' % objectType)
-        if directiveType not in ('class', 'struct', 'union', 'function', 'member', 'var',
-                                 'type', 'concept',
-                                 'enum', 'enum-struct', 'enum-class', 'enumerator'):
-            raise Exception('Internal error, unknown directiveType "%s".' % directiveType)
         visibility = None
         templatePrefix = None
         declaration = None  # type: Any
@@ -6295,7 +6284,7 @@ def parse_declaration(self, objectType, directiveType):
                                                           templatePrefix,
                                                           fullSpecShorthand=False,
                                                           isMember=objectType == 'member')
-        return ASTDeclaration(objectType, directiveType, visibility,
+        return ASTDeclaration(objectType, visibility,
                               templatePrefix, declaration)
 
     def parse_namespace_object(self):
@@ -6325,7 +6314,7 @@ def parse_xref_object(self):
         except DefinitionError as e1:
             try:
                 self.pos = pos
-                res2 = self.parse_declaration('function', 'function')
+                res2 = self.parse_declaration('function')
                 # if there are '()' left, just skip them
                 self.skip_ws()
                 self.skip_string('()')
@@ -6389,7 +6378,7 @@ def warn(self, msg):
         self.state_machine.reporter.warning(msg, line=self.lineno)
 
     def _add_enumerator_to_parent(self, ast):
-        # type: (ASTDeclaration) -> None
+        # type: (Any) -> None
         assert ast.objectType == 'enumerator'
         # find the parent, if it exists && is an enum
         #                     && it's unscoped,
@@ -6415,7 +6404,7 @@ def _add_enumerator_to_parent(self, ast):
             # TODO: maybe issue a warning, enumerators in non-enums is weird,
             # but it is somewhat equivalent to unscoped enums, without the enum
             return
-        if parentDecl.directiveType != 'enum':
+        if parentDecl.scoped:
             return
 
         targetSymbol = parentSymbol.parent
@@ -6431,7 +6420,7 @@ def _add_enumerator_to_parent(self, ast):
                docname=self.env.docname)
 
     def add_target_and_index(self, ast, sig, signode):
-        # type: (ASTDeclaration, str, addnodes.desc_signature) -> None
+        # type: (Any, str, addnodes.desc_signature) -> None
         # general note: name must be lstrip(':')'ed, to remove "::"
         ids = []
         for i in range(1, _max_id + 1):
@@ -6490,23 +6479,13 @@ def add_target_and_index(self, ast, sig, signode):
             signode['first'] = (not self.names)  # hmm, what is this about?
             self.state.document.note_explicit_target(signode)
 
-    @property
-    def object_type(self):
-        # type: () -> str
-        raise NotImplementedError()
-
-    @property
-    def display_object_type(self):
-        # type: () -> str
-        return self.object_type
-
     def get_index_text(self, name):
         # type: (str) -> str
-        return _('%s (C++ %s)') % (name, self.display_object_type)
+        raise NotImplementedError()
 
     def parse_definition(self, parser):
-        # type: (DefinitionParser) -> ASTDeclaration
-        return parser.parse_declaration(self.object_type, self.objtype)
+        # type: (Any) -> Any
+        raise NotImplementedError()
 
     def describe_signature(self, signode, ast, options):
         # type: (addnodes.desc_signature, Any, Dict) -> None
@@ -6542,7 +6521,7 @@ def run(self):
         return super().run()
 
     def handle_signature(self, sig, signode):
-        # type: (str, addnodes.desc_signature) -> ASTDeclaration
+        # type: (str, addnodes.desc_signature) -> Any
         parentSymbol = self.env.temp_data['cpp:parent_symbol']
 
         parser = DefinitionParser(sig, self, self.env.config)
@@ -6593,41 +6572,93 @@ def after_content(self):
 
 
 class CPPTypeObject(CPPObject):
-    object_type = 'type'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ type)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("type")
 
 
 class CPPConceptObject(CPPObject):
-    object_type = 'concept'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ concept)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("concept")
 
 
 class CPPMemberObject(CPPObject):
-    object_type = 'member'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ member)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("member")
 
 
 class CPPFunctionObject(CPPObject):
-    object_type = 'function'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ function)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("function")
 
 
 class CPPClassObject(CPPObject):
-    object_type = 'class'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ class)') % name
 
-    @property
-    def display_object_type(self):
-        # the distinction between class and struct is only cosmetic
-        assert self.objtype in ('class', 'struct')
-        return self.objtype
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("class")
 
 
 class CPPUnionObject(CPPObject):
-    object_type = 'union'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ union)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("union")
 
 
 class CPPEnumObject(CPPObject):
-    object_type = 'enum'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ enum)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        ast = parser.parse_declaration("enum")
+        # self.objtype is set by ObjectDescription in run()
+        if self.objtype == "enum":
+            ast.scoped = None
+        elif self.objtype == "enum-struct":
+            ast.scoped = "struct"
+        elif self.objtype == "enum-class":
+            ast.scoped = "class"
+        else:
+            assert False
+        return ast
 
 
 class CPPEnumeratorObject(CPPObject):
-    object_type = 'enumerator'
+    def get_index_text(self, name):
+        # type: (str) -> str
+        return _('%s (C++ enumerator)') % name
+
+    def parse_definition(self, parser):
+        # type: (Any) -> Any
+        return parser.parse_declaration("enumerator")
 
 
 class CPPNamespaceObject(SphinxDirective):
@@ -6937,17 +6968,7 @@ def warn(self, msg):
 
 
 class CPPDomain(Domain):
-    """C++ language domain.
-
-    There are two 'object type' attributes being used::
-
-    - Each object created from directives gets an assigned .objtype from ObjectDescription.run.
-      This is simply the directive name.
-    - Each declaration (see the distinction in the directives dict below) has a nested .ast of
-      type ASTDeclaration. That object has .objectType which corresponds to the keys in the
-      object_types dict below. They are the core different types of declarations in C++ that
-      one can document.
-    """
+    """C++ language domain."""
     name = 'cpp'
     label = 'C++'
     object_types = {
@@ -6962,9 +6983,7 @@ class CPPDomain(Domain):
     }
 
     directives = {
-        # declarations
         'class': CPPClassObject,
-        'struct': CPPClassObject,
         'union': CPPUnionObject,
         'function': CPPFunctionObject,
         'member': CPPMemberObject,
@@ -6975,17 +6994,14 @@ class CPPDomain(Domain):
         'enum-struct': CPPEnumObject,
         'enum-class': CPPEnumObject,
         'enumerator': CPPEnumeratorObject,
-        # scope control
         'namespace': CPPNamespaceObject,
         'namespace-push': CPPNamespacePushObject,
         'namespace-pop': CPPNamespacePopObject,
-        # other
         'alias': CPPAliasObject
     }
     roles = {
         'any': CPPXRefRole(),
         'class': CPPXRefRole(),
-        'struct': CPPXRefRole(),
         'union': CPPXRefRole(),
         'func': CPPXRefRole(fix_parens=True),
         'member': CPPXRefRole(),
diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py
index 5a84e738f..3a26fcdda 100644
--- a/sphinx/ext/mathjax.py
+++ b/sphinx/ext/mathjax.py
@@ -109,6 +109,6 @@ def setup(app):
     app.add_config_value('mathjax_inline', [r'\(', r'\)'], 'html')
     app.add_config_value('mathjax_display', [r'\[', r'\]'], 'html')
     app.add_config_value('mathjax_config', None, 'html')
-    app.connect('env-updated', install_mathjax)
+    app.connect('env-check-consistency', install_mathjax)
 
     return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t
index f819e0691..5bdd803eb 100644
--- a/sphinx/themes/basic/static/basic.css_t
+++ b/sphinx/themes/basic/static/basic.css_t
@@ -537,6 +537,12 @@ dl.glossary dt {
     font-style: oblique;
 }
 
+.classifier:before {
+    font-style: normal;
+    margin: 0.5em;
+    content: ":";
+}
+
 abbr, acronym {
     border-bottom: dotted 1px;
     cursor: help;


Test patch:
diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py
index fe5e37f23..3a506cd31 100644
--- a/tests/test_domain_cpp.py
+++ b/tests/test_domain_cpp.py
@@ -25,7 +25,7 @@ class Config:
         cpp_paren_attributes = ["paren_attr"]
     parser = DefinitionParser(string, None, Config())
     parser.allowFallbackExpressionParsing = False
-    ast = parser.parse_declaration(name, name)
+    ast = parser.parse_declaration(name)
     parser.assert_end()
     # The scopedness would usually have been set by CPPEnumObject
     if name == "enum":
@@ -194,7 +194,6 @@ def exprCheck(expr, id, id4=None):
     exprCheck('new int[42]', 'nw_AL42E_iE')
     exprCheck('new int()', 'nw_ipiE')
     exprCheck('new int(5, 42)', 'nw_ipiL5EL42EE')
-    exprCheck('::new int', 'nw_iE')
     # delete-expression
     exprCheck('delete p', 'dl1p')
     exprCheck('delete [] p', 'da1p')
@@ -335,8 +334,6 @@ def test_member_definitions():
 
 
 def test_function_definitions():
-    check('function', 'void f(volatile int)', {1: "f__iV", 2: "1fVi"})
-    check('function', 'void f(std::size_t)', {1: "f__std::s", 2: "1fNSt6size_tE"})
     check('function', 'operator bool() const', {1: "castto-b-operatorC", 2: "NKcvbEv"})
     check('function', 'A::operator bool() const',
           {1: "A::castto-b-operatorC", 2: "NK1AcvbEv"})
@@ -526,12 +523,11 @@ def test_class_definitions():
     check('class', 'A', {1: "A", 2: "1A"})
     check('class', 'A::B::C', {1: "A::B::C", 2: "N1A1B1CE"})
     check('class', 'A : B', {1: "A", 2: "1A"})
-    check('class', 'A : private B', {1: "A", 2: "1A"})
+    check('class', 'A : private B', {1: "A", 2: "1A"}, output='A : B')
     check('class', 'A : public B', {1: "A", 2: "1A"})
     check('class', 'A : B, C', {1: "A", 2: "1A"})
     check('class', 'A : B, protected C, D', {1: "A", 2: "1A"})
-    check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='A : private virtual B')
-    check('class', 'A : private virtual B', {1: 'A', 2: '1A'})
+    check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='A : virtual B')
     check('class', 'A : B, virtual C', {1: 'A', 2: '1A'})
     check('class', 'A : public virtual B', {1: 'A', 2: '1A'})
     check('class', 'A : B, C...', {1: 'A', 2: '1A'})
@@ -563,7 +559,6 @@ def test_anon_definitions():
     check('union', '@a', {3: "Ut1_a"})
     check('enum', '@a', {3: "Ut1_a"})
     check('class', '@1', {3: "Ut1_1"})
-    check('class', '@a::A', {3: "NUt1_a1AE"})
 
 
 def test_templates():
@@ -709,9 +704,6 @@ def test_attributes():
     check('function', 'static inline __attribute__(()) void f()',
           {1: 'f', 2: '1fv'},
           output='__attribute__(()) static inline void f()')
-    check('function', '[[attr1]] [[attr2]] void f()',
-          {1: 'f', 2: '1fv'},
-          output='[[attr1]] [[attr2]] void f()')
     # position: declarator
     check('member', 'int *[[attr]] i', {1: 'i__iP', 2:'1i'})
     check('member', 'int *const [[attr]] volatile i', {1: 'i__iPVC', 2: '1i'},