summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2017-10-09 23:20:46 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2017-10-09 23:20:46 +0000
commit8b53f7ca6daa21ea4510c0d2b35bee7edade6b0e (patch)
tree33f3bf0ca3b30c3cb66f1533c64bf1d806f1e716 /clang/lib/Analysis
parent0965da20552af85f43b1a15c0867e423791b5513 (diff)
downloadbcm5719-llvm-8b53f7ca6daa21ea4510c0d2b35bee7edade6b0e.tar.gz
bcm5719-llvm-8b53f7ca6daa21ea4510c0d2b35bee7edade6b0e.zip
[Analyzer] Do not segfault on unexpected call_once implementation
Fixes https://bugs.llvm.org/show_bug.cgi?id=34869 Differential Revision: https://reviews.llvm.org/D38702 llvm-svn: 315250
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/BodyFarm.cpp38
1 files changed, 22 insertions, 16 deletions
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index a6597690c2a..81ad999e527 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -327,6 +327,28 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
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 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) {
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());
OpenPOWER on IntegriCloud