Page MenuHomePhabricator

[analyzer] CastValueChecker: Store the dynamic types and casts
ClosedPublic

Authored by Charusso on Aug 15 2019, 5:24 PM.

Details

Summary

This patch introduces DynamicCastInfo similar to DynamicTypeInfo which
is stored in CastSets which are storing the dynamic cast informations of
objects based on memory regions. It could be used to store and check the
casts and prevent infeasible paths.

Diff Detail

Repository
rL LLVM

Event Timeline

Charusso created this revision.Aug 15 2019, 5:24 PM

@xazax.hun It is somehow performance critical code as we have too many casts in the LLVM. I would really appreciate it if you could review it.

Charusso updated this revision to Diff 215893.EditedAug 19 2019, 7:34 AM
Charusso retitled this revision from [analyzer] CastValueChecker: Store the dynamic types in DynamicTypeMap to [analyzer] CastValueChecker: Store the dynamic types and casts.
  • From now we use a set to store the casts.
  • Added a way to dump out the cast informations.
Charusso edited the summary of this revision. (Show Details)Aug 19 2019, 7:36 AM
NoQ added a comment.Aug 19 2019, 3:11 PM

Yay! I understand the rough idea and it looks perfectly reasonable to start with. Please add FIXMEs/TODOs on how we eventually want to support more complicated inheritance hierarchies.

clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
32 ↗(On Diff #215893)

Emm, so you're saving successes and failures of all casts regardless of which object is getting casted? That's definitely not sufficient. If X is a Stmt that isn't an Expr, you can't automatically infer that Y is a Stmt that isn't an Expr for any object Y other than X . This information needs to be per-object. Then you'll need to clean it up in checkDeadSymbols.

Charusso added inline comments.Aug 19 2019, 3:20 PM
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
32 ↗(On Diff #215893)

I have two implementations, the other is set factory based on memory regions. Is it would be a good idea to go through all the regions every time and all their casts to know every possible cast-assumption? I have made it, and I felt like it is overcomplicated as the DynamicTypeMap could be used for asking what is the type now and whether we have better precision and update that information therefore we could update the cast-set as well.

NoQ added inline comments.Aug 19 2019, 3:30 PM
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
32 ↗(On Diff #215893)

It's about correctness, we don't have much choice here. The current data structure simply cannot work correctly because there's a "one vs many" problem in it: for every pair of types (T₁, T₂) there are *many* possible outcomes of a cast from T₁ to T₂ (depending on the object that's being casted) but the current data structure only has room for *one* such outcome. Your data structure is basically saying "Oh, this shape turned out to be a circle, let's from now on forever believe that triangles don't exist" (?)

Charusso added inline comments.Aug 19 2019, 3:36 PM
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
32 ↗(On Diff #215893)

Well, let me swap then with the set factory. I think I could handle that in the current shape, but I cannot say no to your clear idea. Thanks for the factory idea! It does the same at the moment.

Charusso updated this revision to Diff 216023.Aug 19 2019, 4:55 PM
Charusso edited the summary of this revision. (Show Details)
  • Use a set factory to store a dynamic cast information set per memory region.
In D66325#1636091, @NoQ wrote:

Yay! I understand the rough idea and it looks perfectly reasonable to start with. Please add FIXMEs/TODOs on how we eventually want to support more complicated inheritance hierarchies.

I have not decided yet. This only one successful cast allowance is the smallest possible solution, then we need a very great design to do better without exponential path-splitting. I have added a tiny TODO section.

NoQ added inline comments.Aug 19 2019, 5:47 PM
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h
19 ↗(On Diff #216023)

I suggest enum CastResult { Success, Failure } ("a fail" is slang, also "result" because it's basically a result).

Also TODO: The success information should ideally go straight into the dynamic type map.

31–32 ↗(On Diff #216023)

succeeds(), fails() (valid English).

clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
28 ↗(On Diff #216023)

Can we move these macros into the cpp file so that they were only accessed by the fancy accessors?

Also i don't remember whether these macros do actually work correctly in headers. The original code was doing the trait manually because it had GDMIndex() defined in the cpp file, but if we put these macros into the header we'll have a static variable defined in multiple translation units, which may cause it to have different addresses in different dynamically loaded libraries that include this header.

You might need to merge your checkDeadSymbols() into the existing checkDeadSymbols().

clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
83–93 ↗(On Diff #216023)

Most of the time we should know exactly how many pointer/reference types we need to unwrap. I really prefer we hard-assert this knowledge instead of blindly unwrapping as many pointer/reference types as we want. Because every time we have an unexpected number of unwraps it's an indication that something went horribly wrong. So it's good to have the extra sanity checking.

115 ↗(On Diff #216023)

It would have been much easier for me to read if this variable was called CastInfo.

118 ↗(On Diff #216023)

Just CastSucceeds (valid English).

145–152 ↗(On Diff #216023)

To think: in D66423 you added this fancy feature when you dump the current dynamic type of the object instead of the static type. I think this is super cool and we should do it here as well, because the dynamic type is pretty much the only thing that you won't be able to figure out by looking at the source.

We could give the same message as for isa, say, Assuming the object is a 'Circle' etc.

clang/lib/StaticAnalyzer/Core/DynamicTypeMap.cpp
83–86 ↗(On Diff #216023)

My favorite way of writing this stuff:

const CastSet *SetPtr = State->get<DynamicCastMap>(MR);
CastSet Set = SetPtr ? *SetPTr : F.getEmptySet();
NoQ added a comment.Aug 19 2019, 5:51 PM

Also thanks, everything makes sense now!

Do we already have a test that will cover the necessity for having a map from regions to cast results? Eg.:

void foo(Shape *C, Shape *T) {
  if (isa<Circle>(S) && !isa<Circle>(T))
    clang_analyzer_warnIfReached(); // expected-warning{{TRUE}}
}
clang/test/Analysis/cast-value-state-dump.cpp
30 ↗(On Diff #216023)

We're not assuming it, right? We already know it's gonna fail because we already know that it's a circle.

Charusso updated this revision to Diff 216246.Aug 20 2019, 2:04 PM
Charusso marked 15 inline comments as done.
  • Fix.
NoQ added a comment.Aug 20 2019, 2:16 PM

Something went wrong with message generation, can you take a look?

clang/test/Analysis/cast-value-notes.cpp
24 ↗(On Diff #216246)

A circle is always a shape.

Assuming 'S' is a 'Shape' that is not a 'Circle' sounds about right.

Or just Assuming 'S' is not a 'Circle'.

34 ↗(On Diff #216246)

A circle is always a circle.

55 ↗(On Diff #216246)

The not a 'Circle' part is suspiciously specific.

Charusso updated this revision to Diff 216250.Aug 20 2019, 2:17 PM
  • Added a new test case and refactored that test file.
Charusso updated this revision to Diff 216312.Aug 20 2019, 6:50 PM
Charusso marked 3 inline comments as done.
  • Fix more and publish the previously forgotten comments.
clang/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicCastInfo.h
19 ↗(On Diff #216023)

The successful cast is going to the type map, and the failure will not. Why would we need to store the failing casts in the type map? Therefore no differentiation is necessary I believe so that nor TODO.

clang/test/Analysis/cast-value-state-dump.cpp
30 ↗(On Diff #216023)

We have no knowledge what is what. At the top we see that: Shape -> Circle, and then Triangle -> Circle is something new, so we have to assume that. It is an implementation detail we are allowing only one cast to be succeed. From the user point of view it is an assumption as the current state of the checker could not provide more/better information. It is the same logic from the ConditionBRVisitor.

Charusso marked an inline comment as done.Aug 20 2019, 6:51 PM
Charusso added inline comments.
clang/test/Analysis/cast-value-notes.cpp
34 ↗(On Diff #216246)

I have removed that contradiction test case as being silly, but yes, that was the no-warning test properly.

Charusso updated this revision to Diff 216314.Aug 20 2019, 7:02 PM
  • Remove CastFromTy finally from the getNoteTag() API as it was uninformative.
Charusso updated this revision to Diff 216317.Aug 20 2019, 7:12 PM
  • Make the check-clang pass and simplify a test case.
NoQ added a comment.Aug 21 2019, 11:08 AM

Thanks!! Here's the last couple of nits that i have.

clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
83–93 ↗(On Diff #216023)

I think this one is still forgotten. Maybe a FIXME?

96–100 ↗(On Diff #216317)

I'm worried that this may occasionally get too long and/or contain line breaks. Let's do the usual pattern matching instead: say 'X' for a DeclRefExpr to 'X', say 'field Y' for a MemberExpr made with field 'Y', say "the object" in other cases.

NoQ added inline comments.Aug 21 2019, 11:09 AM
clang/test/Analysis/cast-value-state-dump.cpp
30 ↗(On Diff #216023)

Yeah, but it's not the observable behavior we'll be trying to preserve, so i suggest a FIXME.

Charusso updated this revision to Diff 216509.Aug 21 2019, 3:45 PM
Charusso marked 4 inline comments as done and an inline comment as not done.
  • Fix
NoQ added inline comments.Aug 21 2019, 3:48 PM
clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
126 ↗(On Diff #216509)

"The" should be capitalized if there's no "Assuming" before it.

Charusso updated this revision to Diff 216513.Aug 21 2019, 3:58 PM
  • Fix printing.
Charusso marked an inline comment as done.Aug 21 2019, 3:58 PM
Charusso added inline comments.
clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
83–93 ↗(On Diff #216023)

Now I pattern-match that rule in the evalCall(), therefore we cannot try to evaluate nested references. Would you like to see more checks?

NoQ added a comment.Aug 21 2019, 4:29 PM

Let's land this then!~~

clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
83–93 ↗(On Diff #216023)

Oh, i see, you removed the recursion. Great.

NoQ accepted this revision.Aug 21 2019, 4:29 PM
This revision is now accepted and ready to land.Aug 21 2019, 4:29 PM
Charusso marked 6 inline comments as done.Aug 21 2019, 5:15 PM

Thanks for the review! The build-bots will fire with that QualType fix (1028 TU on its own). I will look into the exploded-graph-rewriter.py after GSoC to fix every stuff like that patch and also invoke my HTML simplification idea.

clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp
83–93 ↗(On Diff #216023)

I was dumb enough to do not publish my comment six times, sorry.

This revision was automatically updated to reflect the committed changes.
Charusso marked an inline comment as done.
Herald added a project: Restricted Project. · View Herald TranscriptAug 21 2019, 5:20 PM

It looks like this renamed DynamicTypeMap.h but didn't update all users, see all the files in Checkers at http://llvm-cs.pcc.me.uk/?q=include.*dynamictypemap.h for example.

Which targets did you try to build locally?

Charusso added a comment.EditedAug 21 2019, 5:36 PM

It looks like this renamed DynamicTypeMap.h but didn't update all users, see all the files in Checkers at http://llvm-cs.pcc.me.uk/?q=include.*dynamictypemap.h for example.

Which targets did you try to build locally?

Well, the errors are in the Static Analyzer, and I have not got any warnings, but now I realized that this header has plenty of injections. Thanks for the fast response! I have fixed it in rL369607.

Thanks! Looks like it builds fine now, but the tests are failing: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/19297/steps/test-check-all/logs/stdio

FAIL: Clang :: Analysis/cast-value-state-dump.cpp (4352 of 48515)
******************** TEST 'Clang :: Analysis/cast-value-state-dump.cpp' FAILED ********************
Script:
--
: 'RUN: at line 1';   c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\bin\clang.exe -cc1 -internal-isystem c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\lib\clang\10.0.0\include -nostdsysteminc -analyze -analyzer-constraints=range   -analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection  -analyzer-output=text -verify C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-state-dump.cpp 2>&1 | c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\bin\filecheck.exe C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-state-dump.cpp
--
Exit Code: 1

Command Output (stdout):
--
$ ":" "RUN: at line 1"
$ "c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\bin\clang.exe" "-cc1" "-internal-isystem" "c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\lib\clang\10.0.0\include" "-nostdsysteminc" "-analyze" "-analyzer-constraints=range" "-analyzer-checker=core,apiModeling.llvm.CastValue,debug.ExprInspection" "-analyzer-output=text" "-verify" "C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-state-dump.cpp"
note: command had no output on stdout or stderr
error: command failed with exit status: 1
$ "c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\bin\filecheck.exe" "C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-state-dump.cpp"

--

********************
PASS: Clang :: Analysis/castexpr-callback.c (4353 of 48515)
PASS: Clang :: Analysis/bool-assignment.c (4354 of 48515)
PASS: Clang :: Analysis/builtin-functions.cpp (4355 of 48515)
PASS: Clang :: Analysis/cfg-indirect-goto-determinism.cpp (4356 of 48515)
PASS: Clang :: Analysis/casts.m (4357 of 48515)
FAIL: Clang :: Analysis/cast-value-notes.cpp (4358 of 48515)
******************** TEST 'Clang :: Analysis/cast-value-notes.cpp' FAILED ********************
Script:
--
: 'RUN: at line 1';   c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\bin\clang.exe -cc1 -internal-isystem c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\lib\clang\10.0.0\include -nostdsysteminc -analyze -analyzer-constraints=range   -analyzer-checker=core,apiModeling.llvm.CastValue   -analyzer-output=text -verify C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp
--
Exit Code: 1

Command Output (stdout):
--
$ ":" "RUN: at line 1"
$ "c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\bin\clang.exe" "-cc1" "-internal-isystem" "c:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\build\lib\clang\10.0.0\include" "-nostdsysteminc" "-analyze" "-analyzer-constraints=range" "-analyzer-checker=core,apiModeling.llvm.CastValue" "-analyzer-output=text" "-verify" "C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp"
# command stderr:
error: 'note' diagnostics expected but not seen: 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 23 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:24): Assuming 'S' is not a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 30 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:31): Assuming 'S' is a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 34 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:35): 'C' is a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 40 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:41): Assuming 'C' is not a 'Triangle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 46 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:47): 'C' is not a 'Triangle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 59 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:60): 'S' is a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 63 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:64): 'C' is a 'Triangle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 76 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:77): Assuming 'S' is not a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 79 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:80): Assuming 'S' is a 'Triangle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 103 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:104): 'S' is a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 114 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:115): 'S' is a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 125 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:126): Assuming 'S' is not a 'Circle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 129 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:130): Assuming 'S' is a 'Triangle'

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 135 (directive at C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp:136): 'S' is a 'Triangle'

error: 'note' diagnostics seen but not expected: 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 23: h2/ 6aM6

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 30: h2/ 6a

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 34: h2/ 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 40: h2/06aM6

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 46: h2/ 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 59: h2/ 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 63: h2/ 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 76: h2/ 6aM6

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 79: h2/ 6aM6

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 103: h2/ 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 114: h2/ 

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 125: h2/ 6aM6

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 129: h2/ 6aM6

  File C:\ps4-buildslave2\llvm-clang-x86_64-expensive-checks-win\llvm\tools\clang\test\Analysis\cast-value-notes.cpp Line 135: h2/ 

28 errors generated.


error: command failed with exit status: 1

--

...

Failing Tests (2):
    Clang :: Analysis/cast-value-notes.cpp
    Clang :: Analysis/cast-value-state-dump.cpp

Thanks! Looks like it builds fine now, but the tests are failing: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/19297/steps/test-check-all/logs/stdio
Failing Tests (2):

Clang :: Analysis/cast-value-notes.cpp
Clang :: Analysis/cast-value-state-dump.cpp

I have noticed something is broken other than the first fix, just I am not that professional C++ developer to immediately catch the error. I am totally on it, thanks!

   return C.getNoteTag(
-      [=] {
+      [=]() -> std::string {
         SmallString<128> Msg;

That was the fix by rL369609. Somehow it converted to a temporary object therefore that was an issue:

[175/176] Running the Clang regression tests
llvm-lit: /b/sanitizer-x86_64-linux-fast/build/llvm/utils/lit/lit/llvm/config.py:340: note: using clang: /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/clang
-- Testing: 15399 tests, 64 threads --
Testing: 0 
FAIL: Clang :: Analysis/cast-value-notes.cpp (355 of 15399)
******************** TEST 'Clang :: Analysis/cast-value-notes.cpp' FAILED ********************
Script:
--
: 'RUN: at line 1';   /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/clang -cc1 -internal-isystem /b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/lib/clang/10.0.0/include -nostdsysteminc -analyze -analyzer-constraints=range   -analyzer-checker=core,apiModeling.llvm.CastValue   -analyzer-output=text -verify /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/Analysis/cast-value-notes.cpp
--
Exit Code: 1

Command Output (stderr):
--
=================================================================
==43337==ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fa639ecfa30 at pc 0x000000c7ac85 bp 0x7fff83887490 sp 0x7fff83886c40
READ of size 19 at 0x7fa639ecfa30 thread T0
    #0 0xc7ac84 in __asan_memcpy /b/sanitizer-x86_64-linux-fast/build/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cc:22
    #1 0xa328415 in copy /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/__string:225:50
    #2 0xa328415 in __init /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/string:1792
    #3 0xa328415 in basic_string /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/string:1813
    #4 0xa328415 in str /b/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/StringRef.h:220
    #5 0xa328415 in operator basic_string /b/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/StringRef.h:247
    #6 0xa328415 in __call<(lambda at /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CastValueChecker.cpp:113:7) &> /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/__functional_base:317
    #7 0xa328415 in operator() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1540
    #8 0xa328415 in std::__1::__function::__func<getNoteTag(clang::ento::CheckerContext&, clang::ento::DynamicCastInfo const*, clang::QualType, clang::Expr const*, bool, bool)::$_0, std::__1::allocator<getNoteTag(clang::ento::CheckerContext&, clang::ento::DynamicCastInfo const*, clang::QualType, clang::Expr const*, bool, bool)::$_0>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > ()>::operator()() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1714
    #9 0xa32751d in operator() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1867:16
    #10 0xa32751d in operator() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:2473
    #11 0xa32751d in operator() /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h:259
    #12 0xa32751d in __invoke<(lambda at /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h:259:23) &, clang::ento::BugReporterContext &, clang::ento::BugReport &> /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/type_traits:3501
    #13 0xa32751d in __call<(lambda at /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h:259:23) &, clang::ento::BugReporterContext &, clang::ento::BugReport &> /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/__functional_base:317
    #14 0xa32751d in operator() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1540
    #15 0xa32751d in std::__1::__function::__func<clang::ento::CheckerContext::getNoteTag(std::__1::function<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > ()>&&, bool)::'lambda'(clang::ento::BugReporterContext&, clang::ento::BugReport&), std::__1::allocator<clang::ento::CheckerContext::getNoteTag(std::__1::function<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > ()>&&, bool)::'lambda'(clang::ento::BugReporterContext&, clang::ento::BugReport&)>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > (clang::ento::BugReporterContext&, clang::ento::BugReport&)>::operator()(clang::ento::BugReporterContext&, clang::ento::BugReport&) /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1714
    #16 0xa990926 in operator() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1867:16
    #17 0xa990926 in operator() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:2473
    #18 0xa990926 in generateMessage /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h:572
    #19 0xa990926 in clang::ento::TagVisitor::VisitNode(clang::ento::ExplodedNode const*, clang::ento::BugReporterContext&, clang::ento::BugReport&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp:2879
    #20 0xa94b59f in generateVisitorsDiagnostics(clang::ento::BugReport*, clang::ento::ExplodedNode const*, clang::ento::BugReporterContext&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:2634:19
    #21 0xa9417b3 in findValidReport /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:2674:9
    #22 0xa9417b3 in clang::ento::PathSensitiveBugReporter::generatePathDiagnostics(llvm::ArrayRef<clang::ento::PathDiagnosticConsumer*>, llvm::ArrayRef<clang::ento::BugReport*>&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:2708
    #23 0xa948006 in clang::ento::BugReporter::generateDiagnosticForConsumerMap(clang::ento::BugReport*, llvm::ArrayRef<clang::ento::PathDiagnosticConsumer*>, llvm::ArrayRef<clang::ento::BugReport*>) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:3032:5
    #24 0xa93c090 in clang::ento::BugReporter::FlushReport(clang::ento::BugReportEquivClass&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:2893:7
    #25 0xa93a72e in clang::ento::BugReporter::FlushReports() /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Core/BugReporter.cpp:2308:5
    #26 0xa23ec21 in RunPathSensitiveChecks /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:816:24
    #27 0xa23ec21 in (anonymous namespace)::AnalysisConsumer::HandleCode(clang::Decl*, unsigned int, clang::ento::ExprEngine::InliningModes, llvm::DenseSet<clang::Decl const*, llvm::DenseMapInfo<clang::Decl const*> >*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:774
    #28 0xa1f6203 in HandleDeclsCallGraph /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:556:5
    #29 0xa1f6203 in runAnalysisOnTranslationUnit /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:607
    #30 0xa1f6203 in (anonymous namespace)::AnalysisConsumer::HandleTranslationUnit(clang::ASTContext&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp:637
    #31 0xad37ae0 in clang::ParseAST(clang::Sema&, bool, bool) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseAST.cpp:171:13
    #32 0x7ad09b9 in clang::FrontendAction::Execute() /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:935:8
    #33 0x79ae417 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:946:33
    #34 0x7d27c53 in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:291:25
    #35 0xcc5084 in cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/cc1_main.cpp:250:15
    #36 0xcbcadc in ExecuteCC1Tool /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:309:12
    #37 0xcbcadc in main /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:381
    #38 0x7fa63d18f2e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    #39 0xbed7c9 in _start (/b/sanitizer-x86_64-linux-fast/build/llvm_build_asan/bin/clang-10+0xbed7c9)

Address 0x7fa639ecfa30 is located in stack of thread T0 at offset 48 in frame
    #0 0xa32780f in std::__1::__function::__func<getNoteTag(clang::ento::CheckerContext&, clang::ento::DynamicCastInfo const*, clang::QualType, clang::Expr const*, bool, bool)::$_0, std::__1::allocator<getNoteTag(clang::ento::CheckerContext&, clang::ento::DynamicCastInfo const*, clang::QualType, clang::Expr const*, bool, bool)::$_0>, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > ()>::operator()() /b/sanitizer-x86_64-linux-fast/build/libcxx_build_asan/include/c++/v1/functional:1713

  This frame has 4 object(s):
    [32, 176) 'Msg.i.i.i.i' <== Memory access at offset 48 is inside this variable
    [240, 288) 'Out.i.i.i.i'
    [320, 344) 'ref.tmp.i.i.i.i'
    [384, 408) 'ref.tmp14.i.i.i.i'
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-use-after-scope /b/sanitizer-x86_64-linux-fast/build/llvm/projects/compiler-rt/lib/asan/asan_interceptors_memintrinsics.cc:22 in __asan_memcpy
Shadow bytes around the buggy address:
  0x0ff5473d1ef0: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0ff5473d1f00: f1 f1 f1 f1 00 00 00 f2 f2 f2 f2 f2 00 00 00 00
  0x0ff5473d1f10: f2 f2 f2 f2 00 00 00 00 f2 f2 f2 f2 f8 f8 f8 f8
  0x0ff5473d1f20: f8 f8 f8 f8 f3 f3 f3 f3 00 00 00 00 00 00 00 00
  0x0ff5473d1f30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ff5473d1f40: f1 f1 f1 f1 f8 f8[f8]f8 f8 f8 f8 f8 f8 f8 f8 f8
  0x0ff5473d1f50: f8 f8 f8 f8 f8 f8 f2 f2 f2 f2 f2 f2 f2 f2 f8 f8
  0x0ff5473d1f60: f8 f8 f8 f8 f2 f2 f2 f2 f8 f8 f8 f2 f2 f2 f2 f2
  0x0ff5473d1f70: f8 f8 f8 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00
  0x0ff5473d1f80: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
  0x0ff5473d1f90: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==43337==ABORTING

--

Thanks for your notes! Also @xazax.hun may you are interested in this lifetime issue.