[cfe-commits] r164348 - in /cfe/trunk: lib/Analysis/BodyFarm.cpp test/Analysis/unix-fns.c
Ted Kremenek
kremenek at apple.com
Fri Sep 21 10:58:00 PDT 2012
Thanks so much for the Valgrind output!
I think I've fixed the issue in r164392, so I've re-enabled this setting in the analyzer. Let's see if that satisfies the build bots.
On Sep 21, 2012, at 5:08 AM, NAKAMURA Takumi <geek4civic at gmail.com> wrote:
> Ted, I had to disable this in r164368, since r164364.
>
> In my investigation, valgrind blames this.
>
> $ valgrind --leak-check=full bin/clang -cc1 -analyzer-config
> faux-bodies=true -triple x86_64-apple-darwin10 -analyze
> -analyzer-checker=core -analyzer-store=region -fblocks -verify
> clang/test/Analysis/blocks.m
>
> Valgrind log attached, HTH.
>
> ...Takumi
>
>
> 2012/9/21 Ted Kremenek <kremenek at apple.com>:
>> Author: kremenek
>> Date: Thu Sep 20 19:52:24 2012
>> New Revision: 164348
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=164348&view=rev
>> Log:
>> Add faux-body support for dispatch_once().
>>
>> Modified:
>> cfe/trunk/lib/Analysis/BodyFarm.cpp
>> cfe/trunk/test/Analysis/unix-fns.c
>>
>> Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=164348&r1=164347&r2=164348&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original)
>> +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Thu Sep 20 19:52:24 2012
>> @@ -22,6 +22,113 @@
>>
>> typedef Stmt *(*FunctionFarmer)(ASTContext &C, const FunctionDecl *D);
>>
>> +static bool isDispatchBlock(QualType Ty) {
>> + // Is it a block pointer?
>> + const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
>> + if (!BPT)
>> + return false;
>> +
>> + // Check if the block pointer type takes no arguments and
>> + // returns void.
>> + const FunctionProtoType *FT =
>> + BPT->getPointeeType()->getAs<FunctionProtoType>();
>> + if (!FT || !FT->getResultType()->isVoidType() ||
>> + FT->getNumArgs() != 0)
>> + return false;
>> +
>> + return true;
>> +}
>> +
>> +/// Create a fake body for dispatch_once.
>> +static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
>> + // Check if we have at least two parameters.
>> + if (D->param_size() != 2)
>> + return 0;
>> +
>> + // Check if the first parameter is a pointer to integer type.
>> + const ParmVarDecl *Predicate = D->getParamDecl(0);
>> + QualType PredicateQPtrTy = Predicate->getType();
>> + const PointerType *PredicatePtrTy = PredicateQPtrTy->getAs<PointerType>();
>> + if (!PredicatePtrTy)
>> + return 0;
>> + QualType PredicateTy = PredicatePtrTy->getPointeeType();
>> + if (!PredicateTy->isIntegerType())
>> + return 0;
>> +
>> + // Check if the second parameter is the proper block type.
>> + const ParmVarDecl *Block = D->getParamDecl(1);
>> + QualType Ty = Block->getType();
>> + if (!isDispatchBlock(Ty))
>> + return 0;
>> +
>> + // Everything checks out. Create a fakse body that checks the predicate,
>> + // 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;
>> + // block();
>> + // }
>> + // }
>> +
>> + // (1) Create the call.
>> + DeclRefExpr *DR = DeclRefExpr::CreateEmpty(C, false, false, false, false);
>> + DR->setDecl(const_cast<ParmVarDecl*>(Block));
>> + DR->setType(Ty);
>> + DR->setValueKind(VK_LValue);
>> + ImplicitCastExpr *ICE = ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
>> + DR, 0, VK_RValue);
>> + CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
>> + VK_RValue, SourceLocation());
>> +
>> + // (2) Create the assignment to the predicate.
>> + IntegerLiteral *IL =
>> + IntegerLiteral::Create(C, llvm::APInt(C.getTypeSize(C.IntTy), (uint64_t) 1),
>> + C.IntTy, SourceLocation());
>> + ICE = ImplicitCastExpr::Create(C, PredicateTy, CK_IntegralCast, IL, 0,
>> + VK_RValue);
>> + DR = DeclRefExpr::CreateEmpty(C, false, false, false, false);
>> + DR->setDecl(const_cast<ParmVarDecl*>(Predicate));
>> + DR->setType(PredicateQPtrTy);
>> + DR->setValueKind(VK_LValue);
>> + ImplicitCastExpr *LValToRval =
>> + ImplicitCastExpr::Create(C, PredicateQPtrTy, CK_LValueToRValue, DR,
>> + 0, VK_RValue);
>> + UnaryOperator *UO = new (C) UnaryOperator(LValToRval, UO_Deref, PredicateTy,
>> + VK_LValue, OK_Ordinary,
>> + SourceLocation());
>> + BinaryOperator *B = new (C) BinaryOperator(UO, ICE, BO_Assign,
>> + PredicateTy, VK_RValue,
>> + OK_Ordinary,
>> + SourceLocation());
>> + // (3) Create the compound statement.
>> + Stmt *Stmts[2];
>> + Stmts[0] = B;
>> + Stmts[1] = CE;
>> + CompoundStmt *CS = new (C) CompoundStmt(C, Stmts, 2, SourceLocation(),
>> + SourceLocation());
>> +
>> + // (4) Create the 'if' condition.
>> + DR = DeclRefExpr::CreateEmpty(C, false, false, false, false);
>> + DR->setDecl(const_cast<ParmVarDecl*>(Predicate));
>> + DR->setType(PredicateQPtrTy);
>> + DR->setValueKind(VK_LValue);
>> + LValToRval = ImplicitCastExpr::Create(C, PredicateQPtrTy, CK_LValueToRValue,
>> + DR, 0, VK_RValue);
>> + UO = new (C) UnaryOperator(LValToRval, UO_Deref, PredicateTy,
>> + VK_LValue, OK_Ordinary,
>> + SourceLocation());
>> + LValToRval = ImplicitCastExpr::Create(C, PredicateTy, CK_LValueToRValue,
>> + UO, 0, VK_RValue);
>> + UO = new (C) UnaryOperator(LValToRval, UO_LNot, C.IntTy,
>> + VK_RValue, OK_Ordinary, SourceLocation());
>> +
>> + // (5) Create the 'if' statement.
>> + IfStmt *If = new (C) IfStmt(C, SourceLocation(), 0, UO, CS);
>> + return If;
>> +}
>> +
>> +
>>
>> /// Create a fake body for dispatch_sync.
>> static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
>> @@ -32,16 +139,7 @@
>> // Check if the second parameter is a block.
>> const ParmVarDecl *PV = D->getParamDecl(1);
>> QualType Ty = PV->getType();
>> - const BlockPointerType *BPT = Ty->getAs<BlockPointerType>();
>> - if (!BPT)
>> - return 0;
>> -
>> - // Check if the block pointer type takes no arguments and
>> - // returns void.
>> - const FunctionProtoType *FT =
>> - BPT->getPointeeType()->getAs<FunctionProtoType>();
>> - if (!FT || !FT->getResultType()->isVoidType() ||
>> - FT->getNumArgs() != 0)
>> + if (!isDispatchBlock(Ty))
>> return 0;
>>
>> // Everything checks out. Create a fake body that just calls the block.
>> @@ -53,6 +151,7 @@
>> //
>> DeclRefExpr *DR = DeclRefExpr::CreateEmpty(C, false, false, false, false);
>> DR->setDecl(const_cast<ParmVarDecl*>(PV));
>> + DR->setType(Ty);
>> DR->setValueKind(VK_LValue);
>> ImplicitCastExpr *ICE = ImplicitCastExpr::Create(C, Ty, CK_LValueToRValue,
>> DR, 0, VK_RValue);
>> @@ -80,6 +179,7 @@
>> FunctionFarmer FF =
>> llvm::StringSwitch<FunctionFarmer>(Name)
>> .Case("dispatch_sync", create_dispatch_sync)
>> + .Case("dispatch_once", create_dispatch_once)
>> .Default(NULL);
>>
>> if (FF) {
> <20120921.log>
More information about the cfe-commits
mailing list