Bug 116239 - Different function redeclaration in function scope is wrongly accepted
Summary: Different function redeclaration in function scope is wrongly accepted
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 14.1.1
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2024-08-05 13:41 UTC by Fedor Chelnokov
Modified: 2024-09-05 15:24 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.8.1
Last reconfirmed: 2024-08-05 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fedor Chelnokov 2024-08-05 13:41:01 UTC
This is an invalid program
```
void f(void);

int main() {
    consteval void f(void); 
}
```
because of function f redeclaration with consteval. It is rejected in Clang and MSVC, but not in GCC unfortunately. Online demo: https://gcc.godbolt.org/z/n8x49h8Wa

Expected error: redeclaration 'consteval void f()' differs in 'consteval' from previous declaration
Comment 1 Drea Pinski 2024-08-05 15:56:53 UTC
```
void f(void);

int main() {
    constexpr void f(void); 
}
```

Also.
Comment 2 Marek Polacek 2024-08-30 14:23:39 UTC
We have validate_constexpr_redeclaration that should have detected this.
Comment 3 Marek Polacek 2024-08-30 17:21:33 UTC
We never call duplicate_decls -> validate_constexpr_redeclaration because decls_match doesn't look at decl-specifiers like constexpr/consteval.

        for (ovl_iterator iter (binding); iter; ++iter)
          if (decls_match (decl, *iter, /*record_versions*/false))
            {    
              alias = *iter;
              break;
            }

so they're just aliases.
Comment 4 Marek Polacek 2024-08-30 17:57:29 UTC
Eh, let's fix this simply in push_local_extern_decl_alias.
Comment 5 GCC Commits 2024-09-05 15:21:20 UTC
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:d44cae2d9310660e3e47f15202e86e4f73f15b37

commit r15-3489-gd44cae2d9310660e3e47f15202e86e4f73f15b37
Author: Marek Polacek <polacek@redhat.com>
Date:   Fri Aug 30 14:12:22 2024 -0400

    c++: fn redecl in fn scope wrongly accepted [PR116239]
    
    Redeclaration such as
    
      void f(void);
      consteval void f(void);
    
    is invalid.  In a namespace scope, we detect the collision in
    validate_constexpr_redeclaration, but not when one declaration is
    at block scope.
    
    When we have
    
      void f(void);
      void g() { consteval void f(void); }
    
    we call pushdecl on the second f and call push_local_extern_decl_alias.
    It finds the namespace-scope f:
    
            for (ovl_iterator iter (binding); iter; ++iter)
              if (decls_match (decl, *iter, /*record_versions*/false))
                {
                  alias = *iter;
                  break;
                }
    
    but decls_match says they match so we just set DECL_LOCAL_DECL_ALIAS
    (and do not call another pushdecl leading to duplicate_decls which
    would detect mismatching return types, for example).  I don't think
    we want to change decls_match, so a simple fix is to detect the
    problem in push_local_extern_decl_alias.
    
            PR c++/116239
    
    gcc/cp/ChangeLog:
    
            * cp-tree.h (validate_constexpr_redeclaration): Declare.
            * decl.cc (validate_constexpr_redeclaration): No longer static.
            * name-lookup.cc (push_local_extern_decl_alias): Call
            validate_constexpr_redeclaration.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/diagnostic/redeclaration-6.C: New test.
Comment 6 Marek Polacek 2024-09-05 15:24:24 UTC
Fixed.