Bug 114165 - &scalar+1 and array+1 rejected as template parameters
Summary: &scalar+1 and array+1 rejected as template parameters
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 14.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2024-02-29 11:34 UTC by наб
Modified: 2024-04-17 06:28 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description наб 2024-02-29 11:34:05 UTC
Given:
    void consoom(void(*)());
    
    template<int *, unsigned>
    void withN() {}
    
    template<int *, int *>
    void withP() {}
    
    
    static int scalar;
    static int array[1];
    
    
    int main() {
        consoom(withN<&scalar, 1>);
        consoom(withN<array,   1>);
        consoom(withP<&scalar, &scalar + 1>);
        consoom(withP<array,   array + 1>);
    }
clang trunk and gcc trunk -std=c++{11,14,17} agree that 
    <source>: In function 'int main()':
    <source>:17:12: error: no matches converting function 'withP' to type 'void (*)()'
       17 |     consoom(withP<&scalar, &scalar + 1>);
          |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    <source>:7:6: note: candidate is: 'template<int* <anonymous>, int* <anonymous> > void withP()'
        7 | void withP() {}
          |      ^~~~~
    <source>:18:12: error: no matches converting function 'withP' to type 'void (*)()'
       18 |     consoom(withP<array,   array + 1>);
          |     ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
    <source>:7:6: note: candidate is: 'template<int* <anonymous>, int* <anonymous> > void withP()'
        7 | void withP() {}
          |      ^~~~~
    Compiler returned: 1
or
    <source>:17:5: error: no matching function for call to 'consoom'
       17 |     consoom(withP<&scalar, &scalar + 1>);
          |     ^~~~~~~
    <source>:1:6: note: candidate function not viable: no overload of 'withP' matching 'void (*)()' for 1st argument
        1 | void consoom(void(*)());
          |      ^       ~~~~~~~~~
    <source>:18:5: error: no matching function for call to 'consoom'
       18 |     consoom(withP<array,   array + 1>);
          |     ^~~~~~~
    <source>:1:6: note: candidate function not viable: no overload of 'withP' matching 'void (*)()' for 1st argument
        1 | void consoom(void(*)());
          |      ^       ~~~~~~~~~
    2 errors generated.
    Compiler returned: 1

clang trunk -std=c++20 accepts the code.
GCC trunk -std=c++20 rejects the code with the same error.

https://godbolt.org/z/63xzf1MT6

Per my reading of [temp.arg.nontype].6, this is allowed in C++20 because it's not rejected by [temp.arg.nontype].6.{1,2,3,4,5}.
Comment 1 Drea Pinski 2024-03-01 18:42:26 UTC
<source>:17:32: error: '((& scalar) + 4)' is not a valid template argument for 'int*' because it is not the address of a variable
Comment 2 Drea Pinski 2024-03-01 18:49:04 UTC
Reduced testcase:
```
template<int *, int *>
void withP() {}
int array[2];
int main() {
  withP<array, array+1>();
  withP<array, &array[1]>();
}
```

GCC and MSVC both reject `array+1` .
All three accept `&array[1]` though in C++20+.