microsoft / vscode-cpptools

Official repository for the Microsoft C/C++ extension for VS Code.
Other
5.52k stars 1.55k forks source link

static_assert ignored in SFINAE and operator ==, != issues #5163

Open diggit opened 4 years ago

diggit commented 4 years ago

Type: LanguageService

Describe the bug

Steps to reproduce

c_cpp_propertis.json

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/clang",
            "intelliSenseMode": "clang-x64",
            "configurationProvider": "vector-of-bool.cmake-tools"
        }
    ],
    "version": 4
}

for quick access cpp file in gist also attached in zip

Verify, that template works as expected static_list flags in Derived class tells Base class which asserts deactivate and thus enable some operators

  1. try to compile flagtest with gcc (tested 9.2.1)/clang (tested 9.0) with --std=c++2a everything works as expected
  2. uncomment line 78 a <= b;
  3. compile, compilation fails on static_assert as expected
  4. add OperatorRequirements::LEQ to list in line 65, this enables operator <= by deactivating static_assert
  5. compile, compilation succeeeds, as expected -> templates works as intended

vscode behavior

  1. get flags.cpp into original state
  2. uncomment lines 77~80
  3. observe vscode info about operators: a) a < b; vscode does no complain (OK), compiles (OK) b) a <= b; vscode does no complain (wrong, operator does not exist due to static_assert), compilation fails due to static_assert on line 52 (OK) c) a == b vscode complains:
    more than one operator "==" matches these operands:
    -- function "Base<Derived>::operator==(const Derived &rhs) const [with Derived=Child]" (with reversed arguments)
    -- function "Base<Derived>::operator==(const Derived &rhs) const [with Derived=Child]"
    -- operand types are: Child == Child

    Compiles fine

d) a!=b vscode complains:

more than one operator "!=" matches these operands:
-- function "Base<Derived>::operator==(const Derived &rhs) const [with Derived=Child]" (with reversed arguments)
-- function "Base<Derived>::operator==(const Derived &rhs) const [with Derived=Child]"
-- operand types are: Child != Child

Compilation fails (g++ error):

../src/flagtest.cpp: In function ‘int main()’:
../src/flagtest.cpp:80:4: error: no match for ‘operator!=’ (operand types are ‘Child’ and ‘Child’)
   80 |  a != b; //vscode complains about multiple != operators (wrong), non of them exist and compilations fails (OK)
      |  ~ ^~ ~
      |  |    |
      |  |    Child
      |  Child

Expected behavior

Logs c_cpp_server_log just commented lines to state when source compiles, nothing interesting there ``` cpptools/getCodeActions: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 451) cpptools/activeDocumentChange: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp cpptools/textEditorSelectionChange cpptools/textEditorSelectionChange idle loop: reparsing the active document Checking for syntax errors: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp Queueing IntelliSense update for files in translation unit of: /home/diggit/dev/flagtest/soclim/src/flagtest.cpp cpptools/cpptools_finishUpdateSquiggles Error squiggle count: 1 Update IntelliSense time (sec): 0.259 Database safe to open tag parsing file: /home/diggit/dev/flagtest/soclim/src/flagtest.cpp cpptools/getDocumentSymbols: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 452) cpptools/getDocumentSymbols Database safe to open cpptools/activeDocumentChange: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp cpptools/textEditorSelectionChange cpptools/textEditorSelectionChange cpptools/getCodeActions: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 453) idle loop: reparsing the active document Checking for syntax errors: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp Queueing IntelliSense update for files in translation unit of: /home/diggit/dev/flagtest/soclim/src/flagtest.cpp textDocument/hover: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 454) cpptools/cpptools_finishUpdateSquiggles Error squiggle count: 1 Update IntelliSense time (sec): 0.264 cpptools/getCodeActions: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 455) textDocument/hover: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 456) textDocument/hover: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 457) cpptools/getCodeActions: file:///home/diggit/dev/flagtest/soclim/src/flagtest.cpp (id: 458) ```

Screenshots image

diggit commented 4 years ago

Here is minimal example code, without those template tricks. Line numbers does not match, otherwise same behavior.

template<typename Derived>
struct Base {

    bool operator<(Derived const& rhs) const {
        static_assert(true, "Your type must add this requirement.");
        auto& me = static_cast<const Derived&>(*this);
        return me.value < rhs.value;
    }

    bool operator<=(Derived const& rhs) const {
        static_assert(false, "Your type must add this requirement.");
        auto& me = static_cast<const Derived&>(*this);
        return me.value <= rhs.value;
    }

    bool operator==(Derived const& rhs) const {
        static_assert(true , "Your type must add this requirement.");
        auto& me = static_cast<const Derived&>(*this);
        return me.value == rhs.value;
    }
};

struct Child : Base<Child> {
    friend Base;

    protected:
        int value;
};

int main(void) {

    Child a, b;

    a < b; //vscode does no complain (OK), compiles (OK)
    a <= b; //vscode does no complain (wrong), compilation fails due to static_assert on line 52 (OK)
    a == b; //vscode complains about multiple == operators, compler does not, compiles (OK)
    a != b; //vscode complains about multiple != operators (wrong), non of them exist and compilations fails (OK)

    return 0;
}
diggit commented 4 years ago

Relevant lines from cmake:

add_compile_options(-Wall -pedantic -Og -g)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Weffc++>)
set_target_properties(${PROJECT_NAME} PROPERTIES CXX_STANDARD 20)
sean-mcmanus commented 4 years ago

Thanks for reporting this. The issues comes from code in VS, so I've filed a bug at https://developercommunity.visualstudio.com/content/problem/959748/cc-intellisense-static-assert-ignored-in-sfinae-an.html .