C++ Language Support in Eclipse CDT

Eclipse CDT provides a feature-rich environment for editing C++ code. To do this, it needs to have a deep level of understanding of the code being edited.

What supporting C++ involves

To obtain such a deep level of understanding, CDT needs to perform many of the same stages of processing on the code that a compiler does:

  • The code is first run through a lexer which converts the code into a token stream.
  • The lexed tokens are then preprocessed, which involves expanding macros and dropping sections disabled by conditional compilation.
  • The preprocessed tokens are parsed into an abstract syntax tree (AST).
  • Semantic analysis is performed on the AST, which creates links between parts of the AST (for example, recognizing that a name in one part of the AST refers to an entity - like a variable or function - declared in another part). In C++, semantic analysis is a complex process that involves procedures like name lookup, overload resolution, and template instantiation.

That's basically everything a compiler does short of optimization and code generation - and CDT can do all this.

In addition, unlike a compiler which compiles C++ code one translation unit at a time, CDT needs to support some features that require a global view of the entire codebase, such as answering the question "where are all the places this function is called in the codebase?" - and it needs to be able to answer such questions efficiently. To this end, CDT maintains an index, which can be thought of as a queryable database containing semantic information about the entire project.

CDT leverages the semantic model of the code that it builds to provide a wealth of editing features, such as showing errors and warnings as you type, semantic highlighting, navigation (such as Open Declaration), search, and code completion, among others.

Adding support for a C++ language feature can involve all of the above: adding support to the lexer, preprocessor, parser, and semantic analysis; storing new types of information in the index; and integrating the feature into our various editor capabilities (for example, a new language feature may require a new semantic highlighting, or a new type of element in the Outline View).

Evolution of the C++ language

The C++ language isn't static, such that you add support for it once and you're done with it - it is constantly evolving. Standardized by a committee of the International Standards Organization, C++ had its initial language standard published in 1998, called C++98. A significant new version of it was published in 2011 (C++11), and since then the committee has been making 3-year releases of the standard: C++14, C++17, and so on.

Let's examine the state of CDT's support for these various language versions.

C++98

C++98 has been published for a while, and CDT has supported all of its major features for a while. Over the years, the quality of CDT's support has improved, with a long tail of edge cases being fixed over time, such that these days, the remaining bug reports CDT receives about C++98 features is about very obscure edge cases.

Here is a screenshot illustrating CDT performing overload resolution to provide accurate code completion:

C++98

An example of a C++98 edge case that CDT still does not support, is the use of #include statements that are not at global scope; however, there is a plan for supporting that as well.

C++11

Adding C++11 support to CDT was a more recent endeavor. By this point, all major C++11 features are supported as well, though we will sometimes get bug reports about not-so-obscure edge cases.

Here's a screenshot of CDT using a C++11 library function, and using C++11's auto to deduce a type:

C++11

C++14

C++14 is the most recent C++ language standard published to date. CDT's support for C++14 is a work in progress: two major features, variable templates and C++14 extensions to constexpr, are already supported, while work on others, such as return type deduction is ongoing.

Here's a screenshot of CDT performing C++14 constexpr evaluation. You can see from the hover that CDT has calculated that the result of the factorial(5) call is 120:

C++14

Non-standard extensions

In addition to standard language features, compilers sometimes support non-standard extensions. CDT doesn't (and can't possibly) support all such extensions for all compilers, but we do have some support. For example, since the majority of our users use the GCC compiler, we support a number of popular GNU extensions, including statement-expressions and label reference expressions.

With a large backlog of standard C++ features to implement, adding support for new non-standard extensions is not a priority, but we do welcome patches in cases where there is significant community interest in an extension.

Encouraging experimentation

In addition to the official releases of the C++ language standard like C++11 and C++14, the C++ standards committee has a mechanism for encouraging experimentation with language features that are still in development: Technical Specifications. These are specifications of new features that are not ready for final standardization yet but are published with the hope that implementers will implement them and users will use them, and provide feedback that may guide final standardization.

CDT aims to play its part in enabling such experimentation, by supporting features published as Technical Specifications. For example, CDT plans to support the Concepts Technical Specification without waiting for the feature's official standardization.

Leveraging the community

The current level of C++ language support in CDT wouldn't be possible without the efforts of our community of contributors to complement the work of CDT's committers. Community contributions in the area of language support have ranged from bug fixes to entirely new features.

A notable community partner for CDT has been the Institute for Software (IFS), an academic group at the Swiss university HSR. Led by Professor Peter Sommerlad, the group uses CDT to teach programming and C++ to students, and they develop Cevelop, a C++ IDE that extends CDT with a number of useful plugins. Among numerous other contributions, the implementations of the two main C++14 features CDT supports so far (variable templates and C++14 constexpr) started as term projects by students at IFS.

CDT wouldn't be what it is without our volunteer contributors. New contributors are always welcome!

The future: C++17 and beyond

The C++ language is evolving rapidly, with a new release, C++17, expected later this year, and more to follow every three years. Even with the help of the community, keeping up with the pace of development of new C++ language features is challenging for CDT.

As a result, there have been discussions about re-architecting CDT to leverage the internals of an existing compiler to understand C++ code, rather than rolling its own support. This wasn't done when CDT was initially designed because, at the time, open-source compilers weren't written with use by IDEs in mind. Since then, clang has come along, a C++ compiler designed from the ground up for extensibility and use by tools.

Specifically, there is an exploratory effort underway to make use of clang's internals via the Language Server Protocol and ClangD. While this would be a long-term project, once it's done CDT would effectively be able to gain support for new language features as soon as clang does - and clang has been pretty good at keeping pace with C++ standardization, with its latest trunk already supporting all of the features in the draft C++17 standard.

About the Author

Nathan Ridge