diff options
author | David L. Jones <dlj@google.com> | 2017-11-15 01:40:05 +0000 |
---|---|---|
committer | David L. Jones <dlj@google.com> | 2017-11-15 01:40:05 +0000 |
commit | fdfce82b87b73e18577d493e84bdabe2585b95d0 (patch) | |
tree | e8d9290e273dba03920bf15a8c7742fcf5ed0b87 /lib/Analysis/BodyFarm.cpp | |
parent | 41af1698c520ea38edf83e7c91f1e519d34f20c1 (diff) | |
parent | a7540887e8b5cb34ee28c12bef863bad85c65b6f (diff) | |
download | clang-google/testing.tar.gz |
Creating branches/google/testing and tags/google/testing/2017-11-14 from r317716google/testing
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/testing@318248 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/BodyFarm.cpp')
-rw-r--r-- | lib/Analysis/BodyFarm.cpp | 61 |
1 files changed, 32 insertions, 29 deletions
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index 58a129c411..e5d3c5ce5b 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -96,8 +96,8 @@ public: /// Create a Return statement. ReturnStmt *makeReturn(const Expr *RetVal); - /// Create an integer literal. - IntegerLiteral *makeIntegerLiteral(uint64_t value); + /// Create an integer literal expression of the given type. + IntegerLiteral *makeIntegerLiteral(uint64_t Value, QualType Ty); /// Create a member expression. MemberExpr *makeMemberExpression(Expr *base, ValueDecl *MemberDecl, @@ -206,11 +206,9 @@ ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) { nullptr); } -IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t value) { - return IntegerLiteral::Create(C, - llvm::APInt( - /*numBits=*/C.getTypeSize(C.IntTy), value), - /*QualType=*/C.IntTy, SourceLocation()); +IntegerLiteral *ASTMaker::makeIntegerLiteral(uint64_t Value, QualType Ty) { + llvm::APInt APValue = llvm::APInt(C.getTypeSize(Ty), Value); + return IntegerLiteral::Create(C, APValue, Ty, SourceLocation()); } MemberExpr *ASTMaker::makeMemberExpression(Expr *base, ValueDecl *MemberDecl, @@ -325,6 +323,16 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { 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 +354,13 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { // 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 +394,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() << "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; } @@ -439,7 +445,8 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { // Create assignment. BinaryOperator *FlagAssignment = M.makeAssignment( - Deref, M.makeIntegralCast(M.makeIntegerLiteral(1), DerefType), DerefType); + Deref, M.makeIntegralCast(M.makeIntegerLiteral(1, C.IntTy), DerefType), + DerefType); IfStmt *Out = new (C) IfStmt(C, SourceLocation(), @@ -478,8 +485,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { // sets it, and calls the block. Basically, an AST dump of: // // void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block) { - // if (!*predicate) { - // *predicate = 1; + // if (*predicate != ~0l) { + // *predicate = ~0l; // block(); // } // } @@ -496,7 +503,9 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { /*SourceLocation=*/SourceLocation()); // (2) Create the assignment to the predicate. - IntegerLiteral *IL = M.makeIntegerLiteral(1); + Expr *DoneValue = + new (C) UnaryOperator(M.makeIntegerLiteral(0, C.LongTy), UO_Not, C.LongTy, + VK_RValue, OK_Ordinary, SourceLocation()); BinaryOperator *B = M.makeAssignment( @@ -504,7 +513,7 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { M.makeLvalueToRvalue( M.makeDeclRefExpr(Predicate), PredicateQPtrTy), PredicateTy), - M.makeIntegralCast(IL, PredicateTy), + M.makeIntegralCast(DoneValue, PredicateTy), PredicateTy); // (3) Create the compound statement. @@ -520,20 +529,14 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) { PredicateQPtrTy), PredicateTy), PredicateTy); - - UnaryOperator *UO = new (C) UnaryOperator( - /* input=*/ LValToRval, - /* opc=*/ UO_LNot, - /* QualType=*/ C.IntTy, - /* ExprValueKind=*/ VK_RValue, - /* ExprObjectKind=*/ OK_Ordinary, SourceLocation()); - + + Expr *GuardCondition = M.makeComparison(LValToRval, DoneValue, BO_NE); // (5) Create the 'if' statement. IfStmt *If = new (C) IfStmt(C, SourceLocation(), /* IsConstexpr=*/ false, /* init=*/ nullptr, /* var=*/ nullptr, - /* cond=*/ UO, + /* cond=*/ GuardCondition, /* then=*/ CS); return If; } |