diff options
Diffstat (limited to 'clang/lib/Analysis')
| -rw-r--r-- | clang/lib/Analysis/BodyFarm.cpp | 105 | ||||
| -rw-r--r-- | clang/lib/Analysis/CFG.cpp | 51 | ||||
| -rw-r--r-- | clang/lib/Analysis/CloneDetection.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Analysis/Consumed.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Analysis/ReachableCode.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Analysis/ThreadSafety.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Analysis/ThreadSafetyCommon.cpp | 3 |
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: |
