18 Commits

Author SHA1 Message Date
Doug Wyatt
fa6cc7eade
[Clang] FunctionEffects: ignore (methods of) local CXXRecordDecls. (#166078)
In the following example, `Functor::method()` inappropriately triggers a
diagnostic that `outer()` is blocking by allocating memory.

```
void outer() [[clang::nonblocking]]
{
	struct Functor {
		int* ptr;
		
		void method() { ptr = new int; }
	};
}
```

---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2025-11-05 07:45:33 -08:00
Doug Wyatt
bc0d0cf3ac
[Clang] FunctionEffect analysis was missing a CXXBindTemporaryExpr's implicit call to a destructor. (#166110)
This example is reduced from a discovery: resetting a shared pointer
from a nonblocking function is not diagnosed.

```
void nb23()
{
	struct X {
		int *ptr = nullptr;
		X() {}
		~X() { delete ptr; }
	};

	auto inner = []() [[clang::nonblocking]] {
		X();
	};
}
```

`shared_ptr<T>::reset()` creates a temporary `shared_ptr` and swaps it
with its current state. The temporary `shared_ptr` constructor is
nonblocking but its destructor potentially deallocates memory and is
unsafe.

Analysis was ignoring the implicit call in the AST to destroy the
temporary.

---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2025-11-03 13:39:56 -08:00
Doug Wyatt
ccc473254f
[Clang] FunctionEffects: properly extract the type of a bound member member function from a CallExpr. (#166101)
There's a bug illustrated by this example:

```
template <typename T>
struct Holder {
	T value;
	
	T& operator*() { return value; }
};

struct X {
	using Dispatch = float (X::*)() [[clang::nonblocking]];
    
	void fails(Holder<Dispatch>& holder) [[clang::nonblocking]]
	{
		(this->*(*holder))();   <<< the expression is incorrectly determined not to be nonblocking
	}

	void succeeds(Holder<Dispatch>& holder) [[clang::nonblocking]]
	{
		auto func = *holder;
		(this->*func)();
	}
};
```

In both cases we have a `CXXMemberCallExpr`. In `succeeds`, the
expression refers to a `Decl` (`func`) and gets a useful PTMF type. In
`fails`, the expression does not refer to a `Decl` and its type is
special, printed as `bound member function`. `Expr` provides a method
for extracting the true type so we can use that in this situation.

---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
Co-authored-by: Sirraide <aeternalmail@gmail.com>
2025-11-03 12:26:49 -08:00
Matheus Izvekov
249167a898
[clang] NFC: reintroduce clang/include/clang/AST/Type.h (#155050)
This reintroduces `Type.h`, having earlier been renamed to `TypeBase.h`,
as a redirection to `TypeBase.h`, and redirects most users to include
the former instead.

This is a preparatory patch for being able to provide inline definitions
for `Type` methods which would otherwise cause a circular dependency
with `Decl{,CXX}.h`.

Doing these operations into their own NFC patch helps the git rename
detection logic work, preserving the history.

This patch makes clang just a little slower to build (~0.17%), just
because it makes more code indirectly include `DeclCXX.h`.
2025-08-27 13:11:34 -03:00
Matheus Izvekov
bcd1530836
[clang] NFC: rename clang/include/clang/AST/Type.h to TypeBase.h (#155049)
This is a preparatory patch, to be able to provide inline definitions
for `Type` functions which depend on `Decl{,CXX}.h`. As the latter also
depends on `Type.h`, this would not be possible without some
reorganizing.

Splitting this rename into its own patch allows git to track this as a
rename, and preserve all git history, and not force any code
reformatting.

A later NFC patch will reintroduce `Type.h` as redirection to
`TypeBase.h`, rewriting most places back to directly including `Type.h`
instead of `TypeBase.h`, leaving only a handful of places where this is
necessary.

Then yet a later patch will exploit this by making more stuff inline.
2025-08-27 13:09:48 -03:00
Matheus Izvekov
91cdd35008
[clang] Improve nested name specifier AST representation (#147835)
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:

![image](https://github.com/user-attachments/assets/700dce98-2cab-4aa8-97d1-b038c0bee831)

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
2025-08-09 05:06:53 -03:00
Matheus Izvekov
49fd0bf35d
[clang] support pack expansions for trailing requires clauses (#133190) 2025-04-03 12:36:15 -03:00
Kazu Hirata
286f8423c5
[Sema] Migrate away from PointerUnion::dyn_cast (NFC) (#123158)
Note that PointerUnion::dyn_cast has been soft deprecated in
PointerUnion.h:

  // FIXME: Replace the uses of is(), get() and dyn_cast() with
  //        isa<T>, cast<T> and the llvm::dyn_cast<T>

Literal migration would result in dyn_cast_if_present (see the
definition of PointerUnion::dyn_cast), but this patch uses dyn_cast
because we expect AP to be nonnull.
2025-01-16 08:45:03 -08:00
Kazu Hirata
1e3e199ed9
[Sema] Migrate away from PointerUnion::{is,get} (NFC) (#117498)
Note that PointerUnion::{is,get} have been soft deprecated in
PointerUnion.h:

  // FIXME: Replace the uses of is(), get() and dyn_cast() with
  //        isa<T>, cast<T> and the llvm::dyn_cast<T>

I'm not touching PointerUnion::dyn_cast for now because it's a bit
complicated; we could blindly migrate it to dyn_cast_if_present, but
we should probably use dyn_cast when the operand is known to be
non-null.
2024-11-27 09:13:28 -08:00
smanna12
4389220549
[Clang] Prevent potential null pointer dereferences (#117176)
This commit addresses several null pointer issues identified by static
analysis by replacing dyn_cast<> with cast<> and getAs<> with castAs<>
in various parts of the Clang codebase. The cast and castAs method is
used to ensure that the type is correctly cast, which helps prevent
potential null pointer dereferences.

Changes:
1. ASTContext.cpp:
Replaced dyn_cast with cast to ensure that the type is correctly cast to
AttributedType.

2. SemaFunctionEffects.cpp:
Replaced getAs with castAs to ensure that the type is correctly cast to
FunctionProtoType.

3. SemaHLSL.cpp:
Replaced getAs with castAs to ensure that the type is correctly cast to
VectorType.
2024-11-22 08:41:20 -06:00
Doug Wyatt
39bdf7a9db
[Clang] SemaFunctionEffects: Fix bug where lambdas produced by template expansion weren't verified. (#116505)
---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2024-11-18 16:04:10 -08:00
Sirraide
dde802b153
[Clang] [NFC] Refactor AST visitors in Sema and the static analyser to use DynamicRecursiveASTVisitor (#115144)
This pr refactors all recursive AST visitors in `Sema`, `Analyze`, and
`StaticAnalysis` to inherit from DRAV instead. This is over half of the
visitors that inherit from RAV directly.

See also #115132, #110040, #93462

LLVM Compile-Time Tracker link for this branch:
https://llvm-compile-time-tracker.com/compare.php?from=5adb5c05a2e9f31385fbba8b0436cbc07d91a44d&to=b58e589a86c06ba28d4d90613864d10be29aa5ba&stat=instructions%3Au
2024-11-15 08:04:08 +01:00
Doug Wyatt
3e30b365c1
[Clang] SemaFunctionEffects: When verifying a function, ignore any conditional noexcept expression. (#115342)
---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2024-11-10 17:02:50 -08:00
Doug Wyatt
7f9d348eb2
[Clang] SemaFunctionEffects: When verifying a function, ignore any trailing requires clause. (#114266)
---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2024-11-05 10:51:01 +01:00
Jinsong Ji
19aa4c854a
[NFC] Fix implicit-fallthrough warnings (#112825)
This is one of the many PRs to fix errors with LLVM_ENABLE_WERROR=on.
Built by GCC 11.

Fix warnings:

clang/lib/Sema/SemaFunctionEffects.cpp:1531:5: error: this statement may
fall through [-Werror=implicit-fallthrough=]
 1531 |     switch (DiffKind) {
      |     ^~~~~~
2024-10-18 11:42:57 +02:00
Doug Wyatt
cef66aa04d
[Clang] Diagnose additional ObjC statements as function effect violations (#112148)
Bug fix: `@autoreleasepool`, `@synchronized`, and `@finally` were not
being noticed and treated as function effect violations.

---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2024-10-14 17:49:30 +02:00
Doug Wyatt
4d218caa77
[Clang] [Sema] Effects: Correctly detect (x ? a : b) as nonblocking when a and b are (#111224)
Correctly detect `(x ? a : b)` as nonblocking when `a` and `b` are. Use 
`FunctionEffectsRef::get` to get to the actual effect set instead of trying 
to retrieve it manually via the `FunctionProtoType` as we may have to 
look through function pointers etc. in some cases.

---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
2024-10-08 10:20:05 +02:00
Doug Wyatt
7fe43ada28
[Clang] nonblocking/nonallocating attributes: 2nd pass caller/callee analysis (#99656)
- In Sema, when encountering Decls with function effects needing
verification, add them to a vector, DeclsWithEffectsToVerify.
- Update AST serialization to include DeclsWithEffectsToVerify.
- In AnalysisBasedWarnings, use DeclsWithEffectsToVerify as a work
queue, verifying functions with declared effects, and inferring (when
permitted and necessary) whether their callees have effects.

---------

Co-authored-by: Doug Wyatt <dwyatt@apple.com>
Co-authored-by: Sirraide <aeternalmail@gmail.com>
Co-authored-by: Erich Keane <ekeane@nvidia.com>
2024-10-03 02:14:51 +02:00