[llvm-bugs] [Bug 30547] New: Invalid __restrict__s on non-pointer, non-reference types in templates are not always diagnosed.

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Sep 27 22:38:37 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=30547

            Bug ID: 30547
           Summary: Invalid __restrict__s on non-pointer, non-reference
                    types in templates are not always diagnosed.
           Product: clang
           Version: trunk
          Hardware: Other
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
          Assignee: unassignedclangbugs at nondot.org
          Reporter: blelbach at cct.lsu.edu
                CC: dgregor at apple.com, llvm-bugs at lists.llvm.org
    Classification: Unclassified

Hello Clang and LLVM peoples!

This is very much a corner case and I don't think it's particularly high
priority.

-------------------------------------------------------------------------------

My vitals:

    OS: Compute Node Linux (CNL)
    Kernel: Linux 3.0.101-0.35.1_1.0502.8640-cray_ari_c 
    Platform: Edison, Cray XC30, 2x Intel Xeon E5-2695 v2 and 64GB DDR3 per
node 

    Clang Version:          4.0.0 (SVN revision 282553)
    LLVM Version:           4.0.0 (SVN revision 282554)
    GNU Binutils:           2.23.1
    glibc Version:          2.2.5
    libc++ Version:         SVN revision 282546
    libc++abi Version:      SVN revision 282547
    compiler-rt Version:    SVN revision 282545

-------------------------------------------------------------------------------

Lemma 0: Adding __restrict__ to a non-pointer, non-reference type is silly.

Clang agrees with me:

    $ clang++ -std=c++11 -c restrict_on_template_parameters0.cpp -o /dev/null
    restrict_on_template_parameters0.cpp:2:16: error: restrict requires a
pointer or reference ('double' is invalid)
    void g(double  __restrict__) {}
                   ^
    1 error generated.

Okay, but what if we have some template:

    template <typename X>
    void h(X __restrict__) {}

Is this okay? Well, that depends on X. h<double*> is fine, but h<double> should
be ill-formed.

Let's look at what happens when we call h(3.14):

    $ clang++ -std=c++11 -c restrict_on_template_parameters1.cpp -o /dev/null
    restrict_on_template_parameters1.cpp:6:5: error: no matching function for
call to 'h'
        h(3.14); // ILL-FORMED. 
        ^
    restrict_on_template_parameters1.cpp:2:6: note: candidate template ignored:
substitution failure [with X = double]: restrict requires a pointer or
reference ('double' is invalid)
    void h(X __restrict__) {}
         ^ ~
    1 error generated.

Okay, good. Clang rejects it, and gives us a useful error message.

Suppose we want to do something more complicated, like create a function
pointer
to h:

    auto fp0 = h<double*>; // Ok.
    auto fp1 = h<double>;  // ILL-FORMED.

Clang gets this right, but...

    $ clang++ -std=c++11 -c restrict_on_template_parameters2.cpp -o /dev/null
    restrict_on_template_parameters2.cpp:7:10: error: variable 'fp1' with type
'auto' has incompatible initializer of type '<overloaded function type>'
        auto fp1 = h<double>;  // ILL-FORMED: Compiler thinks h<double> is
overloaded.
             ^     ~~~~~~~~~
    1 error generated.

The error we get is not particularly useful!

We get the same unclear diagnostic when trying to pass h to another function
that
takes a Callable as a template parameter:

    template <typename Func>
    void i(Func func) {}

    i(h<double>);

Clang still rejects it, but now things are even more cryptic:

    $ clang++ -std=c++11 -c restrict_on_template_parameters3.cpp -o /dev/null
    restrict_on_template_parameters3.cpp:9:5: error: no matching function for
call to 'i'
        i(h<double>);
        ^
    restrict_on_template_parameters3.cpp:5:6: note: candidate template ignored:
couldn't infer template argument 'Func'
    void i(Func func) {}
         ^
    1 error generated.

I encountered this final error when compiling one of my small benchmarks with
Clang. I reduced the problem to restrict_on_template_parameters3.cpp and then
wrote the other two simplified test cases.

You might be wondering "Why did you have X __restrict__ in your code, that's
nonsense on non-pointer, non-reference types?". Originally the function in
question took __restrict__ed pointers and an index that was applied to all
those pointers.  Sadly, my Other Vectorizing Compiler had /issues/ with this.
To get the code gen I wanted, I had to rewrite those functions to take
__restrict__ed references.

Since the template parameter X was always either float or double for these
functions, I decided the arguments that I was passing by const reference should
instead be passed by value (because value-semantics!). E.g. X const&
__restrict__ -> X. When I implemented this change, what I actually did was X
const& __restrict__ -> X __restrict__.  My Other Vectorizing Compiler allowed
this code, and I ended up here.

Suggested resolution: It appears that Clang diagnoses and rejects __restrict__
on non-pointer and non-reference types upon the instantiation of a template in
some cases, but not all. In the cases where we don't currently catch it, we run
into overload resolution problems later. We should make sure to always catch
these early (on instantiation of a template that would form a non-pointer,
non-reference type with a __restrict__ attribute) and diagnose them well.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160928/f35099a3/attachment-0001.html>


More information about the llvm-bugs mailing list