Fix static analyzer crash when casting from an incomplete type Update comment and use hasDefinition() instead of isCompleteDefinition().
http://llvm-reviews.chandlerc.com/D1006 CHANGE SINCE LAST DIFF http://llvm-reviews.chandlerc.com/D1006?vs=2478&id=2499#toc Files: lib/StaticAnalyzer/Core/Store.cpp test/Analysis/derived-to-base.cpp Index: lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- lib/StaticAnalyzer/Core/Store.cpp +++ lib/StaticAnalyzer/Core/Store.cpp @@ -325,7 +325,10 @@ if (MRClass == TargetClass) return loc::MemRegionVal(MR); - if (!TargetType->isVoidType()) { + // We skip over incomplete types. They must be the result of an earlier + // reinterpret_cast, as one can only dynamic_cast between types in the same + // class hierarchy. + if (!TargetType->isVoidType() && MRClass->hasDefinition()) { // Static upcasts are marked as DerivedToBase casts by Sema, so this will // only happen when multiple or virtual inheritance is involved. CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, Index: test/Analysis/derived-to-base.cpp =================================================================== --- test/Analysis/derived-to-base.cpp +++ test/Analysis/derived-to-base.cpp @@ -450,3 +450,28 @@ } }; +namespace Bug16309 { + struct Incomplete; + + struct Base { virtual ~Base(); }; + + struct Derived : public Base { int x; }; + + void* f(Incomplete *i) { + Base *b = reinterpret_cast<Base *>(i); + // This used to crash because of the reinterpret_cast above. + Derived *d = dynamic_cast<Derived *>(b); + return d; + } + + // And check that reinterpret+dynamic casts work correctly after the fix. + void g() { + Derived d; + d.x = 47; + Base *b = &d; + Incomplete *i = reinterpret_cast<Incomplete *>(b); + Base *b2 = reinterpret_cast<Base *>(i); + Derived *d2 = dynamic_cast<Derived *>(b2); + clang_analyzer_eval(d2->x == 47); // expected-warning{{TRUE}} + } +}
Index: lib/StaticAnalyzer/Core/Store.cpp =================================================================== --- lib/StaticAnalyzer/Core/Store.cpp +++ lib/StaticAnalyzer/Core/Store.cpp @@ -325,7 +325,10 @@ if (MRClass == TargetClass) return loc::MemRegionVal(MR); - if (!TargetType->isVoidType()) { + // We skip over incomplete types. They must be the result of an earlier + // reinterpret_cast, as one can only dynamic_cast between types in the same + // class hierarchy. + if (!TargetType->isVoidType() && MRClass->hasDefinition()) { // Static upcasts are marked as DerivedToBase casts by Sema, so this will // only happen when multiple or virtual inheritance is involved. CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, Index: test/Analysis/derived-to-base.cpp =================================================================== --- test/Analysis/derived-to-base.cpp +++ test/Analysis/derived-to-base.cpp @@ -450,3 +450,28 @@ } }; +namespace Bug16309 { + struct Incomplete; + + struct Base { virtual ~Base(); }; + + struct Derived : public Base { int x; }; + + void* f(Incomplete *i) { + Base *b = reinterpret_cast<Base *>(i); + // This used to crash because of the reinterpret_cast above. + Derived *d = dynamic_cast<Derived *>(b); + return d; + } + + // And check that reinterpret+dynamic casts work correctly after the fix. + void g() { + Derived d; + d.x = 47; + Base *b = &d; + Incomplete *i = reinterpret_cast<Incomplete *>(b); + Base *b2 = reinterpret_cast<Base *>(i); + Derived *d2 = dynamic_cast<Derived *>(b2); + clang_analyzer_eval(d2->x == 47); // expected-warning{{TRUE}} + } +}
_______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits