Commit Graph

4751 Commits

Author SHA1 Message Date
Kazu Hirata 22731dbd75 [clang] Use std::nullopt instead of None in comments (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-04 20:31:05 -08:00
Kazu Hirata 35b4fbb559 [clang] Use std::nullopt instead of None in comments (NFC)
This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-04 15:57:24 -08:00
Kazu Hirata 180600660b [StaticAnalyzer] Use std::nullopt instead of None (NFC)
This patch mechanically replaces None with std::nullopt where the
compiler would warn if None were deprecated.  The intent is to reduce
the amount of manual work required in migrating from Optional to
std::optional.

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-12-03 11:34:24 -08:00
Jan Svoboda abf0c6c0c0 Use CTAD on llvm::SaveAndRestore
Reviewed By: dblaikie

Differential Revision: https://reviews.llvm.org/D139229
2022-12-02 15:36:12 -08:00
Alex Richardson a602f76a24 [clang][TargetInfo] Use LangAS for getPointer{Width,Align}()
Mixing LLVM and Clang address spaces can result in subtle bugs, and there
is no need for this hook to use the LLVM IR level address spaces.
Most of this change is just replacing zero with LangAS::Default,
but it also allows us to remove a few calls to getTargetAddressSpace().

This also removes a stale comment+workaround in
CGDebugInfo::CreatePointerLikeType(): ASTContext::getTypeSize() does
return the expected size for ReferenceType (and handles address spaces).

Differential Revision: https://reviews.llvm.org/D138295
2022-11-30 20:24:01 +00:00
Balazs Benics dbb94b415a [analyzer] Remove the unused LocalCheckers.h header 2022-11-28 13:08:38 +01:00
Kazu Hirata 20ba079dda [StaticAnalyzer] Don't use Optional::create (NFC)
Note that std::optional does not offer create().

This is part of an effort to migrate from llvm::Optional to
std::optional:

https://discourse.llvm.org/t/deprecating-llvm-optional-x-hasvalue-getvalue-getvalueor/63716
2022-11-25 15:38:53 -08:00
Balazs Benics 097ce76165 [analyzer] Deprecate FAM analyzer-config, recommend -fstrict-flex-arrays instead
By default, clang assumes that all trailing array objects could be a
FAM. So, an array of undefined size, size 0, size 1, or even size 42 is
considered as FAMs for optimizations at least.

One needs to override the default behavior by supplying the
`-fstrict-flex-arrays=<N>` flag, with `N > 0` value to reduce the set of
FAM candidates. Value `3` is the most restrictive and `0` is the most
permissive on this scale.

0: all trailing arrays are FAMs
1: only incomplete, zero and one-element arrays are FAMs
2: only incomplete, zero-element arrays are FAMs
3: only incomplete arrays are FAMs

If the user is happy with consdering single-element arrays as FAMs, they
just need to remove the
`consider-single-element-arrays-as-flexible-array-members` from the
command line.
Otherwise, if they don't want to recognize such cases as FAMs, they
should specify `-fstrict-flex-arrays` anyway, which will be picked up by
CSA.

Any use of the deprecated analyzer-config value will trigger a warning
explaining what to use instead.
The `-analyzer-config-help` is updated accordingly.

Depends on D138657

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D138659
2022-11-25 10:24:56 +01:00
Balazs Benics 93b98eb399 [analyzer] getBinding should auto-detect type only if it was not given
Casting a pointer to a suitably large integral type by reinterpret-cast
should result in the same value as by using the `__builtin_bit_cast()`.
The compiler exploits this: https://godbolt.org/z/zMP3sG683

However, the analyzer does not bind the same symbolic value to these
expressions, resulting in weird situations, such as failing equality
checks and even results in crashes: https://godbolt.org/z/oeMP7cj8q

Previously, in the `RegionStoreManager::getBinding()` even if `T` was
non-null, we replaced it with `TVR->getValueType()` in case the `MR` was
`TypedValueRegion`.
It doesn't make much sense to auto-detect the type if the type is
already given. By not doing the auto-detection, we would just do the
right thing and perform the load by that type.
This means that we will cast the value to that type.

So, in this patch, I'm proposing to do auto-detection only if the type
was null.

Here is a snippet of code, annotated by the previous and new dump values.
`LocAsInteger` should wrap the `SymRegion`, since we want to load the
address as if it was an integer.
In none of the following cases should type auto-detection be triggered,
hence we should eventually reach an `evalCast()` to lazily cast the loaded
value into that type.

```lang=C++
void LValueToRValueBitCast_dumps(void *p, char (*array)[8]) {
  clang_analyzer_dump(p);     // remained: &SymRegion{reg_$0<void * p>}
  clang_analyzer_dump(array); // remained: {{&SymRegion{reg_$1<char (*)[8] array>}
  clang_analyzer_dump((unsigned long)p);
  // remained: {{&SymRegion{reg_$0<void * p>} [as 64 bit integer]}}
  clang_analyzer_dump(__builtin_bit_cast(unsigned long, p));     <--------- change #1
  // previously: {{&SymRegion{reg_$0<void * p>}}}
  // now:        {{&SymRegion{reg_$0<void * p>} [as 64 bit integer]}}
  clang_analyzer_dump((unsigned long)array); // remained: {{&SymRegion{reg_$1<char (*)[8] array>} [as 64 bit integer]}}
  clang_analyzer_dump(__builtin_bit_cast(unsigned long, array)); <--------- change #2
  // previously: {{&SymRegion{reg_$1<char (*)[8] array>}}}
  // now:        {{&SymRegion{reg_$1<char (*)[8] array>} [as 64 bit integer]}}
}
```

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D136603
2022-11-23 15:52:11 +01:00
Vaibhav Yenamandra 7b6fe711b2 Refactor StaticAnalyzer to use `clang::SarifDocumentWriter`
Refactor StaticAnalyzer to use clang::SarifDocumentWriter for
serializing sarif diagnostics.

Uses clang::SarifDocumentWriter to generate SARIF output in the
StaticAnalyzer.

Various bugfixes are also made to clang::SarifDocumentWriter.

Summary of changes:

clang/lib/Basic/Sarif.cpp:
  * Fix bug in adjustColumnPos introduced from prev move, it now uses
    FullSourceLoc::getDecomposedExpansionLoc which provides the correct
    location (in the presence of macros) instead of
    FullSourceLoc::getDecomposedLoc.
  * Fix createTextRegion so that it handles caret ranges correctly,
    this should bring it to parity with the previous implementation.

clang/test/Analysis/diagnostics/Inputs/expected-sarif:
  * Update the schema URL to the offical website
  * Add the emitted defaultConfiguration sections to all rules
  * Annotate results with the "level" property

clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp:
  * Update SarifDiagnostics class to hold a clang::SarifDocumentWriter
    that it uses to convert diagnostics to SARIF.
2022-11-17 14:47:02 -05:00
Tomasz Kamiński 2fb3bec932 [analyzer] Fix crash for array-delete of UnknownVal values.
We now skip the destruction of array elements for `delete[] p`,
if the value of `p` is UnknownVal and does not have corresponding region.
This eliminate the crash in `getDynamicElementCount` on that
region and matches the behavior for deleting the array of
non-constant range.

Reviewed By: isuckatcs

Differential Revision: https://reviews.llvm.org/D136671
2022-11-09 15:06:46 +01:00
Rageking8 94738a5ac3 Fix duplicate word typos; NFC
This revision fixes typos where there are 2 consecutive words which are
duplicated. There should be no code changes in this revision (only
changes to comments and docs). Do let me know if there are any
undesirable changes in this revision. Thanks.
2022-11-08 07:21:23 -05:00
Nathan James 108e41d962
[clang][NFC] Use c++17 style variable type traits
This was done as a test for D137302 and it makes sense to push these changes

Reviewed By: shafik

Differential Revision: https://reviews.llvm.org/D137491
2022-11-07 18:25:48 +00:00
Jennifer Yu ea64e66f7b [OPENMP]Initial support for error directive.
Differential Revision: https://reviews.llvm.org/D137209
2022-11-02 14:25:28 -07:00
Bill Wendling 7f93ae8086 [clang] Implement -fstrict-flex-arrays=3
The -fstrict-flex-arrays=3 is the most restrictive type of flex arrays.
No number, including 0, is allowed in the FAM. In the cases where a "0"
is used, the resulting size is the same as if a zero-sized object were
substituted.

This is needed for proper _FORTIFY_SOURCE coverage in the Linux kernel,
among other reasons. So while the only reason for specifying a
zero-length array at the end of a structure is for specify a FAM,
treating it as such will cause _FORTIFY_SOURCE not to work correctly;
__builtin_object_size will report -1 instead of 0 for a destination
buffer size to keep any kernel internals from using the deprecated
members as fake FAMs.

For example:

  struct broken {
      int foo;
      int fake_fam[0];
      struct something oops;
  };

There have been bugs where the above struct was created because "oops"
was added after "fake_fam" by someone not realizing. Under
__FORTIFY_SOURCE, doing:

  memcpy(p->fake_fam, src, len);

raises no warnings when __builtin_object_size(p->fake_fam, 1) returns -1
and may stomp on "oops."

Omitting a warning when using the (invalid) zero-length array is how GCC
treats -fstrict-flex-arrays=3. A warning in that situation is likely an
irritant, because requesting this option level is explicitly requesting
this behavior.

Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101836

Differential Revision: https://reviews.llvm.org/D134902
2022-10-27 10:50:04 -07:00
Kristóf Umann a504ddc8bf [analyzer] Initialize regions returned by CXXNew to undefined
Discourse mail:
https://discourse.llvm.org/t/analyzer-why-do-we-suck-at-modeling-c-dynamic-memory/65667

malloc() returns a piece of uninitialized dynamic memory. We were (almost)
always able to model this behaviour. Its C++ counterpart, operator new is a
lot more complex, because it allows for initialization, the most complicated of which is the usage of constructors.

We gradually became better in modeling constructors, but for some reason, most
likely for reasons lost in history, we never actually modeled the case when the
memory returned by operator new was just simply uninitialized. This patch
(attempts) to fix this tiny little error.

Differential Revision: https://reviews.llvm.org/D135375
2022-10-26 17:22:12 +02:00
Gabor Marton 82a50812f7 [analyzer][StdLibraryFunctionsChecker] Add NoteTags for applied arg
constraints

In this patch I add a new NoteTag for each applied argument constraint.
This way, any other checker that reports a bug - where the applied
constraint is relevant - will display the corresponding note. With this
change we provide more information for the users to understand some
bug reports easier.

Differential Revision: https://reviews.llvm.org/D101526

Reviewed By: NoQ
2022-10-26 16:33:25 +02:00
Balazs Benics aa12a48c82 [analyzer] Fix assertion failure with conflicting prototype calls
It turns out we can reach the `Init.castAs<nonlock::CompoundVal>()`
expression with other kinds of SVals. Such as by `nonloc::ConcreteInt`
in this example: https://godbolt.org/z/s4fdxrcs9

```lang=C++
int buffer[10];
void b();
void top() {
  b(&buffer);
}
void b(int *c) {
  *c = 42; // would crash
}
```
In this example, we try to store `42` to the `Elem{buffer, 0}`.

This situation can appear if the CallExpr refers to a function
declaration without prototype. In such cases, the engine will pick the
redecl of the referred function decl which has function body, hence has
a function prototype.

This weird situation will have an interesting effect to the AST, such as
the argument at the callsite will miss a cast, which would cast the
`int (*)[10]` expression into `int *`, which means that when we evaluate
the `*c = 42` expression, we want to bind `42` to an array, causing the
crash.

Look at the AST of the callsite with and without the function prototype:
https://godbolt.org/z/Gncebcbdb
The only difference is that without the proper function prototype, we
will not have the `ImplicitCastExpr` `BitCasting` from `int (*)[10]`
to `int *` to match the expected type of the parameter declaration.

In this patch, I'm proposing to emit a cast in the mentioned edge-case,
to bind the argument value of the expected type to the parameter.

I'm only proposing this if the runtime definition has exactly the same
number of parameters as the callsite feeds it by arguments.
If that's not the case, I believe, we are better off by binding `Unknown`
to those parameters.

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D136162
2022-10-26 11:27:01 +02:00
Tomasz Kamiński 6194229c62 [analyzer] Make directly bounded LazyCompoundVal as lazily copied
Previously, `LazyCompoundVal` bindings to subregions referred by
`LazyCopoundVals`, were not marked as //lazily copied//.

This change returns `LazyCompoundVals` from `getInterestingValues()`,
so their regions can be marked as //lazily copied// in `RemoveDeadBindingsWorker::VisitBinding()`.

Depends on D134947

Authored by: Tomasz Kamiński <tomasz.kamiński@sonarsource.com>

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D135136
2022-10-19 16:06:32 +02:00
Tomasz Kamiński a6b42040ad [analyzer] Fix the liveness of Symbols for values in regions referred by LazyCompoundVal
To illustrate our current understanding, let's start with the following program:
https://godbolt.org/z/33f6vheh1
```lang=c++
void clang_analyzer_printState();

struct C {
   int x;
   int y;
   int more_padding;
};

struct D {
   C c;
   int z;
};

C foo(D d, int new_x, int new_y) {
   d.c.x = new_x;       // B1
   assert(d.c.x < 13);  // C1

   C c = d.c;           // L

   assert(d.c.y < 10);  // C2
   assert(d.z < 5);     // C3

   d.c.y = new_y;       // B2

   assert(d.c.y < 10);  // C4

   return c;  // R
}
```
In the code, we create a few bindings to subregions of root region `d` (`B1`, `B2`), a constrain on the values  (`C1`, `C2`, ….), and create a `lazyCompoundVal` for the part of the region `d` at point `L`, which is returned at point `R`.

Now, the question is which of these should remain live as long the return value of the `foo` call is live. In perfect a word we should preserve:

  # only the bindings of the subregions of `d.c`, which were created before the copy at `L`. In our example, this includes `B1`, and not `B2`.  In other words, `new_x` should be live but `new_y` shouldn’t.

  # constraints on the values of `d.c`, that are reachable through `c`. This can be created both before the point of making the copy (`L`) or after. In our case, that would be `C1` and `C2`. But not `C3` (`d.z` value is not reachable through `c`) and `C4` (the original value of`d.c.y` was overridden at `B2` after the creation of `c`).

The current code in the `RegionStore` covers the use case (1), by using the `getInterestingValues()` to extract bindings to parts of the referred region present in the store at the point of copy. This also partially covers point (2), in case when constraints are applied to a location that has binding at the point of the copy (in our case `d.c.x` in `C1` that has value `new_x`), but it fails to preserve the constraints that require creating a new symbol for location (`d.c.y` in `C2`).

We introduce the concept of //lazily copied// locations (regions) to the `SymbolReaper`, i.e. for which a program can access the value stored at that location, but not its address. These locations are constructed as a set of regions referred to by `lazyCompoundVal`. A //readable// location (region) is a location that //live// or //lazily copied// . And symbols that refer to values in regions are alive if the region is //readable//.

For simplicity, we follow the current approach to live regions and mark the base region as //lazily copied//, and consider any subregions as //readable//. This makes some symbols falsy live (`d.z` in our example) and keeps the corresponding constraints alive.

The rename `Regions` to `LiveRegions` inside  `RegionStore` is NFC change, that was done to make it clear, what is difference between regions stored in this two sets.

Regression Test: https://reviews.llvm.org/D134941
Co-authored-by: Balazs Benics <benicsbalazs@gmail.com>

Reviewed By: martong, xazax.hun

Differential Revision: https://reviews.llvm.org/D134947
2022-10-19 16:06:32 +02:00
Kazu Hirata 08901c8a98 [clang] Use llvm::reverse (NFC) 2022-10-15 21:54:13 -07:00
Matheus Izvekov bcd9ba2b7e
[clang] Track the templated entity in type substitution.
This is a change to how we represent type subsitution in the AST.
Instead of only storing the replaced type, we track the templated
entity we are substituting, plus an index.
We modify MLTAL to track the templated entity at each level.

Otherwise, it's much more expensive to go from the template parameter back
to the templated entity, and not possible to do in some cases, as when
we instantiate outer templates, parameters might still reference the
original entity.

This also allows us to very cheaply lookup the templated entity we saw in
the naming context and find the corresponding argument it was replaced
from, such as for implementing template specialization resugaring.

Signed-off-by: Matheus Izvekov <mizvekov@gmail.com>

Differential Revision: https://reviews.llvm.org/D131858
2022-10-15 22:08:36 +02:00
Balazs Benics b062ee7dc4 [analyzer] Workaround crash on encountering Class non-type template parameters
The Clang Static Analyzer will crash on this code:
```lang=C++
struct Box {
  int value;
};
template <Box V> int get() {
  return V.value;
}
template int get<Box{-1}>();
```
https://godbolt.org/z/5Yb1sMMMb

The problem is that we don't account for encountering `TemplateParamObjectDecl`s
within the `DeclRefExpr` handler in the `ExprEngine`.

IMO we should create a new memregion for representing such template
param objects, to model their language semantics.
Such as:
 - it should have global static storage
 - for two identical values, their addresses should be identical as well
http://eel.is/c%2B%2Bdraft/temp.param#8

I was thinking of introducing a `TemplateParamObjectRegion` under `DeclRegion`
for this purpose. It could have `TemplateParamObjectDecl` as a field.

The `TemplateParamObjectDecl::getValue()` returns `APValue`, which might
represent multiple levels of structures, unions and other goodies -
making the transformation from `APValue` to `SVal` a bit complicated.

That being said, for now, I think having `Unknowns` for such cases is
definitely an improvement to crashing, hence I'm proposing this patch.

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D135763
2022-10-13 08:41:31 +02:00
Arseniy Zaostrovnykh ec6da3fb9d Fix false positive related to handling of [[noreturn]] function pointers
Before this change, the `NoReturnFunctionChecker` was missing function pointers
with a `[[noreturn]]` attribute, while `CFG` was constructed taking that into
account, which leads CSA to take impossible paths. The reason was that the
`NoReturnFunctionChecker` was looking for the attribute in the type of the
entire call expression rather than the type of the function being called.

This change makes the `[[noreturn]]` attribute of a function pointer visible
to `NoReturnFunctionChecker`. This leads to a more coherent behavior of the
CSA on the AST involving.

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D135682
2022-10-12 14:46:32 +02:00
Soumi Manna 3b652fc6d6 [analyzer] Fix static code analysis concerns
ProcessMemberDtor(), ProcessDeleteDtor(), and ProcessAutomaticObjDtor():
Fix static analyzer warnings with suspicious dereference of pointer
'Pred' in function call before NULL checks - NFCI

Differential Revision: https://reviews.llvm.org/D135290
2022-10-07 16:58:37 +02:00
Bill Wendling 7404b855e5 [clang][NFC] Use enum for -fstrict-flex-arrays
Use enums for the strict flex arrays flag so that it's more readable.

Differential Revision: https://reviews.llvm.org/D135107
2022-10-06 10:45:41 -07:00
Argyrios Kyrtzidis 371883f46d [clang/Sema] Fix non-deterministic order for certain kind of diagnostics
In the context of caching clang invocations it is important to emit diagnostics in deterministic order;
the same clang invocation should result in the same diagnostic output.

rdar://100336989

Differential Revision: https://reviews.llvm.org/D135118
2022-10-05 12:58:01 -07:00
Tomasz Kamiński 4ff836a138 [analyzer] Pass correct bldrCtx to computeObjectUnderConstruction
In case when the prvalue is returned from the function (kind is one
of `SimpleReturnedValueKind`, `CXX17ElidedCopyReturnedValueKind`),
then it construction happens in context of the caller.
We pass `BldrCtx` explicitly, as `currBldrCtx` will always refer to callee
context.

In the following example:
```
struct Result {int value; };
Result create() { return Result{10}; }
int accessValue(Result r) { return r.value; }

void test() {
   for (int i = 0; i < 2; ++i)
      accessValue(create());
}
```

In case when the returned object was constructed directly into the
argument to a function call `accessValue(create())`, this led to
inappropriate value of `blockCount` being used to locate parameter region,
and as a consequence resulting object (from `create()`) was constructed
into a different region, that was later read by inlined invocation of
outer function (`accessValue`).
This manifests itself only in case when calling block is visited more
than once (loop in above example), as otherwise there is no difference
in `blockCount` value between callee and caller context.
This happens only in case when copy elision is disabled (before C++17).

Reviewed By: NoQ

Differential Revision: https://reviews.llvm.org/D132030
2022-09-26 11:39:10 +02:00
Jan Korous 85d97aac80 [analyzer] Support implicit parameter 'self' in path note
showBRParamDiagnostics assumed stores happen only via function parameters while that
can also happen via implicit parameters like 'self' or 'this'.
The regression test caused a failed assert in the original cast to ParmVarDecl.

Differential Revision: https://reviews.llvm.org/D133815
2022-09-21 17:26:09 -07:00
isuckatcs 6931d311ea [analyzer] Cleanup some artifacts from non-POD array evaluation
Most of the state traits used for non-POD array evaluation were
only cleaned up if the ctors/dtors were inlined, since the cleanup
happened in ExprEngine::processCallExit(). This patch makes sure
they are removed even if said functions are not inlined.

Differential Revision: https://reviews.llvm.org/D133643
2022-09-17 22:46:27 +02:00
Kazu Hirata 8009d236e5 [clang] Don't include SetVector.h (NFC) 2022-09-17 13:36:13 -07:00
Balazs Benics 7cddf9cad1 [analyzer] Dump the environment entry kind as well
By this change the `exploded-graph-rewriter` will display the class kind
of the expression of the environment entry. It makes easier to decide if
the given entry corresponds to the lvalue or to the rvalue of some
expression.

It turns out the rewriter already had support for visualizing it, but
probably was never actually used?

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D132109
2022-09-13 09:04:27 +02:00
Balazs Benics afcd862b2e [analyzer] LazyCompoundVals should be always bound as default bindings
`LazyCompoundVals` should only appear as `default` bindings in the
store. This fixes the second case in this patch-stack.

Depends on: D132142

Reviewed By: xazax.hun

Differential Revision: https://reviews.llvm.org/D132143
2022-09-13 08:58:46 +02:00
Balazs Benics f8643a9b31 [analyzer] Prefer wrapping SymbolicRegions by ElementRegions
It turns out that in certain cases `SymbolRegions` are wrapped by
`ElementRegions`; in others, it's not. This discrepancy can cause the
analyzer not to recognize if the two regions are actually referring to
the same entity, which then can lead to unreachable paths discovered.

Consider this example:

```lang=C++
struct Node { int* ptr; };
void with_structs(Node* n1) {
  Node c = *n1; // copy
  Node* n2 = &c;
  clang_analyzer_dump(*n1); // lazy...
  clang_analyzer_dump(*n2); // lazy...
  clang_analyzer_dump(n1->ptr); // rval(n1->ptr): reg_$2<int * SymRegion{reg_$0<struct Node * n1>}.ptr>
  clang_analyzer_dump(n2->ptr); // rval(n2->ptr): reg_$1<int * Element{SymRegion{reg_$0<struct Node * n1>},0 S64b,struct Node}.ptr>
  clang_analyzer_eval(n1->ptr != n2->ptr); // UNKNOWN, bad!
  (void)(*n1);
  (void)(*n2);
}
```

The copy of `n1` will insert a new binding to the store; but for doing
that it actually must create a `TypedValueRegion` which it could pass to
the `LazyCompoundVal`. Since the memregion in question is a
`SymbolicRegion` - which is untyped, it needs to first wrap it into an
`ElementRegion` basically implementing this untyped -> typed conversion
for the sake of passing it to the `LazyCompoundVal`.
So, this is why we have `Element{SymRegion{.}, 0,struct Node}` for `n1`.

The problem appears if the analyzer evaluates a read from the expression
`n1->ptr`. The same logic won't apply for `SymbolRegionValues`, since
they accept raw `SubRegions`, hence the `SymbolicRegion` won't be
wrapped into an `ElementRegion` in that case.

Later when we arrive at the equality comparison, we cannot prove that
they are equal.

For more details check the corresponding thread on discourse:
https://discourse.llvm.org/t/are-symbolicregions-really-untyped/64406

---

In this patch, I'm eagerly wrapping each `SymbolicRegion` by an
`ElementRegion`; basically canonicalizing to this form.
It seems reasonable to do so since any object can be thought of as a single
array of that object; so this should not make much of a difference.

The tests also underpin this assumption, as only a few were broken by
this change; and actually fixed a FIXME along the way.

About the second example, which does the same copy operation - but on
the heap - it will be fixed by the next patch.

Reviewed By: martong

Differential Revision: https://reviews.llvm.org/D132142
2022-09-13 08:58:46 +02:00
isuckatcs a11e51e91f [analyzer] Track trivial copy/move constructors and initializer lists in the BugReporter
If an object has a trivial copy/move constructor, it's not inlined
on invocation but a trivial copy is performed instead. This patch
handles trivial copies in the bug reporter by matching the field
regions of the 2 objects involved in the copy/move construction,
and tracking the appropriate region further. This patch also
introduces some support for tracking values in initializer lists.

Differential Revision: https://reviews.llvm.org/D131262
2022-09-05 17:06:27 +02:00
isuckatcs a46154cb1c [analyzer] Warn if the size of the array in `new[]` is undefined
This patch introduces a new checker, called NewArraySize checker,
which detects if the expression that yields the element count of
the array in new[], results in an Undefined value.

Differential Revision: https://reviews.llvm.org/D131299
2022-09-04 23:06:58 +02:00
Kazu Hirata b7a7aeee90 [clang] Qualify auto in range-based for loops (NFC) 2022-09-03 23:27:27 -07:00
isuckatcs b5147937b2 [analyzer] Add more information to the Exploded Graph
This patch dumps every state trait in the egraph. Also
the empty state traits are no longer dumped, instead
they are treated as null by the egraph rewriter script,
which solves reverse compatibility issues.

Differential Revision: https://reviews.llvm.org/D131187
2022-09-03 00:21:05 +02:00
Balázs Kéri d56a1c6824 [clang][analyzer] Errno modeling code refactor (NFC).
Some of the code used in StdLibraryFunctionsChecker is applicable to
other checkers, this is put into common functions. Errno related
parts of the checker are simplified and renamed. Documentations in
errno_modeling functions are updated.

This change makes it available to have more checkers that perform
modeling of some standard functions. These can set the errno state
with common functions and the bug report messages (note tags) can
look similar.

Reviewed By: steakhal, martong

Differential Revision: https://reviews.llvm.org/D131879
2022-09-01 09:05:59 +02:00
Martin Storsjö efc76a1ac5 [analyzer] Silence GCC warnings about unused variables. NFC.
Use `isa<T>()` instead of `Type *Var = dyn_cast<T>()`
when the result of the cast isn't used.
2022-08-29 13:26:13 +03:00
ziqingluo-90 a5e354ec4d [analyzer] Fixing a bug raising false positives of stack block object
leaking in ARC mode

When ARC (automatic reference count) is enabled, (objective-c) block
objects are automatically retained and released thus they do not leak.
Without ARC, they still can leak from an expiring stack frame like
other stack variables.
With this commit, the static analyzer now puts a block object in an
"unknown" region if ARC is enabled because it is up to the
implementation to choose whether to put the object on stack initially
(then move to heap when needed) or in heap directly under ARC.
Therefore, the `StackAddrEscapeChecker` has no need to know
specifically about ARC at all and it will not report errors on objects
in "unknown" regions.

Reviewed By: NoQ (Artem Dergachev)

Differential Revision: https://reviews.llvm.org/D131009
2022-08-26 12:19:32 -07:00
isuckatcs e3e9082b01 [analyzer] Fix for incorrect handling of 0 length non-POD array construction
Prior to this patch when the analyzer encountered a non-POD 0 length array,
it still invoked the constructor for 1 element, which lead to false positives.
This patch makes sure that we no longer construct any elements when we see a
0 length array.

Differential Revision: https://reviews.llvm.org/D131501
2022-08-25 12:42:02 +02:00
isuckatcs aac73a31ad [analyzer] Process non-POD array element destructors
The constructors of non-POD array elements are evaluated under
certain conditions. This patch makes sure that in such cases
we also evaluate the destructors.

Differential Revision: https://reviews.llvm.org/D130737
2022-08-24 01:28:21 +02:00
Fred Tingaud 16cb3be626 [analyzer] Deadstore static analysis: Fix false positive on C++17 assignments
Dead store detection automatically checks that an expression is a
CXXConstructor and skips it because of potential side effects. In C++17,
with guaranteed copy elision, this check can fail because we actually
receive the implicit cast of a CXXConstructor.
Most checks in the dead store analysis were already stripping all casts
and parenthesis and those that weren't were either forgotten (like the
constructor) or would not suffer from it, so this patch proposes to
factorize the stripping.
It has an impact on where the dead store warning is reported in the case
of an explicit cast, from

  auto a = static_cast<B>(A());
           ^~~~~~~~~~~~~~~~~~~

