[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