clangd / vscode-clangd

Visual Studio Code extension for clangd
https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd
MIT License
629 stars 106 forks source link

Calling emplace() for a map gives no member error. #507

Closed baba-ghanouj closed 1 year ago

baba-ghanouj commented 1 year ago

Description of Issue After creating an instance of a map, any call to emplace() member function is highlighted as an error with the following message: No member named 'emplace' in 'std::map<int, std::string>'clang(no_member)

However, the code will compile and run without issue.

Code Snippet

#include <iostream>
#include <map>
#include <string>

using std::string;
using std::map;

int main() {
  map<int, string> test;

  test.emplace(1, "one");

  return 0;
}

System information Clangd version (from the log, or clangd --version): Apple clangd version 14.0.3 (clang-1403.0.22.14.1) clangd extension version: v0.1.24 Operating system: macOS 13.4.1 (c)

1-clangd.log

Screenshot 2023-07-17 at 9 45 31 PM

HighCommander4 commented 1 year ago

map::emplace() was added in C++11, so maybe clangd doesn't know you parse your standard library headers in C++11 mode.

How do you build your code, and with what compiler version?

baba-ghanouj commented 1 year ago

map::emplace() was added in C++11, so maybe clangd doesn't know you parse your standard library headers in C++11 mode.

How do you build your code, and with what compiler version?

I build with clang from zsh installed via Apple’s Xcode command-line tools. I haven’t made any modifications to the C++ library or installed any non-standard packages (other than anything extra Xcode CL tools may already include).

Apple clang version 14.0.3 (clang-1403.0.22.14.1)

Because my environment is so basic, I expect other users on macOS may be encountering this bug.

Is there a way to configure the clangd extension to resolve this issue?

HighCommander4 commented 1 year ago

Is there a way to configure the clangd extension to resolve this issue?

Generally speaking, the way is to specify the compiler flag corresponding to the language version you're using (e.g. -std=c++11), using one of the mechanisms clangd provides for specifying compiler flags (compile_commands.json, compile_flags.txt, or a clangd config file).

The reason the situation is a bit surprising in this case, is that C++11 is a sufficiently old language version that the default language version of most recent compilers should be at least C++11 to begin with (for example, for stock clang 14 it's C++14; I know Apple's clang versions are a bit behind but I'd still expect Apple's clang 14 to be at least C++11).

Anyways, if you haven't tried adding -std=c++11 as a compiler flag, please try that and see if that works. If you're not able to get it to work, please share clangd logs.

baba-ghanouj commented 1 year ago

Anyways, if you haven't tried adding -std=c++11 as a compiler flag, please try that and see if that works. If you're not able to get it to work, please share clangd logs.

I usually compile with -std=c++11 flag but wouldn’t expect the clangd extension to know about this. I haven’t been using a make file nor have I configured clang. Is it possible to check the default standard invoked without any flag? Often, when I don’t use the version 11 flag, I get warnings about the version, for example, using for-range loops.

HighCommander4 commented 1 year ago

Is it possible to check the default standard invoked without any flag?

If you mean the default version clangd is using: open a source file in a project with no configuration, write a line of code that uses the macro __cplusplus (for example, int x = __cplusplus;), and hover over the macro usage to see the value. The value will be a constant of the form YYYYMM, for example 201402 would suggest C++14.

baba-ghanouj commented 1 year ago

int x = __cplusplus;

Seems to return 199711L. Any idea how to resolve this?

Thanks.

HighCommander4 commented 1 year ago

int x = __cplusplus;

Seems to return 199711L. Any idea how to resolve this?

Like I said:

specify the compiler flag corresponding to the language version you're using (e.g. -std=c++11), using one of the mechanisms clangd provides for specifying compiler flags (compile_commands.json, compile_flags.txt, or a clangd config file)

baba-ghanouj commented 1 year ago

Like I said:

Thanks for your help. I was able to resolve the issue by creating a config.yaml file in the following directory: ~/Library/Preferences/clangd/

The contents of the file are simply:

CompileFlags:                     # Tweak the parse settings
  Add: [-std=c++11]

Also, the clangd subfolder was not present so it needed to be created as well. Not sure why the default parse on macOS is C++98. Weird.

HighCommander4 commented 1 year ago

Not sure why the default parse on macOS is C++98. Weird.

I agree it's weird.

If you'd like to help get to the bottom of it, feel free to share clangd logs (taken with --log=verbose). They may not provide the answer (after all, Apple's clangd contains patches that AFAIK aren't public; for all we know they could include a patch that changes the default language version), but we can take a look anyways to see if there's anything suspicious there.

baba-ghanouj commented 1 year ago

If you'd like to help get to the bottom of it, feel free to share clangd logs (taken with --log=verbose). They may not provide the answer (after all, Apple's clangd contains patches that AFAIK aren't public; for all we know they could include a patch that changes the default language version), but we can take a look anyways to see if there's anything suspicious there.

Sorry. I am having trouble figuring out to get VS Code to output verbose logs. It is not clear to me from the documentation. In my OP, I included a clangd log file, but I am not sure if it has the verbose output you desire.

HighCommander4 commented 1 year ago

I am having trouble figuring out to get VS Code to output verbose logs.

Adding --log=verbose to "clangd.arguments" in vscode settings should do it.