This is a major change on how we represent nested name qualifications in
the AST.
* The nested name specifier itself and how it's stored is changed. The
prefixes for types are handled within the type hierarchy, which makes
canonicalization for them super cheap, no memory allocation required.
Also translating a type into nested name specifier form becomes a no-op.
An identifier is stored as a DependentNameType. The nested name
specifier gains a lightweight handle class, to be used instead of
passing around pointers, which is similar to what is implemented for
TemplateName. There is still one free bit available, and this handle can
be used within a PointerUnion and PointerIntPair, which should keep
bit-packing aficionados happy.
* The ElaboratedType node is removed, all type nodes in which it could
previously apply to can now store the elaborated keyword and name
qualifier, tail allocating when present.
* TagTypes can now point to the exact declaration found when producing
these, as opposed to the previous situation of there only existing one
TagType per entity. This increases the amount of type sugar retained,
and can have several applications, for example in tracking module
ownership, and other tools which care about source file origins, such as
IWYU. These TagTypes are lazily allocated, in order to limit the
increase in AST size.
This patch offers a great performance benefit.
It greatly improves compilation time for
[stdexec](https://github.com/NVIDIA/stdexec). For one datapoint, for
`test_on2.cpp` in that project, which is the slowest compiling test,
this patch improves `-c` compilation time by about 7.2%, with the
`-fsyntax-only` improvement being at ~12%.
This has great results on compile-time-tracker as well:

This patch also further enables other optimziations in the future, and
will reduce the performance impact of template specialization resugaring
when that lands.
It has some other miscelaneous drive-by fixes.
About the review: Yes the patch is huge, sorry about that. Part of the
reason is that I started by the nested name specifier part, before the
ElaboratedType part, but that had a huge performance downside, as
ElaboratedType is a big performance hog. I didn't have the steam to go
back and change the patch after the fact.
There is also a lot of internal API changes, and it made sense to remove
ElaboratedType in one go, versus removing it from one type at a time, as
that would present much more churn to the users. Also, the nested name
specifier having a different API avoids missing changes related to how
prefixes work now, which could make existing code compile but not work.
How to review: The important changes are all in
`clang/include/clang/AST` and `clang/lib/AST`, with also important
changes in `clang/lib/Sema/TreeTransform.h`.
The rest and bulk of the changes are mostly consequences of the changes
in API.
PS: TagType::getDecl is renamed to `getOriginalDecl` in this patch, just
for easier to rebasing. I plan to rename it back after this lands.
Fixes#136624
Fixes https://github.com/llvm/llvm-project/issues/43179
Fixes https://github.com/llvm/llvm-project/issues/68670
Fixes https://github.com/llvm/llvm-project/issues/92757
Add `NamespaceBaseDecl` as common base class of `NamespaceDecl` and
`NamespaceAliasDecl`. This simplifies `NestedNameSpecifier` a bit.
Co-authored-by: Matheus Izvekov <mizvekov@gmail.com>
We would try to exact an annotated token before checking if it was
valid, leading to a crash when `decltype` was the only token that was
parsed (which can happen in the absense of opening paren)
Fixes#114815
At the moment, when we report diagnostics from `SemaHLSL` we only
provide the source location of the root signature attr. This allows for
significantly less helpful diagnostics (for eg. reporting resource range
overlaps).
This pr implements a way to retain the source location of a root element
when it is parsed, so that we can output the `SourceLocation` of each
root element that causes the overlap in the diagnostics during semantic
analysis.
This pr defines a wrapper struct `clang::hlsl::RootSignatureElement` in
`SemaHLSL` that will contain the underlying `RootElement` and can hold
any additional diagnostic information. This struct will be what is used
in `HLSLRootSignatureParser` and in `SemaHLSL`. Then the diagnostic
information will be stripped and the underlying element will be stored
in the `RootSignatureDecl`.
For the reporting of diagnostics, we can now use the retained
`SourceLocation` of each `RootElement` when reporting the range overlap,
and we can add a `note` diagnostic to highlight the other root element
as well.
- Defines `RootSignatureElement` in the `hlsl` namespace in `SemaHLSL`
(defined in `SemaHLSL` because `Parse` has a dependency on `Sema`)
- Updates parsing logic to construct `RootSignatureElement`s and retain
the source loction in `ParseHLSLRootSignature`
- Updates `SemaHLSL` when it constructs the `RootSignatureDecl` to take
the new `RootSignatureElement` and store the underlying `RootElement`
- Updates the current tests to ensure the new `note` diagnostic is
produced and that the `SourceLocation` is seen
- Slight update to the `RootSignatureValidations` api to ensure the
caller sorts and owns the memory of the passed in `RangeInfo`
- Adds a test to demonstrate the `SourceLocation` of both elements being
correctly pointed out
Resolves: https://github.com/llvm/llvm-project/issues/145819
The `SourceLocation` of a `RootSignatureToken` is incorrectly set to be
the "offset" into the concatenated string that denotes the
rootsignature. This causes an issue when the `StringLiteral` is a
multi-line expansion macro, since the offset will not account for the
characters between `StringLiteral` tokens.
This pr resolves this by retaining the `SourceLocation` information that
is kept in `StringLiteral` and then converting the offset in the
concatenated string into the proper `SourceLocation` using the
`StringLiteral::getLocationOfByte` interface. To do so, we will need to
adjust the `RootSignatureToken` to only hold its offset into the root
signature string. Then when the parser will use the token, it will need
to compute its actual `SourceLocation`.
See linked issue for more context.
For example:
```
#define DemoRootSignature \
"CBV(b0)," \
"RootConstants(num32BitConstants = 3, b0, invalid)"
expected caret location ---------------^
actual caret location ------------^
```
The caret points 5 characters early because the current offset did not
account for the characters:
```
'"' ' ' '\' ' ' '"'
1 2 3 4 5
```
- Updates `RootSignatureParser` to retain `SourceLocation` information
by retaining the `StringLiteral` and passing the underlying `StringRef`
to the `Lexer`
- Updates `RootSignatureLexer` so that the constructed tokens only
reflect an offset into the `StringRef`
- Updates `RootSignatureParser` to directly construct its used `Lexer`
so that the `StringLiteral` is directly tied with the string used in the
`RootSignatureLexer`
- Updates `RootSignatureParser` to use
`StringLiteral::getLocationOfByte` to get the actual token location for
diagnostics
- Updates `ParseHLSLRootSignatureTest` to construct a phony
`AST`/`StringLiteral` for the test cases
- Adds a test to `RootSignature-err.hlsl` showing that the
`SourceLocation` is correctly set for diagnostics in a multi-line macro
expansion
Resolves: https://github.com/llvm/llvm-project/issues/146967
In ms-compatibility mode we inject static_assert macro definition if
assert macro is defined. This is done by
8da090381d567d0ec555840f6b2a651d2997e4b3
for the sake of better diagnosing, in particular to emit a compatibility
warning when static_assert keyword is used without inclusion of
<assert.h>. Unfortunately it doesn't do a good job in c99 mode adding
that macro unexpectedly for the users, so this patch removes macro
injection and the diagnostics.
---------
Co-authored-by: Corentin Jabot <corentinjabot@gmail.com>
This pr updates `setDefaultFlags` in `HLSLRootSignature.h` to account
for which version it should initialize the default flag values for.
- Updates `setDefaultFlags` with a `Version` argument and initializes
them to be compliant as described
[here](https://github.com/llvm/wg-hlsl/pull/297).
- Updates `RootSignatureParser` to retain the `Version` and pass this
into `setDefaultFlags`
- Updates all uses of `setDefaultFlags` in test-cases
- Adds some new unit testing to ensure behaviour is as expected and that
the Parser correctly passes down the version
Resolves https://github.com/llvm/llvm-project/issues/145820.
These are identified by misc-include-cleaner. I've filtered out those
that break builds. Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
This separates semantic analysis from parsing by moving `RootSignatureDecl` creation, scope storage, and lookup logic into
`SemaHLSL`.
For more context see:
https://github.com/llvm/llvm-project/issues/142834.
- Define `ActOnStartRootSignatureDecl` and `ActOnFinishRootSignatureDecl` on `SemaHLSL`
- NFC so no test changes.
Resolves: https://github.com/llvm/llvm-project/issues/142834
---------
Co-authored-by: Aaron Ballman <aaron@aaronballman.com>
The assumption attribute is exposed with a Clang spelling, which means
we support __attribute__((assume)) as well as [[clang::assume]] as
spellings for the attribute.
In C++, the [[clang::assume]] spelling worked as expected. In C, that
spelling would emit an "unknown attribute ignored" diagnostic. This was
happening because we were failing to pass in the scope name and source
location when creating the attribute. In C++, this worked by chance
because [[assume]] is a known attribute in C++. But in C, where there is
thankfully no [[assume]] standard attribute, the lack of a scope meant
we would set the attribute kind to "unknown".
These are identified by misc-include-cleaner. I've filtered out those
that break builds. Also, I'm staying away from llvm-config.h,
config.h, and Compiler.h, which likely cause platform- or
compiler-specific build failures.
Following the steps of #82217, this patch reorganizes declarations in
`Parse.h`. Highlights are:
1) Declarations are grouped in the same fashion as in `Sema.h`. Table of
contents is provided at the beginning of `Parser` class. `public`
declaration go first, then `private` ones, but unlike `Sema`, most of
the stuff in `Parser` is private.
2) Documentation has been moved from `.cpp` files to the header. Grammar
was consistently put in `\verbatim` blocks to render nicely in Doxygen.
3) File has been formatted with clang-format, except for the grammar,
because clang-format butchers it.
- Defines a new declaration node `HLSLRootSignature` in `DeclNodes.td`
that will consist of a `TrailingObjects` of the in-memory construction
of the root signature, namely an array of `hlsl::rootsig::RootElement`s
- Defines a new clang attr `RootSignature` which simply holds an
identifier to a corresponding root signature declaration as above
- Integrate the `HLSLRootSignatureParser` to construct the decl node in
`ParseMicrosoftAttributes` and then attach the parsed attr with an
identifier to the entry point function declaration.
- Defines the various required declaration methods
- Add testing that the declaration and reference attr are created
correctly, and some syntactical error tests.
It was previously proposed that we could have the root elements
reference be stored directly as an additional member of the attribute
and to not have a separate root signature decl. In contrast, by defining
them separately as this change proposes, we will allow a unique root
signature to have its own declaration in the AST tree. This allows us to
only construct a single root signature for all duplicate root signature
attributes. Having it located directly as a declaration might also prove
advantageous when we consider root signature libraries.
Resolves https://github.com/llvm/llvm-project/issues/119011
Enable parsing alignas attribute after GNU attributes, before
ParseDeclaration
This might be useful for cuda code where __shared__ and other
specificators may be mixed with align.
I'd be glad to see if there are any better places or other technique to
process this attribute without interrupting current flow of parsing.
This adds
- The parsing of `trivially_relocatable_if_eligible`,
`replaceable_if_eligible` keywords
- `__builtin_trivially_relocate`, implemented in terms of memmove. In
the future this should
- Add the appropriate start/end lifetime markers that llvm does not have
(`start_lifetime_as`)
- Add support for ptrauth when that's upstreamed
- the `__builtin_is_cpp_trivially_relocatable` and
`__builtin_is_replaceable` traits
Fixes#127609
When parsing a function pointer typed field we use
Parser::ParseTypeQualifierListOpt, but then drops subsequent type
attributes and qualifiers unless explicitly handled.
There is an existing solution for the _Atomic qualifier, and this PR
simply extends that to __ptrauth for now. In future we may want to
investigate a more robust mechanism to ensure type qualifiers are not
silently dropped so that future type qualifiers do not suffer the same
problem.
This patch adds templated `operator<<` for diagnostics that pass scoped
enums, saving people from `llvm::to_underlying()` clutter on the side of
emitting the diagnostic. This eliminates 80 out of 220 usages of
`llvm::to_underlying()` in Clang.
I also backported `std::is_scoped_enum_v` from C++23.
This is the last item of the OpenACC 3.3 spec. It includes the
implicit-name version of 'routine', plus significant refactorings to
make the two work together. The implicit name version is represented as
an attribute on the function call. This patch also implements the
clauses for the implicit-name version, as well as the A.3.4 warning.
Clang already removes parsed enumerators when merging typedefs to
anonymous enums. This is why the following example decl used to be
handled correctly while merging, and ASTWriter behaves as expected:
```c
typedef enum { Val } AnonEnum;
```
However, the mentioned mechanism didn't handle named enums. This leads
to stale declarations in `IdResolver`, causing an assertion violation in
ASTWriter ``Assertion `DeclIDs.contains(D) && "Declaration not
emitted!"' failed`` when a module is being serialized with the following
example merged enums:
```c
typedef enum Enum1 { Val_A } Enum1;
enum Enum2 { Val_B };
```
The PR applies the same mechanism in the named enums case.
Additionally, I dropped the call to
`getLexicalDeclContext()->removeDecl` as it was causing a wrong
odr-violation diagnostic with anonymous enums.
Might be easier to to review commit by commit. Any feedback is
appreciated.
### Context
This fixes frontend crashes that were encountered when certain
Objective-C modules are included on Xcode 16. For example, by running
`CC=/path/to/clang-19 xcodebuild clean build` on a project that contains
the following Objective-C file:
```c
#include <os/atomic.h>
int main() {
return memory_order_relaxed;
}
```
This crashes the parser in release, when ASTReader tries to load the
enumerator declaration.
`__is_referenceable` is almost unused in the wild, and the few cases I
was able to find had checks around them. Since the places in the
standard library where `__is_referenceable` is used have bespoke
builtins, it doesn't make a ton of sense to keep this builtin around.
`__is_referenceable` has been documented as deprecated in Clang 20.
Added a new `-Wpre-c++26-compat` warning for when this feature is used
in C++26 and a `-Wc++26-extensions` warning for when this is used in
C++11 through C++23.
---------
Co-authored-by: cor3ntin <corentinjabot@gmail.com>
Diagnose this early after parsing declaration specifiers; this allows us
to issue a better diagnostic. This also checks for `concept friend` and
concept declarations w/o a template-head because it’s easiest to do that
at the same time.
Fixes#45182.
`is_null_pointer` can be implemented very efficiently as
`__is_same(__remove_cv(T), decltype(nullptr))`. Since GCC supports both
of these builtins as well, libc++ has no interest in using
`__is_nullptr` instead. Furthermore, I could find only a single use in
the wild
(https://sourcegraph.com/search?q=context:global+__is_nullptr%28+-file:clang&patternType=keyword&sm=0).
Because of these reasons I don't think it's worth keeping this builtin
around.
Implements `export` keyword in HLSL.
There are two ways the `export` keyword can be used:
1. On individual function declarations
```
export void f() {}
```
2. On a group of function declaration:
```
export {
void f1();
void f2() {}
}
```
Functions declared with the `export` keyword have external linkage. The
implementation does not include validation of when a function can or
cannot be exported, such as when it has resource argument or semantic
annotations. That will be covered by llvm/llvm-project#93330.
Currently all function declarations in global or named namespaces have
external linkage by default so there are no specific code changes
required right now to make sure exported function have external linkage
as well. That will change as part of llvm/llvm-project#92071. Any
additional changes to make sure exported functions still have external
linkage will be done as part of this work item.
Fixes#92812
`MaybeParseHLSLAnnotations` should be run on Field Decls instead of just
assuming that any colon after a field decl is a bitfield. In the case
that HLSL is the language, the code after the colon may be an
annotation. This PR gives the parser a chance to parse the subsequent
text as if it was an HLSL annotation.
The burden of parsing is now on the HLSL parser, but the actual work
needs to be done in handling every case of an hlsl annotation on a field
decl. SV_DispatchThreadID was straightforward enough to implement in
this PR, and tests have been added that the annotation appears as an
attribute in the AST.
Previously, the `hlsl_annotations_on_struct_members.hlsl` test would
result in an error shown below on the line that declares variable `a` in
struct Eg9:
error: use of undeclared identifier
'SV_DispatchThreadID'
This is because the annotation is parsed as if it was a c++ bit field,
and an identifier
that represents an integer is expected, but not found.
This test ensures that hlsl annotations are parsed when parsing struct
decls.
This test not only ensures we make progress by moving the validation
error from the realm of
C++ and expecting bitfields, to HLSL and a specialized error for the
recognized annotation, but also
validates that the parser does parse the annotation and adds an
attribute to the field decl in the AST.
Fixes https://github.com/llvm/llvm-project/issues/57889
According to [temp.expl.spec] p2:
> The declaration in an _explicit-specialization_ shall not be an
_export-declaration_. An explicit specialization shall not use a
_storage-class-specifier_ other than `thread_local`.
Clang partially implements this, but a number of issues exist:
1. We don't diagnose class scope explicit specializations of variable
templates with _storage-class-specifiers_, e.g.
```
struct A
{
template<typename T>
static constexpr int x = 0;
template<>
static constexpr int x<void> = 1; // ill-formed, but clang accepts
};
````
2. We incorrectly reject class scope explicit specializations of
variable templates when `static` is not used, e.g.
```
struct A
{
template<typename T>
static constexpr int x = 0;
template<>
constexpr int x<void> = 1; // error: non-static data member cannot be
constexpr; did you intend to make it static?
};
````
3. We don't diagnose dependent class scope explicit specializations of
function templates with storage class specifiers, e.g.
```
template<typename T>
struct A
{
template<typename U>
static void f();
template<>
static void f<int>(); // ill-formed, but clang accepts
};
````
This patch addresses these issues as follows:
- # 1 is fixed by issuing a diagnostic when an explicit
specialization of a variable template has storage class specifier
- # 2 is fixed by considering any non-function declaration with any
template parameter lists at class scope to be a static data member. This
also allows for better error recovery (it's more likely the user
intended to declare a variable template than a "field template").
- # 3 is fixed by checking whether a function template explicit
specialization has a storage class specifier even when the primary
template is not yet known.
One thing to note is that it would be far simpler to diagnose this when
parsing the _decl-specifier-seq_, but such an implementation would
necessitate a refactor of `ParsedTemplateInfo` which I believe to be
outside the scope of this patch.
This is a followup to #81014 and #84582: Before this patch, Clang
would accept `__attribute__((assume))` and `[[clang::assume]]` as
nonstandard spellings for the `[[omp::assume]]` attribute; this
resulted in a potentially very confusing name clash with C++23’s
`[[assume]]` attribute (and GCC’s `assume` attribute with the same
semantics).
This pr replaces every usage of `__attribute__((assume))` with
`[[omp::assume]]` and makes `__attribute__((assume))` and
`[[clang::assume]]` alternative spellings for C++23’s `[[assume]]`;
this shouldn’t cause any problems due to differences in appertainment
and because almost no-one was using this variant spelling to begin
with (a use in libclc has already been changed to use a different
attribute).
This patch continues previous efforts to split `Sema` up, this time
covering code completion.
Context can be found in #84184.
Dropping `Code` prefix from function names in `SemaCodeCompletion` would
make sense, but I think this PR has enough changes already.
As usual, formatting changes are done as a separate commit. Hopefully
this helps with the review.