summaryrefslogtreecommitdiffstats
path: root/clang/lib/Analysis/BodyFarm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis/BodyFarm.cpp')
-rw-r--r--clang/lib/Analysis/BodyFarm.cpp70
1 files changed, 70 insertions, 0 deletions
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 4d5c2ee236f..a6567ade52f 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -74,6 +74,9 @@ public:
/// Create an Objective-C bool literal.
ObjCBoolLiteralExpr *makeObjCBool(bool Val);
+
+ /// Create an Objective-C ivar reference.
+ ObjCIvarRefExpr *makeObjCIvarRef(const Expr *Base, const ObjCIvarDecl *IVar);
/// Create a Return statement.
ReturnStmt *makeReturn(const Expr *RetVal);
@@ -147,6 +150,15 @@ ObjCBoolLiteralExpr *ASTMaker::makeObjCBool(bool Val) {
return new (C) ObjCBoolLiteralExpr(Val, Ty, SourceLocation());
}
+ObjCIvarRefExpr *ASTMaker::makeObjCIvarRef(const Expr *Base,
+ const ObjCIvarDecl *IVar) {
+ return new (C) ObjCIvarRefExpr(const_cast<ObjCIvarDecl*>(IVar),
+ IVar->getType(), SourceLocation(),
+ SourceLocation(), const_cast<Expr*>(Base),
+ /*arrow=*/true, /*free=*/false);
+}
+
+
ReturnStmt *ASTMaker::makeReturn(const Expr *RetVal) {
return new (C) ReturnStmt(SourceLocation(), const_cast<Expr*>(RetVal), 0);
}
@@ -374,3 +386,61 @@ Stmt *BodyFarm::getBody(const FunctionDecl *D) {
return Val.getValue();
}
+static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
+ const ObjCPropertyDecl *Prop) {
+ const ObjCIvarDecl *IVar = Prop->getPropertyIvarDecl();
+ if (!IVar)
+ return 0;
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
+ return 0;
+ if (IVar->getType().getCanonicalType() !=
+ Prop->getType().getNonReferenceType().getCanonicalType())
+ return 0;
+
+ // C++ records require copy constructors, so we can't just synthesize an AST.
+ // FIXME: Use ObjCPropertyImplDecl's already-synthesized AST. Currently it's
+ // not in a form the analyzer can use.
+ if (Prop->getType()->getAsCXXRecordDecl())
+ return 0;
+
+ ASTMaker M(Ctx);
+
+ const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
+
+ Expr *loadedIVar =
+ M.makeObjCIvarRef(
+ M.makeLvalueToRvalue(
+ M.makeDeclRefExpr(selfVar),
+ selfVar->getType()),
+ IVar);
+
+ if (!Prop->getType()->isReferenceType())
+ loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
+
+ return M.makeReturn(loadedIVar);
+}
+
+Stmt *BodyFarm::getBody(const ObjCMethodDecl *D, const ObjCPropertyDecl *Prop) {
+ if (!D->isPropertyAccessor())
+ return 0;
+
+ D = D->getCanonicalDecl();
+
+ Optional<Stmt *> &Val = Bodies[D];
+ if (Val.hasValue())
+ return Val.getValue();
+ Val = 0;
+
+ if (!Prop)
+ Prop = D->findPropertyDecl();
+ if (!Prop)
+ return 0;
+
+ if (D->param_size() != 0)
+ return 0;
+
+ Val = createObjCPropertyGetter(C, Prop);
+
+ return Val.getValue();
+}
+
OpenPOWER on IntegriCloud