MaskRay / ccls

C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting
Apache License 2.0
3.73k stars 254 forks source link

Using MSVC with ccls #875

Open OrangeLightning219 opened 2 years ago

OrangeLightning219 commented 2 years ago

Observed behavior

Hi. I'm trying to use msvc with ccls but ccls keeps using clang for parsing the files. This causes my editor to show an error even though my code compiles fine with msvc.

My .ccls file:

cl
%c -std=c11
%cpp -std=c++2a
%h -x
%h c++-header
-wd4201
-wd4100
-wd4505
-wd4189
-wd4146
-wd4127
-wd4312
-wd4239
-IE:\Tools\glfw\include\GLFW
-IE:\Tools\glad\include

The code that's causing the problem:

struct Vector3
{
    float x, y, z;
    Vector3( float x, float y, float z )
    {
        this->x = x;
        this->y = y;
        this->z = z;
    }
};
inline Vector3 operator-( Vector3 &a, Vector3 &b )
{
    return Vector3( a.x - b.x, a.y - b.y, a.z - b.z );
}

inline Vector3 operator*( Vector3 &v, float s )
{
    return Vector3( v.x * s, v.y * s, v.z * s );
}

inline float Dot( Vector3 &a, Vector3 &b )
{
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

inline Vector3 Reject( Vector3 &a, Vector3 &b )
{
    return a - b * ( Dot( a, b ) / Dot( b, b ) ); // the error is here: invalid operands to binary expression ('Vector3' and 'Vector3')
}

The command I'm using to compile the code:

@echo off

if not exist build mkdir build

set compiler_args=^
-MTd ^
-nologo ^
-GR- ^
-EHa ^
-Od -Oi ^
-WX -W4 ^
-FC ^
-Zi ^
-diagnostics:caret ^
-wd4201 ^
-wd4100 ^
-wd4505 ^
-wd4189 ^
-wd4146 ^
-wd4127 ^
-wd4312 ^
-wd4239 ^
-IE:\Tools\glfw\include\GLFW ^
-IE:\Tools\glad\include ^

set linker_args=^
E:\Tools\glfw\build\src\Debug\glfw3.lib ^
user32.lib gdi32.lib shell32.lib opengl32.lib

pushd build

cl %compiler_args% ..\src\main.cpp /link %linker_args%

popd

Expected behavior

The error isn't shown in the editor.

Steps to reproduce

Paste the code to a cpp file and let ccls parse it using the .ccls file.

System information

aqilc commented 2 years ago

Is there any workaround to this? I'm trying to use ccls to debug my project and it's just painful trying to get rid of nonexistent errors.

OrangeLightning219 commented 2 years ago

Unfortunately I haven't found any workarounds. I case of the error I described I either add a local variable or change the function parameters from references to normal variables. I tried figuring out how to use Microsoft's language server but it seems like it's available only as a vs code extension.

ZigaSajovic commented 1 year ago

@OrangeLightning219 Your code is not valid C++. This compiles on MSVC because it is a non-compliant compiler, which has been addressed in newer version with a compiler flag, but was left in the defaults for backwards compatibility. Try adding this flag in MSVC and you will get the same error.

To explain the problem with your code: The expression Dot( a, b ) is a temporary or an rvalue. Meaning it has no name and cannot be referenced by an l-value reference Vecor3&. But an r-value reference (Vector3&&) and a const reference (const Vector3 &) can bind to it. Besides, the reference in your operator- should be const, because you do not modify the parameters in the body of the function. The same goes for all your other functions.

inline Vector3 operator-( const Vector3 &a,  const Vector3 &b )
{
    return Vector3( a.x - b.x, a.y - b.y, a.z - b.z );
}

Now the code will compile on any compiler, because it is correct, valid c++. You should take this as an opportunity to fill the voids in your understanding of C++ which caused you to write non-compliant C++.

OrangeLightning219 commented 1 year ago

@ZigaSajovic sure I can change my code so that clang won't throw an error but that's not the solution I wanted. What I wanted is ccls using msvc instead of clang so that the non standard stuff wouldn't throw errors in the editor. Anyway thanks for your answer (I didn't even know there are r-value references in c++ :) ).

madscientist commented 1 year ago

What you want is not possible because that's not how ccls works. Apparently there's a common idea out there that ccls works by "running a compiler" and using its output (we had a similar request just a short time ago, but with GCC being requested not MSVC) but that's definitely not true. Compilers do not "generate" output sufficient for an LSP server like ccls. ccls needs to parse your code into an internal structure so it can be fully indexed. To do this it needs a very sophisticated, accurate C++ parser. It so happens that the Clang compiler makes its C++ parser available as a separable library, and so ccls, rather than writing its own C++ parser which would be a TON of never-ending work, links in that library and uses the clang parser. It doesn't "run" the Clang compiler.

MSVC does not make its C++ parser available as a separable library, and so there's no way that ccls could use MSVC's parser--even if someone wanted to make the effort to allow ccls to work with it, which would basically amount to rewriting ccls since there's little chance the internal structures generated by MSVC's parser would be compatible with Clang's.

aqilc commented 1 year ago

Sorry, this may be a stupid question but why would you need more info than the warnings and errors the compilers give you? MSVC, GCC, and Clang give the exact place in the code where the error/warning is at on top of severity and the proper error message. In the case of an ambiguous error message, like just an error number, you can probably have a lookup table for a more specific one right?

I would understand needing a parser for definitions and syntax highlighting, but you can use your clang parser for that. I don't see why you would need the command and flags just for parsing the code and generating your own errors. I honestly only need the compiler errors and/or definitions, and that would be enough for me.

madscientist commented 1 year ago

Sorry @AqilCont I don't know what you're trying to say in your comment. ccls is an implementation of the Language Server Protocol. This is a way for an editor (the LSP client) to obtain information about source code and implement advanced editor features like, "jump to the location in the code where this function or variable is defined", "show all the callers of this function", "tell me the return type of this function", "tell me what arguments I need to pass when I call this function, and their types", and much much more. In a complex codebase these capabilities are critical for productive coding.

In order to provide those features, obviously ccls has to be able to parse the code. If the code is invalid, then the parser will fail, so editors using ccls can also warn you about those types of errors before you even save your code, much less try to compile it. But this is just a small part of what an LSP server does; almost a side-effect.

It sounds to me like all you want is something that will interpret compiler error messages and jump to the lines where they happened: if that's all you want you don't need ccls. You just need an editor that can run a compile command and interpret the compiler output. As you say almost every editor out there already has that.

aqilc commented 1 year ago

Right, nevermind, sorry. I currently don't have a good reliable solution and am just slightly frustrated. VSCode, at least, does not parse compiler errors for me, and it's been a constant back and forth to the terminal for me.

madscientist commented 1 year ago

Well, the best solution is to write code that conforms to the C or C++ standards. Then ccls won't complain about non-existing errors but will only complain about real errors :). Perhaps when writing some types of platform-specific code this can be hard to do.

You haven't provided any info about your build environment (and I don't use vscode) but as far as I'm aware VSCode comes with the ability to jump to errors in the results of a build, more or less built in. It even lets you customize what constitutes an "error", if the default settings don't match. I would try googling around to figure out why yours doesn't work. For example: https://stackoverflow.com/questions/41851469/how-to-jump-to-build-error-in-visual-studio-code In any event, that is not related to ccls...