[analyzer] do not crash on libcxx03 call_once implementation
Addresses https://bugs.llvm.org/show_bug.cgi?id=35075, rdar://35230961
Differential Revision: https://reviews.llvm.org/D39518
llvm-svn: 317293
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 58a129c..3e62ae5 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -325,6 +325,16 @@
const ParmVarDecl *Flag = D->getParamDecl(0);
const ParmVarDecl *Callback = D->getParamDecl(1);
+
+ if (!Callback->getType()->isReferenceType()) {
+ llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n";
+ return nullptr;
+ }
+ if (!Flag->getType()->isReferenceType()) {
+ llvm::dbgs() << "unknown std::call_once implementation, skipping.\n";
+ return nullptr;
+ }
+
QualType CallbackType = Callback->getType().getNonReferenceType();
// Nullable pointer, non-null iff function is a CXXRecordDecl.
@@ -346,15 +356,13 @@
// Otherwise, try libstdc++ implementation, with a field
// `_M_once`
if (!FlagFieldDecl) {
- DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
- << "assuming libstdc++ implementation\n");
FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once");
}
if (!FlagFieldDecl) {
- DEBUG(llvm::dbgs() << "No field _M_once found on std::once flag struct: "
- << "unknown std::call_once implementation, "
- << "ignoring the call");
+ DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on "
+ << "std::once_flag struct: unknown std::call_once "
+ << "implementation, ignoring the call.");
return nullptr;
}
@@ -388,9 +396,9 @@
// First two arguments are used for the flag and for the callback.
if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) {
- DEBUG(llvm::dbgs() << "Number of params of the callback does not match "
- << "the number of params passed to std::call_once, "
- << "ignoring the call");
+ DEBUG(llvm::dbgs() << "Types of params of the callback do not match "
+ << "params passed to std::call_once, "
+ << "ignoring the call\n");
return nullptr;
}