to

  auto a = static_cast<B>(A());
                          ^~~

which we think is an improvement.

Patch By: frederic-tingaud-sonarsource

Reviewed By: steakhal

Differential Revision: https://reviews.llvm.org/D126534
2022-08-23 18:33:26 +02:00
isuckatcs c81bf940c7 [analyzer] Handling non-POD multidimensional arrays in ArrayInitLoopExpr
This patch makes it possible for lambdas, implicit copy/move ctors
and structured bindings to handle non-POD multidimensional arrays.

Differential Revision: https://reviews.llvm.org/D131840
2022-08-22 13:53:53 +02:00
isuckatcs 3c482632e6 [analyzer] Remove pattern matching of lambda capture initializers
Prior to this patch we handled lambda captures based on their
initializer expression, which resulted in pattern matching. With
C++17 copy elision the initializer expression can be anything,
and this approach proved to be fragile and a source of crashes.
This patch removes pattern matching and only checks whether the
object is under construction or not.

Differential Revision: https://reviews.llvm.org/D131944
2022-08-22 13:00:31 +02:00
isuckatcs a47ec1b797 [analyzer][NFC] Be more descriptive when we replay without inlining
This patch adds a ProgramPointTag to the EpsilonPoint created
before we replay a call without inlining.

Differential Revision: https://reviews.llvm.org/D132246
2022-08-19 18:05:52 +02:00
isuckatcs b4e3e3a3eb [analyzer] Fix a crash on copy elided initialized lambda captures
Inside `ExprEngine::VisitLambdaExpr()` we wasn't prepared for a
copy elided initialized capture's `InitExpr`. This patch teaches
the analyzer how to handle such situation.

Differential Revision: https://reviews.llvm.org/D131784
2022-08-13 00:22:01 +02:00
Denys Petrov adcd4b1c0b [analyzer] [NFC] Fix comments into more regular form. 2022-08-11 21:28:23 +03:00
malavikasamak c74a204826 [analyzer] Fix false positive in use-after-move checker
Differential Revision: https://reviews.llvm.org/D131525
2022-08-09 17:26:30 -07:00