[cfe-commits] r165743 - in /cfe/trunk/lib: Analysis/BodyFarm.cpp StaticAnalyzer/Checkers/OSAtomicChecker.cpp

Jordan Rose jordan_rose at apple.com
Thu Oct 11 14:40:36 PDT 2012


Awesome!

We could probably use more test cases here. Also, SeanMcBride pointed out a few weeks back that OSCompareAndSwap* (from <Kernel/OSAtomic.h>) follows the same pattern. (He also included CompareAndSwap from <CoreServices/DriverSynchronization.h>, but that seems to be deprecated in 10.8.)

Double-also, not all of these things return BOOL. We should probably be casting to whichever type is specified…some of which are integral and some of which are boolean.

Jordan


On Oct 11, 2012, at 13:58 , Ted Kremenek <kremenek at apple.com> wrote:

> Author: kremenek
> Date: Thu Oct 11 15:58:18 2012
> New Revision: 165743
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=165743&view=rev
> Log:
> Switch over to BodyFarm implementation of OSAtomicCompareAndSwap and
> objc_atomicCompareAndSwap.
> 
> Modified:
>    cfe/trunk/lib/Analysis/BodyFarm.cpp
>    cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
> 
> Modified: cfe/trunk/lib/Analysis/BodyFarm.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BodyFarm.cpp?rev=165743&r1=165742&r2=165743&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Analysis/BodyFarm.cpp (original)
> +++ cfe/trunk/lib/Analysis/BodyFarm.cpp Thu Oct 11 15:58:18 2012
> @@ -16,6 +16,7 @@
> #include "clang/AST/ASTContext.h"
> #include "clang/AST/Expr.h"
> #include "clang/AST/Decl.h"
> +#include "clang/AST/ExprObjC.h"
> #include "BodyFarm.h"
> 
> using namespace clang;
> @@ -49,6 +50,13 @@
>   /// Create a new BinaryOperator representing a simple assignment.
>   BinaryOperator *makeAssignment(const Expr *LHS, const Expr *RHS, QualType Ty);
> 
> +  /// Create a new BinaryOperator representing a comparison.
> +  BinaryOperator *makeComparison(const Expr *LHS, const Expr *RHS,
> +                                 BinaryOperator::Opcode Op);
> +  
> +  /// Create a new compound stmt using the provided statements.
> +  CompoundStmt *makeCompound(ArrayRef<Stmt*>);
> +  
>   /// Create a new DeclRefExpr for the referenced variable.
>   DeclRefExpr *makeDeclRefExpr(const VarDecl *D);
> 
> @@ -58,9 +66,18 @@
>   /// Create an implicit cast for an integer conversion.
>   ImplicitCastExpr *makeIntegralCast(const Expr *Arg, QualType Ty);
> 
> +  /// Create an implicit cast to a builtin boolean type.
> +  ImplicitCastExpr *makeIntegralCastToBoolean(const Expr *Arg);
> +  
>   // Create an implicit cast for lvalue-to-rvaluate conversions.
>   ImplicitCastExpr *makeLvalueToRvalue(const Expr *Arg, QualType Ty);
> 
> +  /// Create an Objective-C bool literal.
> +  ObjCBoolLiteralExpr *makeObjCBool(bool Val);
> +  
> +  /// Create a Return statement.
> +  ReturnStmt *makeReturn(const Expr *RetVal);
> +  
> private:
>   ASTContext &C;
> };
> @@ -73,6 +90,24 @@
>                                OK_Ordinary, SourceLocation(), false);
> }
> 
> +BinaryOperator *ASTMaker::makeComparison(const Expr *LHS, const Expr *RHS,
> +                                         BinaryOperator::Opcode Op) {
> +  assert(BinaryOperator::isLogicalOp(Op) ||
> +         BinaryOperator::isComparisonOp(Op));
> +  return new (C) BinaryOperator(const_cast<Expr*>(LHS),
> +                                const_cast<Expr*>(RHS),
> +                                Op,
> +                                C.getLogicalOperationType(),
> +                                VK_RValue,
> +                                OK_Ordinary, SourceLocation(), false);
> +}
> +
> +CompoundStmt *ASTMaker::makeCompound(ArrayRef<Stmt *> Stmts) {
> +  return new (C) CompoundStmt(C, const_cast<Stmt**>(Stmts.data()),
> +                              Stmts.size(),
> +                              SourceLocation(), SourceLocation());
> +}
> +
> DeclRefExpr *ASTMaker::makeDeclRefExpr(const VarDecl *D) {
>   DeclRefExpr *DR =
>     DeclRefExpr::Create(/* Ctx = */ C,
> @@ -101,6 +136,20 @@
>                                   const_cast<Expr*>(Arg), 0, VK_RValue);
> }
> 
> +ImplicitCastExpr *ASTMaker::makeIntegralCastToBoolean(const Expr *Arg) {
> +  return ImplicitCastExpr::Create(C, C.BoolTy, CK_IntegralToBoolean,
> +                                  const_cast<Expr*>(Arg), 0, VK_RValue);
> +}
> +
> +ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
> +  QualType Ty = C.getBOOLDecl() ? C.getBOOLType() : C.ObjCBuiltinBoolTy;
> +  return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
> +}
> +
> +ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
> +  return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 0);
> +}
> +
> //===----------------------------------------------------------------------===//
> // Creation functions for faux ASTs.
> //===----------------------------------------------------------------------===//
> @@ -163,9 +212,8 @@
>   // (3) Create the compound statement.
>   Stmt *Stmts[2];
>   Stmts[0] = B;
> -  Stmts[1] = CE;  
> -  CompoundStmt *CS = new (C) CompoundStmt(C, Stmts, 2, SourceLocation(),
> -                                          SourceLocation());
> +  Stmts[1] = CE;
> +  CompoundStmt *CS = M.makeCompound(ArrayRef<Stmt*>(Stmts, 2));
> 
>   // (4) Create the 'if' condition.
>   ImplicitCastExpr *LValToRval =
> @@ -213,6 +261,71 @@
>   return CE;
> }
> 
> +static Stmt *create_OSAtomicCompareAndSwap(ASTContext &C, const FunctionDecl *D)
> +{
> +  // There are exactly 3 arguments.
> +  if (D->param_size() != 3)
> +    return 0;
> +  
> +  // Body for:
> +  //   if (oldValue == *theValue) {
> +  //    *theValue = newValue;
> +  //    return YES;
> +  //   }
> +  //   else return NO;
> +  
> +  const ParmVarDecl *OldValue = D->getParamDecl(0);
> +  QualType OldValueTy = OldValue->getType();
> +
> +  const ParmVarDecl *NewValue = D->getParamDecl(1);
> +  QualType NewValueTy = NewValue->getType();
> +  
> +  assert(OldValueTy == NewValueTy);
> +  
> +  const ParmVarDecl *TheValue = D->getParamDecl(2);
> +  QualType TheValueTy = TheValue->getType();
> +  const PointerType *PT = TheValueTy->getAs<PointerType>();
> +  if (!PT)
> +    return 0;
> +  QualType PointeeTy = PT->getPointeeType();
> +  
> +  ASTMaker M(C);
> +  // Construct the comparison.
> +  Expr *Comparison =
> +    M.makeComparison(
> +      M.makeLvalueToRvalue(M.makeDeclRefExpr(OldValue), OldValueTy),
> +      M.makeLvalueToRvalue(
> +        M.makeDereference(
> +          M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
> +          PointeeTy),
> +        PointeeTy),
> +      BO_EQ);
> +
> +  // Construct the body of the IfStmt.
> +  Stmt *Stmts[2];
> +  Stmts[0] =
> +    M.makeAssignment(
> +      M.makeDereference(
> +        M.makeLvalueToRvalue(M.makeDeclRefExpr(TheValue), TheValueTy),
> +        PointeeTy),
> +      M.makeLvalueToRvalue(M.makeDeclRefExpr(NewValue), NewValueTy),
> +      NewValueTy);
> +  Stmts[1] =
> +    M.makeReturn(M.makeIntegralCastToBoolean(M.makeObjCBool(true)));
> +  CompoundStmt *Body = M.makeCompound(ArrayRef<Stmt*>(Stmts, 2));
> +  
> +  // Construct the else clause.
> +  Stmt *Else =
> +    M.makeReturn(M.makeIntegralCastToBoolean(M.makeObjCBool(false)));
> +  
> +  /// Construct the If.
> +  Stmt *If =
> +    new (C) IfStmt(C, SourceLocation(), 0, Comparison, Body,
> +                   SourceLocation(), Else);
> +  
> +  return If;  
> +}
> +
> Stmt *BodyFarm::getBody(const FunctionDecl *D) {
>   D = D->getCanonicalDecl();
> 
> @@ -228,17 +341,21 @@
>   StringRef Name = D->getName();
>   if (Name.empty())
>     return 0;
> -  
> -  FunctionFarmer FF =
> -    llvm::StringSwitch<FunctionFarmer>(Name)
> -      .Case("dispatch_sync", create_dispatch_sync)
> -      .Case("dispatch_once", create_dispatch_once)
> -      .Default(NULL);
> -  
> -  if (FF) {
> -    Val = FF(C, D);
> +
> +  FunctionFarmer FF;
> +
> +  if (Name.startswith("OSAtomicCompareAndSwap") ||
> +      Name.startswith("objc_atomicCompareAndSwap")) {
> +    FF = create_OSAtomicCompareAndSwap;
> +  }
> +  else {
> +    FF = llvm::StringSwitch<FunctionFarmer>(Name)
> +          .Case("dispatch_sync", create_dispatch_sync)
> +          .Case("dispatch_once", create_dispatch_once)
> +        .Default(NULL);
>   }
> 
> +  if (FF) { Val = FF(C, D); }
>   return Val.getValue();
> }
> 
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp?rev=165743&r1=165742&r2=165743&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp Thu Oct 11 15:58:18 2012
> @@ -212,5 +212,5 @@
> }
> 
> void ento::registerOSAtomicChecker(CheckerManager &mgr) {
> -  mgr.registerChecker<OSAtomicChecker>();
> +  //  mgr.registerChecker<OSAtomicChecker>();
> }
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits





More information about the cfe-commits mailing list