5.12.5.2.2.2.1.3.7. Finish the derived RECORD_TYPE – verify methods
Next, some fix may need be done if t is the derived type. Recall that in C++, once declaring a method as virtual in the base class, later all overrides are considered as virtual too no matter you declare them as virtual or not. And certain semantic check is expected as now we can see both the derived class and base class.
check_bases_and_members (continue)
4175 /* Check all the method declarations. */
4176 check_methods (t);
4177
4178 /* A nearly-empty class has to be vptr-containing; a nearly empty
4179 class contains just a vptr. */
4180 if (!TYPE_CONTAINS_VPTR_P (t))
4181 CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
4182
4183 /* Do some bookkeeping that will guide the generation of implicitly
4184 declared member functions. */
4185 TYPE_HAS_COMPLEX_INIT_REF (t)
4186 |= (TYPE_HAS_INIT_REF (t)
4187 || TYPE_USES_VIRTUAL_BASECLASSES (t)
4188 || TYPE_POLYMORPHIC_P (t));
4189 TYPE_NEEDS_CONSTRUCTING (t)
4190 |= (TYPE_HAS_CONSTRUCTOR (t)
4191 || TYPE_USES_VIRTUAL_BASECLASSES (t)
4192 || TYPE_POLYMORPHIC_P (t));
4193 CLASSTYPE_NON_AGGREGATE (t) |= (TYPE_HAS_CONSTRUCTOR (t)
4194 || TYPE_POLYMORPHIC_P (t));
4195 CLASSTYPE_NON_POD_P (t)
4196 |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
4197 || TYPE_HAS_ASSIGN_REF (t));
4198 TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
4199 TYPE_HAS_COMPLEX_ASSIGN_REF (t)
4200 |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
4201
4202 /* Synthesize any needed methods. Note that methods will be synthesized
4203 for anonymous unions; grok_x_components undoes that. */
4204 add_implicitly_declared_members (t, cant_have_default_ctor,
4205 cant_have_const_ctor,
4206 no_const_asn_ref);
DECL_VINDEX below if nonzero, points to a FUNCTION_DECL in a base class by which the FUNCTION_DECL (i.e., x ) will replace as a virtual function. Then TYPE_POLYMORPHIC_P for the class should be set to indicate it contain virtual method. Further if the method is the pure virtual (DECL_PURE_VIRTUAL_P returns nonzero), the class should be chained by CLASSTYPE_PURE_VIRTUALS, as classes of this kind can’t be instantiated.
3770 static void
3771 check_methods (tree t) in class.c
3772 {
3773 tree x;
3774
3775 for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
3776 {
3777 /* If this was an evil function, don't keep it in class. */
3778 if (DECL_ASSEMBLER_NAME_SET_P (x)
3779 && IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
3780 continue ;
3781
3782 check_for_override (x, t);
3783 if (DECL_PURE_VIRTUAL_P (x) && ! DECL_VINDEX (x))
3784 cp_error_at ("initializer specified for non-virtual method `%D'", x);
3785
3786 /* The name of the field is the original field name
3787 Save this in auxiliary field for later overloading. */
3788 if (DECL_VINDEX (x))
3789 {
3790 TYPE_POLYMORPHIC_P (t) = 1;
3791 if (DECL_PURE_VIRTUAL_P (x))
3792 CLASSTYPE_PURE_VIRTUALS (t)
3793 = tree_cons (NULL_TREE, x, CLASSTYPE_PURE_VIRTUALS (t));
3794 }
3795 }
3796 }
For normal method, semantic check carried during its parsing is good enough. However there is an exception, in C++, if a method is declared as virtual in base class, its overload is virtual one too in derived class even if it is not declared as virtual there. This fix is done by check_for_override .
2423 static void
2424 check_for_override (tree decl, tree ctype) in class.c
2425 {
2426 if (TREE_CODE (decl) == TEMPLATE_DECL)
2427 /* In [temp.mem] we have:
2428
2429 A specialization of a member function template does not
2430 override a virtual function from a base class. */
2431 return ;
2432 if ((DECL_DESTRUCTOR_P (decl)
2433 || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))
2434 || DECL_CONV_FN_P (decl))
2435 && look_for_overrides (ctype, decl)
2436 && !DECL_STATIC_FUNCTION_P (decl))
2437 /* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
2438 the error_mark_node so that we know it is an overriding
2439 function. */
2440 DECL_VINDEX (decl) = decl;
2441
2442 if (DECL_VIRTUAL_P (decl))
2443 {
2444 if (!DECL_VINDEX (decl))
2445 DECL_VINDEX (decl) = error_mark_node;
2446 IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
2447 }
2448 }
DECL_DESTRUCTOR_P is nonzero if the node is a destructor, and DECL_CONV_FN_P is nonzero if the node is a user-defined conversion operator, and IDENTIFIER_VIRTUAL_P is nonzero if this identifier is used as a virtual function name somewhere. We checks for these 3 cases is because unlike normal virtual method which name is same in during derivation, and has IDENTIFIER_VIRTUAL_P set as long as any declaration is declared as virtual; destructor and user-defined conversion operator must have different name in derived class.
1849 int
1850 look_for_overrides (tree type, tree fndecl) in search.c
1851 {
1852 tree binfo = TYPE_BINFO (type);
1853 tree basebinfos = BINFO_BASETYPES (binfo);
1854 int nbasebinfos = basebinfos ? TREE_VEC_LENGTH (basebinfos) : 0;
1855 int ix;
1856 int found = 0;
1857
1858 for (ix = 0; ix != nbasebinfos; ix++)
1859 {
1860 tree basetype = BINFO_TYPE (TREE_VEC_ELT (basebinfos, ix));
1861
1862 if (TYPE_POLYMORPHIC_P (basetype))
1863 found += look_for_overrides_r (basetype, fndecl);
1864 }
1865 return found;
1866 }
TYPE_POLYMORPHIC_P is nonzero if and only if a class declares or inherits a virtual function. It tells us which base class should be looked into for searching the virtual declaration.
1909 static int
1910 look_for_overrides_r (tree type, tree fndecl) in search.c
1911 {
1912 tree fn = look_for_overrides_here (type, fndecl);
1913 if (fn)
1914 {
1915 if (DECL_STATIC_FUNCTION_P (fndecl))
1916 {
1917 /* A static member function cannot match an inherited
1918 virtual member function. */
1919 cp_error_at ("`%#D' cannot be declared", fndecl);
1920 cp_error_at (" since `%#D' declared in base class", fn);
1921 }
1922 else
1923 {
1924 /* It's definitely virtual, even if not explicitly set. */
1925 DECL_VIRTUAL_P (fndecl) = 1;
1926 check_final_overrider (fndecl, fn);
1927 }
1928 return 1;
1929 }
1930
1931 /* We failed to find one declared in this class. Look in its bases. */
1932 return look_for_overrides (type, fndecl);
1933 }
See that if look_for_overrides_here finds out the specified virtual function declaration in base, the declaration we interesting here is tagged as virtual at line 1925.
1871 tree
1872 look_for_overrides_here (tree type, tree fndecl) in search.c
1873 {
1874 int ix;
1875
1876 if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (fndecl))
1877 ix = CLASSTYPE_DESTRUCTOR_SLOT;
1878 else
1879 ix = lookup_fnfields_1 (type, DECL_NAME (fndecl));
1880 if (ix >= 0)
1881 {
1882 tree fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix);
1883
1884 for (; fns; fns = OVL_NEXT (fns))
1885 {
1886 tree fn = OVL_CURRENT (fns);
1887
1888 if (!DECL_VIRTUAL_P (fn))
1889 /* Not a virtual. */;
1890 else if (DECL_CONTEXT (fn) != type)
1891 /* Introduced with a using declaration. */;
1892 else if (DECL_STATIC_FUNCTION_P (fndecl))
1893 {
1894 tree btypes = TYPE_ARG_TYPES (TREE_TYPE (fn));
1895 tree dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
1896 if (compparms (TREE_CHAIN (btypes), dtypes))
1897 return fn;
1898 }
1899 else if (same_signature_p (fndecl, fn))
1900 return fn;
1901 }
1902 }
1903 return NULL_TREE;
1904 }
It is possible that user defines a virtual method in base class, and then overrides it as static method in derived one. For the case, look_for_overrides_here must be able to find out the base virtual one as requested. However, such definition is not allowed in C++, it is complained by look_for_overrides_r immediately after invoking look_for_overrides_here .
Even for non-static method, some rules should be obeyed to be a validate overrides for virtual base method. First, the returned type of both methods must be compatible. They are either the same, or the type returned by base method is also the base for the type returned by derived one, and both have the same cv-qualifier and reference level. Next, both should throw out the compatible exception.
1743 int
1744 check_final_overrider (tree overrider, tree basefn) in search.c
1745 {
1746 tree over_type = TREE_TYPE (overrider);
1747 tree base_type = TREE_TYPE (basefn);
1748 tree over_return = TREE_TYPE (over_type);
1749 tree base_return = TREE_TYPE (base_type);
1750 tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
1751 tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
1752 int fail = 0;
1753
1754 if (same_type_p (base_return, over_return))
1755 /* OK */;
1756 else if ((CLASS_TYPE_P (over_return) && CLASS_TYPE_P (base_return))
1757 || (TREE_CODE (base_return) == TREE_CODE (over_return)
1758 && POINTER_TYPE_P (base_return)))
1759 {
1760 /* Potentially covariant. */
1761 unsigned base_quals, over_quals;
1762
1763 fail = !POINTER_TYPE_P (base_return);
1764 if (!fail)
1765 {
1766 fail = cp_type_quals (base_return) != cp_type_quals (over_return);
1767
1768 base_return = TREE_TYPE (base_return);
1769 over_return = TREE_TYPE (over_return);
1770 }
1771 base_quals = cp_type_quals (base_return);
1772 over_quals = cp_type_quals (over_return);
1773
1774 if ((base_quals & over_quals) != over_quals)
1775 fail = 1;
1776
1777 if (CLASS_TYPE_P (base_return) && CLASS_TYPE_P (over_return))
1778 {
1779 tree binfo = lookup_base (over_return, base_return,
1780 ba_check | ba_quiet, NULL);
1781
1782 if (!binfo)
1783 fail = 1;
1784 }
1785 else if (!pedantic
1786 && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type)))
1787 /* GNU extension, allow trivial pointer conversions such as
1788 converting to void *, or qualification conversion. */
1789 {
1790 /* can_convert will permit user defined conversion from a
1791 (reference to) class type. We must reject them. */
1792 over_return = non_reference (TREE_TYPE (over_type));
1793 if (CLASS_TYPE_P (over_return))
1794 fail = 2;
1795 }
1796 else
1797 fail = 2;
1798 }
1799 else
1800 fail = 2;
1801 if (!fail)
1802 /* OK */;
1803 else if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
1804 return 0;
1805 else
1806 {
1807 if (fail == 1)
1808 {
1809 cp_error_at ("invalid covariant return type for `%#D'", overrider);
1810 cp_error_at (" overriding `%#D'", basefn);
1811 }
1812 else
1813 {
1814 cp_error_at ("conflicting return type specified for `%#D'",
1815 overrider);
1816 cp_error_at (" overriding `%#D'", basefn);
1817 }
1818 SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
1819 DECL_CONTEXT (overrider));
1820 return 0;
1821 }
1822
1823 /* Check throw specifier is at least as strict. */
1824 if (!comp_except_specs (base_throw, over_throw, 0))
1825 {
1826 if (!IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider)))
1827 {
1828 cp_error_at ("looser throw specifier for `%#F'", overrider);
1829 cp_error_at (" overriding `%#F'", basefn);
1830 SET_IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (overrider),
1831 DECL_CONTEXT (overrider));
1832 }
1833 return 0;
1834 }
1835
1836 return 1;
1837 }