[PATCH] D38702: [Analyzer] Do not segfault on unexpected call_once implementation
George Karpenkov via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 9 16:21:04 PDT 2017
This revision was automatically updated to reflect the committed changes.
Closed by commit rL315250: [Analyzer] Do not segfault on unexpected call_once implementation (authored by george.karpenkov).
Changed prior to commit:
https://reviews.llvm.org/D38702?vs=118291&id=118294#toc
Repository:
rL LLVM
https://reviews.llvm.org/D38702
Files:
cfe/trunk/lib/Analysis/BodyFarm.cpp
cfe/trunk/test/Analysis/call_once.cpp
Index: cfe/trunk/lib/Analysis/BodyFarm.cpp
===================================================================
--- cfe/trunk/lib/Analysis/BodyFarm.cpp
+++ cfe/trunk/lib/Analysis/BodyFarm.cpp
@@ -327,6 +327,28 @@
const ParmVarDecl *Flag = D->getParamDecl(0);
const ParmVarDecl *Callback = D->getParamDecl(1);
QualType CallbackType = Callback->getType().getNonReferenceType();
+ QualType FlagType = Flag->getType().getNonReferenceType();
+ CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl();
+ if (!FlagCXXDecl) {
+ DEBUG(llvm::dbgs() << "Flag field is not a CXX record: "
+ << "unknown std::call_once implementation."
+ << "Ignoring the call.\n");
+ return nullptr;
+ }
+
+ // Note: here we are assuming libc++ implementation of call_once,
+ // which has a struct with a field `__state_`.
+ // Body farming might not work for other `call_once` implementations.
+ NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");
+ ValueDecl *FieldDecl;
+ if (FoundDecl) {
+ FieldDecl = dyn_cast<ValueDecl>(FoundDecl);
+ } else {
+ DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
+ << "unable to synthesize call_once body, ignoring "
+ << "the call.\n");
+ return nullptr;
+ }
bool isLambdaCall = CallbackType->getAsCXXRecordDecl() &&
CallbackType->getAsCXXRecordDecl()->isLambda();
@@ -355,27 +377,11 @@
CallbackCall = create_call_once_funcptr_call(C, M, Callback, CallArgs);
}
- QualType FlagType = Flag->getType().getNonReferenceType();
DeclRefExpr *FlagDecl =
M.makeDeclRefExpr(Flag,
/* RefersToEnclosingVariableOrCapture=*/true,
/* GetNonReferenceType=*/true);
- CXXRecordDecl *FlagCXXDecl = FlagType->getAsCXXRecordDecl();
-
- // Note: here we are assuming libc++ implementation of call_once,
- // which has a struct with a field `__state_`.
- // Body farming might not work for other `call_once` implementations.
- NamedDecl *FoundDecl = M.findMemberField(FlagCXXDecl, "__state_");
- ValueDecl *FieldDecl;
- if (FoundDecl) {
- FieldDecl = dyn_cast<ValueDecl>(FoundDecl);
- } else {
- DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, "
- << "unable to synthesize call_once body, ignoring "
- << "the call.\n");
- return nullptr;
- }
MemberExpr *Deref = M.makeMemberExpression(FlagDecl, FieldDecl);
assert(Deref->isLValue());
Index: cfe/trunk/test/Analysis/call_once.cpp
===================================================================
--- cfe/trunk/test/Analysis/call_once.cpp
+++ cfe/trunk/test/Analysis/call_once.cpp
@@ -231,3 +231,12 @@
int x = call_once();
clang_analyzer_eval(x == 5); // expected-warning{{TRUE}}
}
+
+namespace std {
+template <typename d, typename e>
+void call_once(d, e);
+}
+void g();
+void test_no_segfault_on_different_impl() {
+ std::call_once(g, false); // no-warning
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D38702.118294.patch
Type: text/x-patch
Size: 3072 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171009/20ae2cf7/attachment.bin>
More information about the cfe-commits
mailing list