[LLVMbugs] [Bug 22668] New: Inconsistent rules for parenthesizing bound functions

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Mon Feb 23 14:20:38 PST 2015


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

            Bug ID: 22668
           Summary: Inconsistent rules for parenthesizing bound functions
           Product: clang
           Version: 3.5
          Hardware: Macintosh
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
          Assignee: unassignedclangbugs at nondot.org
          Reporter: alexandermbock at gmail.com
                CC: dgregor at apple.com, llvmbugs at cs.uiuc.edu
    Classification: Unclassified

Neither [expr.pseudo] (Example 1) nor [expr.mptr.oper] (Example 2) explicitly
states whether or not enclosing their "bound callable" expressions in
parentheses is acceptable (though [expr.mptr.oper] contains a (non-normative)
example of calling a pointer to member function using parentheses). Despite
almost identical wording for the requirement that .*/->*/.~ be used to perform
a call, clang requires parentheses for pointer to member function calls but
does not allow them for pseudo destructor calls.

Additionally, I'm not clear from the wording of the standard if an uncalled
bound function is permitted as the expression of an expression statement
(mainly because I see no wording that allows parentheses explicitly, so
presumably this is also a valid expression in other places where it is not
"used" -- this depends heavily on how one interprets "can be used in exactly
the same contexts", which I would intuitively take as waiver of the
requirements a context imposes on its operand, but not vice versa).

>From [expr.pseudo]:
"The use of a pseudo-destructor-name after a dot . or arrow -> operator
represents the destructor for the non-class type denoted by type-name or
decltype-specifier. The result shall only be used as the operand for the
function call operator (), and the result of such a call has type void."

>From [expr.mptr.oper]:
"If the result of .* or ->* is a function, then that result can be used only as
the operand for the function call operator ()."

>From [expr.prim.general]:
"A parenthesized expression is a primary expression whose type and value are
identical to those of the enclosed expression. The presence of parentheses does
not affect whether the expression is an lvalue. The parenthesized expression
can be used in exactly the same contexts as those where the enclosed expression
can be used, and with the same meaning, except as otherwise indicated."

Example 1:

typedef int I;

void f(int i) {
    i.~I(); // accepted
    (i.~I)(); // error: pseudo-destructor expression
              // must be called immediately with '()'
}

==
Example 2:
==

struct X;

void f(X& x) {
    void (X::*p)();
    // x.*p(); // this isn't an option due to the precedence rules
    (x.*p)(); // accepted, even though the similar case in the pseudo
destructor example is not

    x.*p; // error: reference to non-static member function must be called;
          // did you mean to call it with no arguments?
}



Given that gcc and edg both consider the use as an expression statement illegal
but allow extra parentheses around a pseudo destructor expression, I think the
most reasonable resolution is probably to allow (i.~I)().

-- 
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/20150223/5164c7d6/attachment.html>


More information about the llvm-bugs mailing list