Skip to content
| Marketplace
Sign in
Visual Studio Code>Programming Languages>clangd++New to Visual Studio Code? Get it now.
clangd++

clangd++

Preview

CGQAQ

|
2 installs
| (0) | Free
Class hierarchy, call, ownership and include graphs, exact class layouts, and go-to-definition through forward declarations for C and C++, powered by clangd.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

clangd++

Class hierarchy, call, ownership and include graphs, exact class layouts and more for C and C++, built on clangd.

clangd++ adds views on top of the clangd extension. Installing clangd++ installs the clangd extension too. clangd++ reuses that extension's clangd process, so you don't pay for a second language server.

Type Graph

Put the cursor on a class (or anywhere inside a class definition) and run Show Type Graph (clangd++) from the editor's context menu, or clangd++: Show Type Graph from the command palette.

  • Base classes are shown up to the roots, and direct subtypes one level down.
  • Click a class to jump to its definition. Ctrl/Cmd-click opens it beside.
  • +N chips add the next batch of subtypes (clangdpp.graph.maxChildren at a time). A class with more subtypes than that gets one chip per directory instead (chrome/browser/ui/ · 342 ▸): click a chip to split it by subdirectory, or to show its classes once there are few enough.
  • Find class in the toolbar highlights matching classes; Enter and Shift+Enter step through them, Esc clears.
  • Follow re-roots the graph on the class at your cursor as you move around (clicking a class in the graph doesn't count as moving).
  • The panel comes back after a window reload, on the class it was showing.
  • Right-click a class to show its base classes, re-root the graph on it, find references, copy its qualified name or hide it.
  • Members: tick Fields, Methods or Types in the toolbar to list each class's members under its name, UML-style: + public, # protected, − private; virtual in italics, static underlined. Public only hides the rest. Click a member to jump to its declaration. All off by default; your choice is remembered.
  • Interface: the toolbar's Interface button opens a panel listing every virtual method of the class, across all its bases: which base introduces it, every class that overrides it, and which one actually implements it. Filter to Overridden here, Inherited or Not implemented (pure virtuals nothing implements). Click a method to open its implementation, or a class in its chain to open that class's version; hover to highlight those classes in the graph and see the method's documentation.
  • Docs on hover: hovering a member shows its documentation from clangd.
  • Export the graph as Mermaid (for docs and code review), DOT or PNG.

Subtypes come from clangd's index, so they're only complete once background indexing (or a remote index) covers your project.

Call Graph

Put the cursor on a function or method and run Show Call Graph (clangd++) from the context menu (clangd++: Show Call Graph in the palette).

  • Callers on the left, callees on the right; +N callers / +N callees chips load more. Edges show how many call sites there are (×2); click an edge to jump to its call sites.
  • Calls through a base class are included and drawn dashed (via View): view->OnThemeChanged() with a View* can run LabelButton::OnThemeChanged, but clangd reports it as a caller of the base method only.
  • Right-click a function to show its callers or callees, re-root on it, find references, copy its name or hide it.
  • Export as Mermaid, DOT or PNG.

Ownership Diagram

Put the cursor on a class and run Show Ownership Diagram (clangd++) from the context menu (clangd++: Show Ownership Diagram in the palette; also in the type graph's right-click menu). It answers "what does this class hold, and who holds it?":

  • Below: what its fields point to, UML-style: owns ◆ (unique_ptr), shares ◇ (shared_ptr), refers → (T*, T&), weak ⇢ (weak_ptr), and contains ◆ for members held by value (off by default: sizes, timers and callbacks are noise). Containers count: std::vector<std::unique_ptr<Tab>> owns many tabs ([*]).
  • Above: the classes with fields pointing to it, found from clangd's references (it stops at 1000 references, clangd's default limit).
  • Chromium types: tick Chromium types (the clangdpp.includeChromiumTypes setting) to read raw_ptr, raw_ref, base::WeakPtr, scoped_refptr, ObserverList, ScopedObservation, base::flat_map and other Chromium and Abseil containers, and Blink's Member, WeakMember and Persistent. Off, the diagram says how many fields it's leaving out.
  • Click a class to open it (forward declarations are followed to the definition), an edge to open its fields. Double-click a class for its fields; right-click for who owns or points to it, re-root, its type graph or class layout.
  • Your own smart pointers: clangdpp.ownership.patterns, e.g. { "my::OwnedPtr": "owns", "my::Ref": "refers" }.
  • Export as a Mermaid class diagram, DOT or PNG.

Class Layout

Show Class Layout (clangd++) (also in the type graph's right-click menu) shows how the class at the cursor is laid out in memory, from clangd's own numbers, without compiling: one row per cache line, each field's offset and size, padding holes in red, and the bytes taken by base classes and the vtable pointer. If ordering the fields by alignment would make the class smaller, it says by how much. Click a field to open it.

Exact Layout in the view compiles a tiny probe with the file's own command from compile_commands.json and clang's -fdump-record-layouts, and shows everything at every level: each base class, vtable pointer and field, the members of members, and padding inside bases and members as well as in the class itself (Expand Padding opens everything that has some). Private nested types and enum sizes work. It takes about as long as compiling the header: around 2.5 s for views::LabelButton in Chromium. Turn on clangdpp.layout.exactAutomatically to get it every time.

Include Graph

Show Include Graph (clangd++) preprocesses the current file with its compile command and shows what it includes:

  • Include Tree: every header in include order, with the lines of preprocessed code each #include brings in and its share of the translation unit. Click a header's name to open it, or the file.cc:12 link to go to the #include that brought it in. Sort by lines to see the expensive includes first.
  • Heaviest Headers: every header by what it costs. Click one to see why it's included, the chain of #includes from your file down to it, each step a link.
  • A filter box finds a header anywhere in the tree, with the chain to it.

It works on headers too, with their source file's flags. Chromium's label_button.cc (1,832 headers, 241k lines) preprocesses in about 0.15 s.

Virtual methods

A CodeLens above each virtual method shows what it overrides and how often it's overridden: ↑ View::OnThemeChanged · ↓ 2 overrides. Click it to peek at them.

Go to Class Definition through forward declarations

Headers are full of forward declarations (class WebFrame;). When clangd's index doesn't cover the header that defines the class, Go to Definition just lands on a forward declaration. clangd++ finds the real definition:

  1. clangd first: if clangd knows the definition, that's where you go.
  2. The file named after the class: WebFrame → web_frame.h (also WebFrame.h), checked to actually define the class in the right namespace, so blink::WebFrame doesn't send you to iOS's web::WebFrame.
  3. Text search for the definition (git grep, or rg outside git checkouts), if no file matched by name.

How to use it:

  • F12 on a forward declaration (cursor on WebFrame in class WebFrame;) jumps straight to the definition.
  • Go to Class Definition (clangd++) in the editor's context menu (clangd++: Go to Class Definition in the command palette) works anywhere on a class name.
  • Go to Definition, Peek and Ctrl/Cmd+click get the definition added next to clangd's answer when clangd only knows forward declarations.

Lookups use git in git checkouts (about 0.1–0.2s by file name on Chromium) and cover nested checkouts such as a downstream browser's own repo inside src/.

cppreference on hover

Hover a standard library name (std::vector, push_back, std::move, std::chrono::steady_clock::now, even plain printf) and, below clangd's hover, clangd++ adds a short summary from cppreference.com with a link to the full page:

std::vector<T,Allocator>::push_back · cppreference

Appends the given element value to the end of the container.

It finds the right page for members (through the class's own member list on cppreference) and for names with several pages (std::move from <utility> vs <algorithm>, using the header clangd says provides it). It works with libc++ (Chromium's included) and libstdc++.

Only the cppreference pages for names you hover are requested; no code or file names leave your machine. Pages are cached for 30 days, so after the first hover it works offline too. Turn it off with clangdpp.cppreference.enabled, or point clangdpp.cppreference.url at another cppreference site. Text from cppreference.com is CC BY-SA.

Build directories and compile commands

  • Status bar: shows which build directory clangd reads compile_commands.json from (e.g. out/Default), and how big and how old it is. Click it to switch.
  • clangd++: Switch Build Directory lists the build directories (out/*, build, … with their compile DB's size and age). Picking one sets --compile-commands-dir in the workspace's clangd.arguments and restarts clangd.
  • clangd++: Generate compile_commands.json runs your generate command as a task, e.g. gn gen ${buildDir} --export-compile-commands (suggested for GN, CMake and Meson projects the first time).
  • Show Compile Command (clangd++) opens the current file's command, one argument per line; clangd++: Copy Compile Command copies it as one line, with the cd. A header uses its source file's command, as clangd does.
  • Preprocess Current File (clangd++) runs that command with -E and opens the output at the file's own code, highlighted as C++ (but kept away from clangd). F12 on any line of the output jumps to the source line it came from.

Huge compile DBs are fine: Chromium's (600+ MB, ~78k entries) is indexed in under a second, without loading it into memory.

Settings

Setting Default
clangdpp.graph.maxChildren 25 Subtypes added per expansion
clangdpp.graph.direction TB TB (bases on top) or LR (bases on the left)
clangdpp.graph.openBeside false Click opens beside; Ctrl/Cmd-click does the opposite
clangdpp.graph.followCursor false Start with Follow on (the panel's toggle is remembered)
clangdpp.requests.maxConcurrent 4 Requests kept in flight to clangd
clangdpp.forwardDeclarations.f12 true F12 on class Foo; jumps to the definition
clangdpp.forwardDeclarations.definitionProvider true Add the definition to Go to Definition / Ctrl+click results
clangdpp.forwardDeclarations.textSearch true Fall back to searching source text
clangdpp.callGraph.dispatchAware true Include callers through base-class methods
clangdpp.layout.cacheLineSize 64 Bytes per row in Class Layout
clangdpp.layout.exactAutomatically false Get the exact layout (compiling a probe) whenever Class Layout opens a class
clangdpp.includeChromiumTypes false Ownership Diagram reads Chromium, Blink and Abseil pointer and container types
clangdpp.cppreference.enabled true Add a cppreference.com summary and link when hovering standard library names
clangdpp.cppreference.url https://en.cppreference.com The cppreference site to read and link to
clangdpp.ownership.patterns {} Your own templates for the Ownership Diagram: name → owns, shares, refers, weak, contains or container
clangdpp.codeLens.virtualMethods true The ↑ overrides / ↓ overrides CodeLens
clangdpp.buildDirs.globs ["out/*", "build", "build/*", "cmake-build-*"] Where to look for build directories
clangdpp.compileDb.generateCommand "" Command that writes compile_commands.json; ${buildDir} is the build directory
  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
  • Your Privacy Choices
  • Consumer Health Privacy
© 2026 Microsoft