summaryrefslogtreecommitdiff
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/BodyFarm.cpp105
-rw-r--r--clang/lib/Analysis/CFG.cpp51
-rw-r--r--clang/lib/Analysis/CloneDetection.cpp2
-rw-r--r--clang/lib/Analysis/Consumed.cpp2
-rw-r--r--clang/lib/Analysis/ReachableCode.cpp1
-rw-r--r--clang/lib/Analysis/ThreadSafety.cpp3
-rw-r--r--clang/lib/Analysis/ThreadSafetyCommon.cpp3
7 files changed, 115 insertions, 52 deletions
diff --git a/clang/lib/Analysis/BodyFarm.cpp b/clang/lib/Analysis/BodyFarm.cpp
index 43f9e715b3de..1a7891550542 100644
--- a/clang/lib/Analysis/BodyFarm.cpp
+++ b/clang/lib/Analysis/BodyFarm.cpp
@@ -737,50 +737,69 @@ static const ObjCIvarDecl *findBackingIvar(const ObjCPropertyDecl *Prop) {
}
static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
- const ObjCPropertyDecl *Prop) {
- // First, find the backing ivar.
- const ObjCIvarDecl *IVar = findBackingIvar(Prop);
- if (!IVar)
- return nullptr;
+ const ObjCMethodDecl *MD) {
+ // First, find the backing ivar.
+ const ObjCIvarDecl *IVar = nullptr;
+
+ // Property accessor stubs sometimes do not correspond to any property decl
+ // in the current interface (but in a superclass). They still have a
+ // corresponding property impl decl in this case.
+ if (MD->isSynthesizedAccessorStub()) {
+ const ObjCInterfaceDecl *IntD = MD->getClassInterface();
+ const ObjCImplementationDecl *ImpD = IntD->getImplementation();
+ for (const auto *PI: ImpD->property_impls()) {
+ if (const ObjCPropertyDecl *P = PI->getPropertyDecl()) {
+ if (P->getGetterName() == MD->getSelector())
+ IVar = P->getPropertyIvarDecl();
+ }
+ }
+ }
- // Ignore weak variables, which have special behavior.
- if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
- return nullptr;
+ if (!IVar) {
+ const ObjCPropertyDecl *Prop = MD->findPropertyDecl();
+ IVar = findBackingIvar(Prop);
+ if (!IVar)
+ return nullptr;
+
+ // Ignore weak variables, which have special behavior.
+ if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak)
+ return nullptr;
- // Look to see if Sema has synthesized a body for us. This happens in
- // Objective-C++ because the return value may be a C++ class type with a
- // non-trivial copy constructor. We can only do this if we can find the
- // @synthesize for this property, though (or if we know it's been auto-
- // synthesized).
- const ObjCImplementationDecl *ImplDecl =
- IVar->getContainingInterface()->getImplementation();
- if (ImplDecl) {
- for (const auto *I : ImplDecl->property_impls()) {
- if (I->getPropertyDecl() != Prop)
- continue;
-
- if (I->getGetterCXXConstructor()) {
- ASTMaker M(Ctx);
- return M.makeReturn(I->getGetterCXXConstructor());
+ // Look to see if Sema has synthesized a body for us. This happens in
+ // Objective-C++ because the return value may be a C++ class type with a
+ // non-trivial copy constructor. We can only do this if we can find the
+ // @synthesize for this property, though (or if we know it's been auto-
+ // synthesized).
+ const ObjCImplementationDecl *ImplDecl =
+ IVar->getContainingInterface()->getImplementation();
+ if (ImplDecl) {
+ for (const auto *I : ImplDecl->property_impls()) {
+ if (I->getPropertyDecl() != Prop)
+ continue;
+
+ if (I->getGetterCXXConstructor()) {
+ ASTMaker M(Ctx);
+ return M.makeReturn(I->getGetterCXXConstructor());
+ }
}
}
- }
- // Sanity check that the property is the same type as the ivar, or a
- // reference to it, and that it is either an object pointer or trivially
- // copyable.
- if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
- Prop->getType().getNonReferenceType()))
- return nullptr;
- if (!IVar->getType()->isObjCLifetimeType() &&
- !IVar->getType().isTriviallyCopyableType(Ctx))
- return nullptr;
+ // Sanity check that the property is the same type as the ivar, or a
+ // reference to it, and that it is either an object pointer or trivially
+ // copyable.
+ if (!Ctx.hasSameUnqualifiedType(IVar->getType(),
+ Prop->getType().getNonReferenceType()))
+ return nullptr;
+ if (!IVar->getType()->isObjCLifetimeType() &&
+ !IVar->getType().isTriviallyCopyableType(Ctx))
+ return nullptr;
+ }
// Generate our body:
// return self->_ivar;
ASTMaker M(Ctx);
- const VarDecl *selfVar = Prop->getGetterMethodDecl()->getSelfDecl();
+ const VarDecl *selfVar = MD->getSelfDecl();
if (!selfVar)
return nullptr;
@@ -791,7 +810,7 @@ static Stmt *createObjCPropertyGetter(ASTContext &Ctx,
selfVar->getType()),
IVar);
- if (!Prop->getType()->isReferenceType())
+ if (!MD->getReturnType()->isReferenceType())
loadedIVar = M.makeLvalueToRvalue(loadedIVar, IVar->getType());
return M.makeReturn(loadedIVar);
@@ -814,10 +833,6 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
return Val.getValue();
Val = nullptr;
- const ObjCPropertyDecl *Prop = D->findPropertyDecl();
- if (!Prop)
- return nullptr;
-
// For now, we only synthesize getters.
// Synthesizing setters would cause false negatives in the
// RetainCountChecker because the method body would bind the parameter
@@ -830,7 +845,17 @@ Stmt *BodyFarm::getBody(const ObjCMethodDecl *D) {
if (D->param_size() != 0)
return nullptr;
- Val = createObjCPropertyGetter(C, Prop);
+ // If the property was defined in an extension, search the extensions for
+ // overrides.
+ const ObjCInterfaceDecl *OID = D->getClassInterface();
+ if (dyn_cast<ObjCInterfaceDecl>(D->getParent()) != OID)
+ for (auto *Ext : OID->known_extensions()) {
+ auto *OMD = Ext->getInstanceMethod(D->getSelector());
+ if (OMD && !OMD->isImplicit())
+ return nullptr;
+ }
+
+ Val = createObjCPropertyGetter(C, D);
return Val.getValue();
}
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index a533a8d97b84..4c1ea8995f9f 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -542,6 +542,7 @@ public:
private:
// Visitors to walk an AST and construct the CFG.
+ CFGBlock *VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc);
CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
CFGBlock *VisitBreakStmt(BreakStmt *B);
@@ -1428,7 +1429,7 @@ void CFGBuilder::findConstructionContexts(
if (Layer->getItem().getKind() ==
ConstructionContextItem::ElidableConstructorKind) {
auto *MTE = cast<MaterializeTemporaryExpr>(Child);
- findConstructionContexts(withExtraLayer(MTE), MTE->GetTemporaryExpr());
+ findConstructionContexts(withExtraLayer(MTE), MTE->getSubExpr());
}
break;
}
@@ -1694,7 +1695,7 @@ static QualType getReferenceInitTemporaryType(const Expr *Init,
// Skip through the temporary-materialization expression.
if (const MaterializeTemporaryExpr *MTE
= dyn_cast<MaterializeTemporaryExpr>(Init)) {
- Init = MTE->GetTemporaryExpr();
+ Init = MTE->getSubExpr();
if (FoundMTE)
*FoundMTE = true;
continue;
@@ -2135,6 +2136,14 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
default:
return VisitStmt(S, asc);
+ case Stmt::ImplicitValueInitExprClass:
+ if (BuildOpts.OmitImplicitValueInitializers)
+ return Block;
+ return VisitStmt(S, asc);
+
+ case Stmt::InitListExprClass:
+ return VisitInitListExpr(cast<InitListExpr>(S), asc);
+
case Stmt::AddrLabelExprClass:
return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
@@ -2341,15 +2350,37 @@ CFGBlock *CFGBuilder::VisitChildren(Stmt *S) {
// Visit the children in their reverse order so that they appear in
// left-to-right (natural) order in the CFG.
reverse_children RChildren(S);
- for (reverse_children::iterator I = RChildren.begin(), E = RChildren.end();
- I != E; ++I) {
- if (Stmt *Child = *I)
+ for (Stmt *Child : RChildren) {
+ if (Child)
if (CFGBlock *R = Visit(Child))
B = R;
}
return B;
}
+CFGBlock *CFGBuilder::VisitInitListExpr(InitListExpr *ILE, AddStmtChoice asc) {
+ if (asc.alwaysAdd(*this, ILE)) {
+ autoCreateBlock();
+ appendStmt(Block, ILE);
+ }
+ CFGBlock *B = Block;
+
+ reverse_children RChildren(ILE);
+ for (Stmt *Child : RChildren) {
+ if (!Child)
+ continue;
+ if (CFGBlock *R = Visit(Child))
+ B = R;
+ if (BuildOpts.AddCXXDefaultInitExprInAggregates) {
+ if (auto *DIE = dyn_cast<CXXDefaultInitExpr>(Child))
+ if (Stmt *Child = DIE->getExpr())
+ if (CFGBlock *R = Visit(Child))
+ B = R;
+ }
+ }
+ return B;
+}
+
CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
AddStmtChoice asc) {
AddressTakenLabels.insert(A->getLabel());
@@ -3462,7 +3493,7 @@ CFGBuilder::VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *MTE,
AddStmtChoice asc) {
findConstructionContexts(
ConstructionContextLayer::create(cfg->getBumpVectorContext(), MTE),
- MTE->getTemporary());
+ MTE->getSubExpr());
return VisitStmt(MTE, asc);
}
@@ -4649,7 +4680,7 @@ tryAgain:
// Find the expression whose lifetime needs to be extended.
E = const_cast<Expr *>(
cast<MaterializeTemporaryExpr>(E)
- ->GetTemporaryExpr()
+ ->getSubExpr()
->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments));
// Visit the skipped comma operator left-hand sides for other temporaries.
for (const Expr *CommaLHS : CommaLHSs) {
@@ -5879,12 +5910,16 @@ const Expr *CFGBlock::getLastCondition() const {
if (succ_size() < 2)
return nullptr;
+ // FIXME: Is there a better condition expression we can return in this case?
+ if (size() == 0)
+ return nullptr;
+
auto StmtElem = rbegin()->getAs<CFGStmt>();
if (!StmtElem)
return nullptr;
const Stmt *Cond = StmtElem->getStmt();
- if (isa<ObjCForCollectionStmt>(Cond))
+ if (isa<ObjCForCollectionStmt>(Cond) || isa<DeclStmt>(Cond))
return nullptr;
// Only ObjCForCollectionStmt is known not to be a non-Expr terminator, hence
diff --git a/clang/lib/Analysis/CloneDetection.cpp b/clang/lib/Analysis/CloneDetection.cpp
index 30d104165cc5..5fb5840ce293 100644
--- a/clang/lib/Analysis/CloneDetection.cpp
+++ b/clang/lib/Analysis/CloneDetection.cpp
@@ -11,7 +11,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/CloneDetection.h"
-
+#include "clang/AST/Attr.h"
#include "clang/AST/DataCollection.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/Support/MD5.h"
diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp
index cde753e8ec57..9560248b173f 100644
--- a/clang/lib/Analysis/Consumed.cpp
+++ b/clang/lib/Analysis/Consumed.cpp
@@ -847,7 +847,7 @@ void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) {
void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr(
const MaterializeTemporaryExpr *Temp) {
- forwardInfo(Temp->GetTemporaryExpr(), Temp);
+ forwardInfo(Temp->getSubExpr(), Temp);
}
void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) {
diff --git a/clang/lib/Analysis/ReachableCode.cpp b/clang/lib/Analysis/ReachableCode.cpp
index 1dab8e309f59..369879ad65f5 100644
--- a/clang/lib/Analysis/ReachableCode.cpp
+++ b/clang/lib/Analysis/ReachableCode.cpp
@@ -19,6 +19,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
+#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/BitVector.h"
diff --git a/clang/lib/Analysis/ThreadSafety.cpp b/clang/lib/Analysis/ThreadSafety.cpp
index c60954374ce3..48f4106b6bae 100644
--- a/clang/lib/Analysis/ThreadSafety.cpp
+++ b/clang/lib/Analysis/ThreadSafety.cpp
@@ -2142,6 +2142,9 @@ void BuildLockset::VisitDeclStmt(const DeclStmt *S) {
// handle constructors that involve temporaries
if (auto *EWC = dyn_cast<ExprWithCleanups>(E))
E = EWC->getSubExpr();
+ if (auto *ICE = dyn_cast<ImplicitCastExpr>(E))
+ if (ICE->getCastKind() == CK_NoOp)
+ E = ICE->getSubExpr();
if (auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
E = BTE->getSubExpr();
diff --git a/clang/lib/Analysis/ThreadSafetyCommon.cpp b/clang/lib/Analysis/ThreadSafetyCommon.cpp
index 373dfc77fa9b..1b8c55e56d47 100644
--- a/clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -244,8 +244,7 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) {
case Stmt::CXXBindTemporaryExprClass:
return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx);
case Stmt::MaterializeTemporaryExprClass:
- return translate(cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr(),
- Ctx);
+ return translate(cast<MaterializeTemporaryExpr>(S)->getSubExpr(), Ctx);
// Collect all literals
case Stmt::CharacterLiteralClass: