[Bug c++/92467] New: gcc miscompiles ternary expression with omitted first operand ?: involving C++ prvalues

st at quanttec dot com gcc-bugzilla@gcc.gnu.org
Mon Nov 11 21:40:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92467

            Bug ID: 92467
           Summary: gcc miscompiles ternary expression with omitted first
                    operand ?: involving C++ prvalues
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: st at quanttec dot com
  Target Milestone: ---

The current trunk version of GCC miscompiles the following code involving a
ternary expression with omitted first operand ("elvis operator"). Compiled with
`g++-9 --std=c++2a` the program prints "deleting: 1" followed by "result: 1".
The same code compiled with clang doesn't erroneously call the deleter
function.

(Note that such use of the ternary operator in C++ will become increasingly
common:
https://stackoverflow.com/questions/58368012/how-to-enable-the-c-c-conditional-with-omitted-operand-aka-elvis-operator
)


#include <memory>
#include <iostream>

#define NOINLINE __attribute__ ((noinline))

struct Deleter {    
    NOINLINE void operator()(void* p) {
        std::cout << "deleting: " << (uintptr_t)p << std::endl;
    }
};

NOINLINE std::unique_ptr<void, Deleter> get1() {
    return std::unique_ptr<void, Deleter>{(void*)1};
}
NOINLINE std::unique_ptr<void, Deleter> get2() {
    return std::unique_ptr<void, Deleter>{(void*)2};
}

NOINLINE void* test() {
    return (get1() ?: get2()).release();
}

int main() {
    uintptr_t result = (uintptr_t)test();
    std::cout << "result: " << result;
    return 0;
}


More information about the Gcc-bugs mailing list