This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Fix a crash on destroying a temporary array.
ClosedPublic

Authored by NoQ on Feb 9 2018, 4:05 PM.

Details

Summary

Tried to actually run the analyzer with temporary destructor support on some real code, found two crashes for now - D43144 and this one. In this example, a temporary of type C[2] is constructed in the context of InitListExpr within CXXBindTemporaryExpr:

`-ExprWithCleanups 0x7f82b9020c28 <line:872:3, col:36> 'std::initializer_list<C>':'std::initializer_list<temporary_list_crash::C>'
  `-CXXFunctionalCastExpr 0x7f82b9020c00 <col:3, col:36> 'std::initializer_list<C>':'std::initializer_list<temporary_list_crash::C>' functional cast to std::initializer_list<C> <NoOp>
    `-CXXStdInitializerListExpr 0x7f82ba0258f8 <col:27, col:36> 'std::initializer_list<C>':'std::initializer_list<temporary_list_crash::C>'
      `-MaterializeTemporaryExpr 0x7f82ba0258e0 <col:27, col:36> 'const temporary_list_crash::C [2]' xvalue
        `-CXXBindTemporaryExpr 0x7f82ba0258c0 <col:27, col:36> 'const temporary_list_crash::C [2]' (CXXTemporary 0x7f82ba0258b8)    *** <=== THIS ONE ***
          `-InitListExpr 0x7f82ba025748 <col:27, col:36> 'const temporary_list_crash::C [2]'
            |-CXXConstructExpr 0x7f82ba025818 <col:28, col:30> 'const temporary_list_crash::C' 'void (const temporary_list_crash::C &) noexcept' elidable
            | `-MaterializeTemporaryExpr 0x7f82ba0257b0 <col:28, col:30> 'const temporary_list_crash::C' lvalue
            |   `-ImplicitCastExpr 0x7f82ba025798 <col:28, col:30> 'const temporary_list_crash::C' <NoOp>
            |     `-CXXBindTemporaryExpr 0x7f82ba024ae8 <col:28, col:30> 'temporary_list_crash::C' (CXXTemporary 0x7f82ba024ae0)
            |       `-CXXTemporaryObjectExpr 0x7f82ba024aa8 <col:28, col:30> 'temporary_list_crash::C' 'void ()'
            `-CXXConstructExpr 0x7f82ba025880 <col:33, col:35> 'const temporary_list_crash::C' 'void (const temporary_list_crash::C &) noexcept' elidable
              `-MaterializeTemporaryExpr 0x7f82ba025868 <col:33, col:35> 'const temporary_list_crash::C' lvalue
                `-ImplicitCastExpr 0x7f82ba025850 <col:33, col:35> 'const temporary_list_crash::C' <NoOp>
                  `-CXXBindTemporaryExpr 0x7f82ba024b58 <col:33, col:35> 'temporary_list_crash::C' (CXXTemporary 0x7f82ba024b50)
                    `-CXXTemporaryObjectExpr 0x7f82ba024b18 <col:33, col:35> 'temporary_list_crash::C' 'void ()'

We'd have to actually support this case eventually, but for now do the trick that we've always did: unwrap the array type and pretend we're destroying a single object. Once we have the construction context provided for this constructor, we'd have the region here, and in this case we'd also need to construct ElementRegion as part of this trick. And even then, calling a destructor of a single array element does not invalidate the whole array for us, because destructors are const (unless there are mutable members). So we'd have to do this manually later as well.

Diff Detail

Event Timeline

NoQ created this revision.Feb 9 2018, 4:05 PM
NoQ updated this revision to Diff 133718.Feb 9 2018, 4:44 PM

And even then, calling a destructor of a single array element does not invalidate the whole array for us, because destructors are const (unless there are mutable members). So we'd have to do this manually later as well.

Hmm, no, we don't. Because, well, destructors are const, so they won't change the contents of the array, so there's no need to invalidate in the first place.

This revision was not accepted when it landed; it landed in state Needs Review.Feb 15 2018, 11:37 AM
This revision was automatically updated to reflect the committed changes.