[LLVMbugs] [Bug 14154] New: Constant expression with function pointer cannot be used as non-type template argument

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Tue Oct 23 05:04:37 PDT 2012


http://llvm.org/bugs/show_bug.cgi?id=14154

             Bug #: 14154
           Summary: Constant expression with function pointer cannot be
                    used as non-type template argument
           Product: clang
           Version: trunk
          Platform: Macintosh
        OS/Version: MacOS X
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++11
        AssignedTo: unassignedclangbugs at nondot.org
        ReportedBy: jonathan.sauer at gmx.de
                CC: dgregor at apple.com, llvmbugs at cs.uiuc.edu
    Classification: Unclassified


The following program fails to compile with clang r166410:

// Identity function
template <typename T>
constexpr T identity(T t) { return t; }

// Some template
template <typename T, T t>
struct Foo { };

// Overloaded function. Getting its address requires explicit type
// conversion (13.4p1)
static void bar() {}
static void bar(int) {}

using BarPtr = void(*)();

// Show that "identity((BarPtr) &bar)" is a compile-time constant
// expression
static constexpr BarPtr BAR = identity((BarPtr) &bar);

int main()
{
    Foo<int, identity(1)>                a;    // A: Compiles
    Foo<BarPtr, &bar>                    b;    // B: Compiles
    Foo<BarPtr, (BarPtr) &bar>           c;    // C: Does not compile
    Foo<BarPtr, identity((BarPtr) &bar)> d;    // D: Does not compile
}


This results in:

% ~/LLVM/build/Release+Asserts/bin/clang++ -std=c++11 -stdlib=libc++ clang.cpp
clang.cpp:24:17: error: non-type template argument does not refer to any
declaration
    Foo<BarPtr, (BarPtr) &bar>           c;    // C: Does not compile
                ^~~~~~~~~~~~~
clang.cpp:6:25: note: template parameter is declared here
template <typename T, T t>
                        ^
clang.cpp:25:17: error: non-type template argument does not refer to any
declaration
    Foo<BarPtr, identity((BarPtr) &bar)> d;    // D: Does not compile
                ^~~~~~~~~~~~~~~~~~~~~~~
clang.cpp:6:25: note: template parameter is declared here
template <typename T, T t>
                        ^
2 errors generated.


It seems that clang rejects a function pointer as a non-type template parameter
when this function pointer is not used stand-alone, but as part of a bigger
constant expression, which here is either the explicit type cast to select the
correct overload in case C (c.f. 13.4p1 and 5.4), or the call to a constexpr
function in case D. This only seems to happen with function pointers, not with
integral constant expressions, as case A compiles successfully.

According to 14.3.2p1, "a template-argument for a non-type, non-template
template-parameter shall be one of: [...] a constant expression (5.19) that
designates the address of an object with static storage duration and external
or internal linkage or a function with external or internal linkage".

According to 5.19p2, a constant expression can contain constexpr function as
long as some restrictions are met (which they are, as the definition of "BAR"
compiles).

(I am aware that a workaround for case C is to leave out the explicit type
cast, because in that case the correct overload of "bar" is selected via the
type of the non-type template parameter as shown in case B.)

This is possibly related to the (fixed) Bug 9700.

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list