Bug 51851 (cwg1001)

Summary: [core/1001] Overriding a function with a parameter of dependent type fails to override.
Product: gcc Reporter: Ville Voutilainen <ville.voutilainen>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: SUSPENDED ---    
Severity: normal CC: daniel.kruegler, jason, nickhuang99, webrown.cpp
Priority: P3 Keywords: rejects-valid
Version: 4.7.0   
Target Milestone: ---   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102039
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2012-01-13 00:00:00
Bug Depends on:    
Bug Blocks: 94404    

Description Ville Voutilainen 2012-01-13 19:01:53 UTC
Test snippet:

template<class T>
struct A
{
       typedef double Point[2];
       virtual double calculate(const Point point) const = 0;
};

template<class T>
struct B : public A<T>
{
       virtual double calculate(const typename A<T>::Point point) const
       {
               return point[0];
       }
};

int main()
{
       B<int> b;
       return 0;
}

gcc says
ville.cpp: In function ‘int main()’:
ville.cpp:19:16: error: cannot declare variable ‘b’ to be of abstract type ‘B<int>’
ville.cpp:9:8: note:   because the following virtual functions are pure within ‘B<int>’:
ville.cpp:5:24: note: 	double A<T>::calculate(const double*) const [with T = int]
Comment 1 Ville Voutilainen 2012-01-13 19:13:13 UTC
Johannes Schaub says "in both situations the question is whether the parameter type adjustments happen immediately or after instantiation (when T is replaced by the actual type)", regarding the possibility that
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49051
is related.
Comment 2 Jason Merrill 2012-01-13 20:49:44 UTC
This is core issue 1001; see my reply in CWG.
Comment 3 Marek Polacek 2021-07-12 16:57:37 UTC
*** Bug 101402 has been marked as a duplicate of this bug. ***
Comment 4 qingzhe huang 2021-08-23 12:31:56 UTC
At least since release/gcc-10, this test code has been successfully compiled. Can we change its status to Resolved?
Comment 5 Jonathan Wakely 2021-08-23 13:41:55 UTC
The example in CWG 1001 still doesn't compile (as you noted in PR 101402) and CWG 1001 is still open. So no, this shouldn't be closed as resolved yet.
Comment 6 Jonathan Wakely 2021-08-23 13:43:27 UTC
The case here is accepted since r10-7622:

c++: Function type and parameter type disagreements [PR92010]

This resolves parts of Core issues 1001/1322 by rebuilding the function type
of an instantiated function template in terms of its formal parameter types
whenever the original function type and formal parameter types disagree about
the type of a parameter after substitution.
Comment 7 qingzhe huang 2021-08-23 14:10:37 UTC
Thank you for clarifications!

I just found a solution for this 10-year-old issue and preparing a patch. However, the solution is not able to solve more complicated cases which requires more work.
This issue is so complicated and I am hesitating to file more complicated bugs which this patch won't work because it requires improvement work of function *resolve_typename_type* to handle recursive case correctly.



diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 3414cbdc876..db0d43b2b08 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14493,7 +14493,16 @@ grokparms (tree parmlist, tree *parms)
 
          /* Top-level qualifiers on the parameters are
             ignored for function types.  */
-         type = cp_build_qualified_type (type, 0);
+         int type_quals = 0;
+         /* Top-level qualifiers are reserved for array type. PR101783 */
+         if (TREE_CODE (type) == TYPENAME_TYPE)
+         {
+            tree resolved_type = resolve_typename_type(type, false);
+            if (resolved_type && TREE_CODE(resolved_type) == ARRAY_TYPE)
+               type_quals = CP_TYPE_CONST_P(type);
+         }
+         type = cp_build_qualified_type (type, type_quals);
+
          if (TREE_CODE (type) == METHOD_TYPE)
            {
              error ("parameter %qD invalidly declared method type", decl);
Comment 8 GCC Commits 2021-10-15 21:00:40 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:79802c5dcc043a515f429bb2bec7573b8537c32a

commit r12-4453-g79802c5dcc043a515f429bb2bec7573b8537c32a
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Sep 28 10:02:04 2021 -0400

    c++: array cv-quals and template specialization [PR101402]
    
    PRs 101402, 102033, etc. demonstrated that the fix for PR92010 wasn't
    handling all cases of the CWG1001/1322 issue with parameter type qual
    stripping and arrays with templates.  The problem turned out to be in
    determine_specialization, which did an extra substitution without the 92010
    fix and then complained that the result didn't match.
    
    But just removing that wrong/redundant code meant that we were accepting
    specializations with different numbers of parameters, because the code in
    fn_type_unification that compares types in this case wasn't checking for
    length mismatch.
    
    After fixing that, I realized that fn_type_unification couldn't tell the
    difference between variadic and non-variadic function types, because the
    args array doesn't include the terminal void we use to indicate non-variadic
    function type.  So I added it, and made the necessary adjustments.
    
    Thanks to qingzhe "nick" huang <nickhuang99@hotmail.com> for the patch that
    led me to dig more into this, and the extensive testcases.
    
            PR c++/51851
            PR c++/101402
            PR c++/102033
            PR c++/102034
            PR c++/102039
            PR c++/102044
    
    gcc/cp/ChangeLog:
    
            * pt.c (determine_specialization): Remove redundant code.
            (fn_type_unification): Check for mismatched length.
            (type_unification_real): Ignore terminal void.
            (get_bindings): Don't stop at void_list_node.
            * class.c (resolve_address_of_overloaded_function): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/fnspec2.C: New test.
            * g++.dg/template/parm-cv1.C: New test.
            * g++.dg/template/parm-cv2.C: New test.
            * g++.dg/template/parm-cv3.C: New test.