Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intellisense incorrectly identifies pow() as a non-constexpr, which causes constexpr functions containing pow() to incorrectly show an error #13122

Open
twfry opened this issue Jan 7, 2025 · 6 comments
Labels
bug Language Service Visual Studio Inherited from Visual Studio
Milestone

Comments

@twfry
Copy link

twfry commented Jan 7, 2025

Environment

  • OS and Version: Windows 11
  • VS Code Version: v1.96.2
  • C/C++ Extension Version: v1.22.11
  • If using SSH remote, specify OS of remote machine: Running on Remote Explorer on Ubuntu 22.04 using g++ v11.4.0 and c++20

Bug Summary and Steps to Reproduce

Bug Summary:
We have a constexpr function that contains the math function pow(). This compiles fine on g++ however Intellisense shows an error, the error reported is "cannot call non-constexpr function "__builtin_powf" (declared implicitly)". However the code compiles cleanly and works as expected.

Steps to reproduce:
Simplified example

constexpr std::array<float, 256> gen_lut() {
    std::array<float, 256> lut = {};
    for (int i = 0; i < 256; ++i) {
        lut[i] = std::pow((2f, static_cast<float>(i));
    }
    return lut;
} 
constexpr auto linear_lut = gen_lut();

The error is reported under the gen_lut(); call in the last line.

Expected behavior:
Intellisense should not report an error. This is valid C++ that compiles on g++ 11.4

Configuration and Logs

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/usr/include",
                "/usr/local/include"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/gcc",
            "cStandard": "c17",
            "cppStandard": "c++20",
            "intelliSenseMode": "linux-gcc-x64",
            "compilerArgs": [
                "-std=c++20"
            ]
        }
    ],
    "version": 4
}

Other Extensions

No response

Additional context

This bug prevents our projects from reporting no error, which impacts development since it is difficult to notice during development when there is an actual bug and we don't notice later till the compilation fails.

@sean-mcmanus sean-mcmanus added bug Language Service Visual Studio Inherited from Visual Studio labels Jan 7, 2025
@sean-mcmanus sean-mcmanus added this to the Tracking milestone Jan 7, 2025
@sean-mcmanus
Copy link
Contributor

@twfry I get the same error when using the clang++ or cl.exe compilers, so it looks like it may be relying on a g++ extension that our IntelliSense compiler doesn't currently emulate.

Your repro code didn't compile as provided, so my modified repro code is

#include <array>
#include <cmath>

constexpr std::array<float, 256> gen_lut() {
    std::array<float, 256> lut = {};
    for (int i = 0; i < 256; ++i) {
        lut[i] = std::pow(2.0f, static_cast<float>(i));
    }
    return lut;
}
constexpr auto linear_lut = gen_lut();

@bobbrow
Copy link
Member

bobbrow commented Jan 7, 2025

This was previously reported in #4736 but closed because EDG doesn't support replacing the parsed header code with the compiler intrinsics. cppreference.com says this won't officially be constexpr until C++26.

@twfry
Copy link
Author

twfry commented Jan 7, 2025

@sean-mcmanus here is a short working example. VSCode shows an error in line 22 over genereate_lut(). However g++ compiles it cleanly with all warnings on.

#include <iostream>
#include <array>
#include <cmath>

// Compile time accelerations

// Compile-time LUT 
constexpr std::array<float, 256> generate_lut() {
    std::array<float, 256> lut = {};
    for (int i = 0; i < 256; ++i) {
        float var = static_cast<float>(i) / 255.0f;
        if (var > 0.04045f) {
            lut[i] = std::pow((var + 0.055f) / 1.055f, 2.4f) * 100.0f;
        } else {
            lut[i] = (var / 12.92f) * 100.0f;
        }
    }
    return lut;
}

// LUT as a constexpr
constexpr auto lut = generate_lut();

int main()
{
    std::cout << lut[10] << std::endl;
    return EXIT_SUCCESS;
} 

Compiles with no warnings or errors using:

g++ -o test -std=c++20 -O2 -Wall -Wextra test.cpp

executes successfully

foo@system:/tank/folder$ ./test
0.303527

@twfry
Copy link
Author

twfry commented Jan 7, 2025

@bobbrow I understand cppreference requires support by c++26, however g++ supports this today. Since VSCode supports Remote Explore and g++ through that, that seems to imply VSCode should support g++ existing capabilities. For us it isn't a blocker to development, but it is a significant annoyance to the point we just turn Intellisense off, which itself is an issue.

@sean-mcmanus
Copy link
Contributor

sean-mcmanus commented Jan 7, 2025

@twfry Yes, our IntelliSense parser is supposed to emulate the gcc behavior. I've filed an internal bug 2333165.

A reduced repro for the issue is

int main()
{
    constexpr double c = __builtin_pow(0.0, 0.0);
}

@twfry
Copy link
Author

twfry commented Jan 7, 2025

Thank you for filing the bug. Yes that is a much better reduced repro.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Language Service Visual Studio Inherited from Visual Studio
Projects
Status: No status
Development

No branches or pull requests

3 participants