diff options
Diffstat (limited to 'lib/Analysis/BodyFarm.cpp')
| -rw-r--r-- | lib/Analysis/BodyFarm.cpp | 68 |
1 files changed, 42 insertions, 26 deletions
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index 89ca8484819d1..b9fb15b2db25e 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -149,7 +149,8 @@ DeclRefExpr *ASTMaker::makeDeclRefExpr( UnaryOperator *ASTMaker::makeDereference(const Expr *Arg, QualType Ty) { return new (C) UnaryOperator(const_cast<Expr*>(Arg), UO_Deref, Ty, - VK_LValue, OK_Ordinary, SourceLocation()); + VK_LValue, OK_Ordinary, SourceLocation(), + /*CanOverflow*/ false); } ImplicitCastExpr *ASTMaker::makeLvalueToRvalue(const Expr *Arg, QualType Ty) { @@ -253,21 +254,24 @@ static CallExpr *create_call_once_funcptr_call(ASTContext &C, ASTMaker M, QualType Ty = Callback->getType(); DeclRefExpr *Call = M.makeDeclRefExpr(Callback); - CastKind CK; + Expr *SubExpr; if (Ty->isRValueReferenceType()) { - CK = CK_LValueToRValue; - } else { - assert(Ty->isLValueReferenceType()); - CK = CK_FunctionToPointerDecay; + SubExpr = M.makeImplicitCast( + Call, Ty.getNonReferenceType(), CK_LValueToRValue); + } else if (Ty->isLValueReferenceType() && + Call->getType()->isFunctionType()) { Ty = C.getPointerType(Ty.getNonReferenceType()); + SubExpr = M.makeImplicitCast(Call, Ty, CK_FunctionToPointerDecay); + } else if (Ty->isLValueReferenceType() + && Call->getType()->isPointerType() + && Call->getType()->getPointeeType()->isFunctionType()){ + SubExpr = Call; + } else { + llvm_unreachable("Unexpected state"); } return new (C) - CallExpr(C, M.makeImplicitCast(Call, Ty.getNonReferenceType(), CK), - /*args=*/CallArgs, - /*QualType=*/C.VoidTy, - /*ExprValueType=*/VK_RValue, - /*SourceLocation=*/SourceLocation()); + CallExpr(C, SubExpr, CallArgs, C.VoidTy, VK_RValue, SourceLocation()); } static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, @@ -313,7 +317,7 @@ static CallExpr *create_call_once_lambda_call(ASTContext &C, ASTMaker M, /// } /// \endcode static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { - DEBUG(llvm::dbgs() << "Generating body for call_once\n"); + LLVM_DEBUG(llvm::dbgs() << "Generating body for call_once\n"); // We need at least two parameters. if (D->param_size() < 2) @@ -341,9 +345,9 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { auto *FlagRecordDecl = dyn_cast_or_null<RecordDecl>(FlagType->getAsTagDecl()); if (!FlagRecordDecl) { - DEBUG(llvm::dbgs() << "Flag field is not a record: " - << "unknown std::call_once implementation, " - << "ignoring the call.\n"); + LLVM_DEBUG(llvm::dbgs() << "Flag field is not a record: " + << "unknown std::call_once implementation, " + << "ignoring the call.\n"); return nullptr; } @@ -358,16 +362,17 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { } if (!FlagFieldDecl) { - DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on " - << "std::once_flag struct: unknown std::call_once " - << "implementation, ignoring the call."); + LLVM_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; } bool isLambdaCall = CallbackRecordDecl && CallbackRecordDecl->isLambda(); if (CallbackRecordDecl && !isLambdaCall) { - DEBUG(llvm::dbgs() << "Not supported: synthesizing body for functors when " - << "body farming std::call_once, ignoring the call."); + LLVM_DEBUG(llvm::dbgs() + << "Not supported: synthesizing body for functors when " + << "body farming std::call_once, ignoring the call."); return nullptr; } @@ -394,9 +399,9 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { // First two arguments are used for the flag and for the callback. if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) { - DEBUG(llvm::dbgs() << "Types of params of the callback do not match " - << "params passed to std::call_once, " - << "ignoring the call\n"); + LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match " + << "params passed to std::call_once, " + << "ignoring the call\n"); return nullptr; } @@ -405,6 +410,16 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { // reference. for (unsigned int ParamIdx = 2; ParamIdx < D->getNumParams(); ParamIdx++) { const ParmVarDecl *PDecl = D->getParamDecl(ParamIdx); + if (PDecl && + CallbackFunctionType->getParamType(ParamIdx - 2) + .getNonReferenceType() + .getCanonicalType() != + PDecl->getType().getNonReferenceType().getCanonicalType()) { + LLVM_DEBUG(llvm::dbgs() << "Types of params of the callback do not match " + << "params passed to std::call_once, " + << "ignoring the call\n"); + return nullptr; + } Expr *ParamExpr = M.makeDeclRefExpr(PDecl); if (!CallbackFunctionType->getParamType(ParamIdx - 2)->isReferenceType()) { QualType PTy = PDecl->getType().getNonReferenceType(); @@ -441,7 +456,8 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { /* opc=*/ UO_LNot, /* QualType=*/ C.IntTy, /* ExprValueKind=*/ VK_RValue, - /* ExprObjectKind=*/ OK_Ordinary, SourceLocation()); + /* ExprObjectKind=*/ OK_Ordinary, SourceLocation(), + /* CanOverflow*/ false); // Create assignment. BinaryOperator *FlagAssignment = M.makeAssignment( @@ -505,7 +521,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { // (2) Create the assignment to the predicate. Expr *DoneValue = new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy, - VK_RValue, OK_Ordinary, SourceLocation()); + VK_RValue, OK_Ordinary, SourceLocation(), + /*CanOverflow*/false); BinaryOperator *B = M.makeAssignment( @@ -813,4 +830,3 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) { return Val.getValue(); } - |
