[cfe-commits] r164348 - in /cfe/trunk: lib/Analysis/BodyFarm.cpp test/Analysis/unix-fns.c
NAKAMURA Takumi
geek4civic at gmail.com
Fri Sep 21 05:08:33 PDT 2012
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) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 20120921.log
Type: application/octet-stream
Size: 29408 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120921/d5e7eec6/attachment.obj>
More information about the cfe-commits
mailing list