aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:49 +0000
commit2298981669bf3bd63335a4be179bc0f96823a8f4 (patch)
tree1cbe2eb27f030d2d70b80ee5ca3c86bee7326a9f /include/clang/Analysis
parent9a83721404652cea39e9f02ae3e3b5c964602a5c (diff)
Vendor import of stripped clang trunk r366426 (just before thevendor/clang/clang-trunk-r366426
Notes
Notes: svn path=/vendor/clang/dist/; revision=351280 svn path=/vendor/clang/clang-trunk-r366426/; revision=351281; tag=vendor/clang/clang-trunk-r366426
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r--include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h7
-rw-r--r--include/clang/Analysis/Analyses/Consumed.h7
-rw-r--r--include/clang/Analysis/Analyses/Dominators.h315
-rw-r--r--include/clang/Analysis/Analyses/ExprMutationAnalyzer.h7
-rw-r--r--include/clang/Analysis/Analyses/LiveVariables.h7
-rw-r--r--include/clang/Analysis/Analyses/PostOrderCFGView.h7
-rw-r--r--include/clang/Analysis/Analyses/ReachableCode.h7
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafety.h19
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyCommon.h7
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyLogical.h7
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyOps.def7
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTIL.h9
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyTraverse.h7
-rw-r--r--include/clang/Analysis/Analyses/ThreadSafetyUtil.h7
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h7
-rw-r--r--include/clang/Analysis/AnalysisDeclContext.h20
-rw-r--r--include/clang/Analysis/AnalysisDiagnostic.h7
-rw-r--r--include/clang/Analysis/AnyCall.h209
-rw-r--r--include/clang/Analysis/BodyFarm.h7
-rw-r--r--include/clang/Analysis/CFG.h113
-rw-r--r--include/clang/Analysis/CFGStmtMap.h7
-rw-r--r--include/clang/Analysis/CallGraph.h7
-rw-r--r--include/clang/Analysis/CloneDetection.h7
-rw-r--r--include/clang/Analysis/CodeInjector.h7
-rw-r--r--include/clang/Analysis/ConstructionContext.h7
-rw-r--r--include/clang/Analysis/DomainSpecific/CocoaConventions.h7
-rw-r--r--include/clang/Analysis/DomainSpecific/ObjCNoReturn.h7
-rw-r--r--include/clang/Analysis/FlowSensitive/DataflowValues.h7
-rw-r--r--include/clang/Analysis/ProgramPoint.h19
-rw-r--r--include/clang/Analysis/RetainSummaryManager.h767
-rw-r--r--include/clang/Analysis/SelectorExtras.h7
-rw-r--r--include/clang/Analysis/Support/BumpVector.h7
32 files changed, 1416 insertions, 223 deletions
diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index 49da6815ace9..16c0a7af0504 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -1,9 +1,8 @@
//===- CFGReachabilityAnalysis.h - Basic reachability analysis --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 5a70989e5087..dec1ae3b2b4b 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -1,9 +1,8 @@
//===- Consumed.h -----------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index 021e98dcd885..061c98137da2 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -1,9 +1,8 @@
//- Dominators.h - Implementation of dominators tree for Clang CFG -*- C++ -*-//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -19,6 +18,7 @@
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/Support/GenericIteratedDominanceFrontier.h"
#include "llvm/Support/GenericDomTree.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/raw_ostream.h"
@@ -37,132 +37,319 @@ namespace clang {
using DomTreeNode = llvm::DomTreeNodeBase<CFGBlock>;
-/// Concrete subclass of DominatorTreeBase for Clang
-/// This class implements the dominators tree functionality given a Clang CFG.
-///
-class DominatorTree : public ManagedAnalysis {
+/// Dominator tree builder for Clang's CFG based on llvm::DominatorTreeBase.
+template <bool IsPostDom>
+class CFGDominatorTreeImpl : public ManagedAnalysis {
virtual void anchor();
public:
- llvm::DomTreeBase<CFGBlock> *DT;
+ using DominatorTreeBase = llvm::DominatorTreeBase<CFGBlock, IsPostDom>;
- DominatorTree() {
- DT = new llvm::DomTreeBase<CFGBlock>();
+ CFGDominatorTreeImpl() = default;
+
+ CFGDominatorTreeImpl(CFG *cfg) {
+ buildDominatorTree(cfg);
}
- ~DominatorTree() override { delete DT; }
+ ~CFGDominatorTreeImpl() override = default;
+
+ DominatorTreeBase &getBase() { return DT; }
- llvm::DomTreeBase<CFGBlock>& getBase() { return *DT; }
+ CFG *getCFG() { return cfg; }
- /// This method returns the root CFGBlock of the dominators tree.
+ /// \returns the root CFGBlock of the dominators tree.
CFGBlock *getRoot() const {
- return DT->getRoot();
+ return DT.getRoot();
}
- /// This method returns the root DomTreeNode, which is the wrapper
- /// for CFGBlock.
- DomTreeNode *getRootNode() const {
- return DT->getRootNode();
+ /// \returns the root DomTreeNode, which is the wrapper for CFGBlock.
+ DomTreeNode *getRootNode() {
+ return DT.getRootNode();
}
- /// This method compares two dominator trees.
- /// The method returns false if the other dominator tree matches this
- /// dominator tree, otherwise returns true.
- bool compare(DominatorTree &Other) const {
+ /// Compares two dominator trees.
+ /// \returns false if the other dominator tree matches this dominator tree,
+ /// false otherwise.
+ bool compare(CFGDominatorTreeImpl &Other) const {
DomTreeNode *R = getRootNode();
DomTreeNode *OtherR = Other.getRootNode();
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
return true;
- if (DT->compare(Other.getBase()))
+ if (DT.compare(Other.getBase()))
return true;
return false;
}
- /// This method builds the dominator tree for a given CFG
- /// The CFG information is passed via AnalysisDeclContext
- void buildDominatorTree(AnalysisDeclContext &AC) {
- cfg = AC.getCFG();
- DT->recalculate(*cfg);
+ /// Builds the dominator tree for a given CFG.
+ void buildDominatorTree(CFG *cfg) {
+ assert(cfg);
+ this->cfg = cfg;
+ DT.recalculate(*cfg);
}
- /// This method dumps immediate dominators for each block,
- /// mainly used for debug purposes.
+ /// Dumps immediate dominators for each block.
void dump() {
- llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n";
+ llvm::errs() << "Immediate " << (IsPostDom ? "post " : "")
+ << "dominance tree (Node#,IDom#):\n";
for (CFG::const_iterator I = cfg->begin(),
E = cfg->end(); I != E; ++I) {
- if(DT->getNode(*I)->getIDom())
+
+ assert(*I &&
+ "LLVM's Dominator tree builder uses nullpointers to signify the "
+ "virtual root!");
+
+ DomTreeNode *IDom = DT.getNode(*I)->getIDom();
+ if (IDom && IDom->getBlock())
llvm::errs() << "(" << (*I)->getBlockID()
<< ","
- << DT->getNode(*I)->getIDom()->getBlock()->getBlockID()
+ << IDom->getBlock()->getBlockID()
<< ")\n";
- else llvm::errs() << "(" << (*I)->getBlockID()
- << "," << (*I)->getBlockID() << ")\n";
+ else {
+ bool IsEntryBlock = *I == &(*I)->getParent()->getEntry();
+ bool IsExitBlock = *I == &(*I)->getParent()->getExit();
+
+ bool IsDomTreeRoot = !IDom && !IsPostDom && IsEntryBlock;
+ bool IsPostDomTreeRoot =
+ IDom && !IDom->getBlock() && IsPostDom && IsExitBlock;
+
+ assert((IsDomTreeRoot || IsPostDomTreeRoot) &&
+ "If the immediate dominator node is nullptr, the CFG block "
+ "should be the exit point (since it's the root of the dominator "
+ "tree), or if the CFG block it refers to is a nullpointer, it "
+ "must be the entry block (since it's the root of the post "
+ "dominator tree)");
+
+ (void)IsDomTreeRoot;
+ (void)IsPostDomTreeRoot;
+
+ llvm::errs() << "(" << (*I)->getBlockID()
+ << "," << (*I)->getBlockID() << ")\n";
+ }
}
}
- /// This method tests if one CFGBlock dominates the other.
- /// The method return true if A dominates B, false otherwise.
+ /// Tests whether \p A dominates \p B.
/// Note a block always dominates itself.
bool dominates(const CFGBlock *A, const CFGBlock *B) const {
- return DT->dominates(A, B);
+ return DT.dominates(A, B);
}
- /// This method tests if one CFGBlock properly dominates the other.
- /// The method return true if A properly dominates B, false otherwise.
+ /// Tests whether \p A properly dominates \p B.
+ /// \returns false if \p A is the same block as \p B, otherwise whether A
+ /// dominates B.
bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const {
- return DT->properlyDominates(A, B);
+ return DT.properlyDominates(A, B);
}
- /// This method finds the nearest common dominator CFG block
- /// for CFG block A and B. If there is no such block then return NULL.
+ /// \returns the nearest common dominator CFG block for CFG block \p A and \p
+ /// B. If there is no such block then return NULL.
CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
- return DT->findNearestCommonDominator(A, B);
+ return DT.findNearestCommonDominator(A, B);
}
const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
const CFGBlock *B) {
- return DT->findNearestCommonDominator(A, B);
+ return DT.findNearestCommonDominator(A, B);
}
- /// This method is used to update the dominator
- /// tree information when a node's immediate dominator changes.
+ /// Update the dominator tree information when a node's immediate dominator
+ /// changes.
void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
- DT->changeImmediateDominator(N, NewIDom);
+ DT.changeImmediateDominator(N, NewIDom);
}
- /// This method tests if the given CFGBlock can be reachable from root.
- /// Returns true if reachable, false otherwise.
+ /// Tests whether \p A is reachable from the entry block.
bool isReachableFromEntry(const CFGBlock *A) {
- return DT->isReachableFromEntry(A);
+ return DT.isReachableFromEntry(A);
}
- /// This method releases the memory held by the dominator tree.
+ /// Releases the memory held by the dominator tree.
virtual void releaseMemory() {
- DT->releaseMemory();
+ DT.releaseMemory();
}
- /// This method converts the dominator tree to human readable form.
+ /// Converts the dominator tree to human readable form.
virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const {
- DT->print(OS);
+ DT.print(OS);
}
private:
CFG *cfg;
+ DominatorTreeBase DT;
+};
+
+using CFGDomTree = CFGDominatorTreeImpl</*IsPostDom*/ false>;
+using CFGPostDomTree = CFGDominatorTreeImpl</*IsPostDom*/ true>;
+
+template<> void CFGDominatorTreeImpl<true>::anchor();
+template<> void CFGDominatorTreeImpl<false>::anchor();
+
+} // end of namespace clang
+
+namespace llvm {
+namespace IDFCalculatorDetail {
+
+/// Specialize ChildrenGetterTy to skip nullpointer successors.
+template <bool IsPostDom>
+struct ChildrenGetterTy<clang::CFGBlock, IsPostDom> {
+ using NodeRef = typename GraphTraits<clang::CFGBlock>::NodeRef;
+ using ChildrenTy = SmallVector<NodeRef, 8>;
+
+ ChildrenTy get(const NodeRef &N) {
+ using OrderedNodeTy =
+ typename IDFCalculatorBase<clang::CFGBlock, IsPostDom>::OrderedNodeTy;
+
+ auto Children = children<OrderedNodeTy>(N);
+ ChildrenTy Ret{Children.begin(), Children.end()};
+ Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+ return Ret;
+ }
+};
+
+} // end of namespace IDFCalculatorDetail
+} // end of namespace llvm
+
+namespace clang {
+
+class ControlDependencyCalculator : public ManagedAnalysis {
+ using IDFCalculator = llvm::IDFCalculatorBase<CFGBlock, /*IsPostDom=*/true>;
+ using CFGBlockVector = llvm::SmallVector<CFGBlock *, 4>;
+ using CFGBlockSet = llvm::SmallPtrSet<CFGBlock *, 4>;
+
+ CFGPostDomTree PostDomTree;
+ IDFCalculator IDFCalc;
+
+ llvm::DenseMap<CFGBlock *, CFGBlockVector> ControlDepenencyMap;
+
+public:
+ ControlDependencyCalculator(CFG *cfg)
+ : PostDomTree(cfg), IDFCalc(PostDomTree.getBase()) {}
+
+ const CFGPostDomTree &getCFGPostDomTree() const { return PostDomTree; }
+
+ // Lazily retrieves the set of control dependencies to \p A.
+ const CFGBlockVector &getControlDependencies(CFGBlock *A) {
+ auto It = ControlDepenencyMap.find(A);
+ if (It == ControlDepenencyMap.end()) {
+ CFGBlockSet DefiningBlock = {A};
+ IDFCalc.setDefiningBlocks(DefiningBlock);
+
+ CFGBlockVector ControlDependencies;
+ IDFCalc.calculate(ControlDependencies);
+
+ It = ControlDepenencyMap.insert({A, ControlDependencies}).first;
+ }
+
+ assert(It != ControlDepenencyMap.end());
+ return It->second;
+ }
+
+ /// Whether \p A is control dependent on \p B.
+ bool isControlDependent(CFGBlock *A, CFGBlock *B) {
+ return llvm::is_contained(getControlDependencies(A), B);
+ }
+
+ // Dumps immediate control dependencies for each block.
+ LLVM_DUMP_METHOD void dump() {
+ CFG *cfg = PostDomTree.getCFG();
+ llvm::errs() << "Control dependencies (Node#,Dependency#):\n";
+ for (CFGBlock *BB : *cfg) {
+
+ assert(BB &&
+ "LLVM's Dominator tree builder uses nullpointers to signify the "
+ "virtual root!");
+
+ for (CFGBlock *isControlDependency : getControlDependencies(BB))
+ llvm::errs() << "(" << BB->getBlockID()
+ << ","
+ << isControlDependency->getBlockID()
+ << ")\n";
+ }
+ }
};
} // namespace clang
+namespace llvm {
+
+/// Clang's CFG contains nullpointers for unreachable succesors, e.g. when an
+/// if statement's condition is always false, it's 'then' branch is represented
+/// with a nullptr. This however will result in a nullpointer derefernece for
+/// dominator tree calculation.
+///
+/// To circumvent this, let's just crudely specialize the children getters
+/// used in LLVM's dominator tree builder.
+namespace DomTreeBuilder {
+
+using ClangCFGDomChildrenGetter =
+SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<
+ /*Inverse=*/false>;
+
+template <>
+template <>
+inline ClangCFGDomChildrenGetter::ResultTy ClangCFGDomChildrenGetter::Get(
+ clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {
+ auto RChildren = reverse(children<NodePtr>(N));
+ ResultTy Ret(RChildren.begin(), RChildren.end());
+ Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+ return Ret;
+}
+
+using ClangCFGDomReverseChildrenGetter =
+SemiNCAInfo<clang::CFGDomTree::DominatorTreeBase>::ChildrenGetter<
+ /*Inverse=*/true>;
+
+template <>
+template <>
+inline ClangCFGDomReverseChildrenGetter::ResultTy
+ClangCFGDomReverseChildrenGetter::Get(
+ clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {
+ auto IChildren = inverse_children<NodePtr>(N);
+ ResultTy Ret(IChildren.begin(), IChildren.end());
+ Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+ return Ret;
+}
+
+using ClangCFGPostDomChildrenGetter =
+SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<
+ /*Inverse=*/false>;
+
+template <>
+template <>
+inline ClangCFGPostDomChildrenGetter::ResultTy
+ClangCFGPostDomChildrenGetter::Get(
+ clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/false>) {
+ auto RChildren = reverse(children<NodePtr>(N));
+ ResultTy Ret(RChildren.begin(), RChildren.end());
+ Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+ return Ret;
+}
+
+using ClangCFGPostDomReverseChildrenGetter =
+SemiNCAInfo<clang::CFGPostDomTree::DominatorTreeBase>::ChildrenGetter<
+ /*Inverse=*/true>;
+
+template <>
+template <>
+inline ClangCFGPostDomReverseChildrenGetter::ResultTy
+ClangCFGPostDomReverseChildrenGetter::Get(
+ clang::CFGBlock *N, std::integral_constant<bool, /*Inverse=*/true>) {
+ auto IChildren = inverse_children<NodePtr>(N);
+ ResultTy Ret(IChildren.begin(), IChildren.end());
+ Ret.erase(std::remove(Ret.begin(), Ret.end(), nullptr), Ret.end());
+ return Ret;
+}
+
+} // end of namespace DomTreeBuilder
+
//===-------------------------------------
/// DominatorTree GraphTraits specialization so the DominatorTree can be
/// iterable by generic graph iterators.
///
-namespace llvm {
-
-template <> struct GraphTraits< ::clang::DomTreeNode* > {
+template <> struct GraphTraits<clang::DomTreeNode *> {
using NodeRef = ::clang::DomTreeNode *;
using ChildIteratorType = ::clang::DomTreeNode::iterator;
@@ -182,17 +369,17 @@ template <> struct GraphTraits< ::clang::DomTreeNode* > {
}
};
-template <> struct GraphTraits< ::clang::DominatorTree* >
- : public GraphTraits< ::clang::DomTreeNode* > {
- static NodeRef getEntryNode(::clang::DominatorTree *DT) {
+template <> struct GraphTraits<clang::CFGDomTree *>
+ : public GraphTraits<clang::DomTreeNode *> {
+ static NodeRef getEntryNode(clang::CFGDomTree *DT) {
return DT->getRootNode();
}
- static nodes_iterator nodes_begin(::clang::DominatorTree *N) {
+ static nodes_iterator nodes_begin(clang::CFGDomTree *N) {
return nodes_iterator(df_begin(getEntryNode(N)));
}
- static nodes_iterator nodes_end(::clang::DominatorTree *N) {
+ static nodes_iterator nodes_end(clang::CFGDomTree *N) {
return nodes_iterator(df_end(getEntryNode(N)));
}
};
diff --git a/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h b/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
index edc6e00f1d00..9397c5df78ab 100644
--- a/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
+++ b/include/clang/Analysis/Analyses/ExprMutationAnalyzer.h
@@ -1,9 +1,8 @@
//===---------- ExprMutationAnalyzer.h ------------------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_EXPRMUTATIONANALYZER_H
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 114597661a67..a46c35ee5b30 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -1,9 +1,8 @@
//===- LiveVariables.h - Live Variable Analysis for Source CFGs -*- C++ --*-//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h
index 7df3dc66c311..08fda0982df4 100644
--- a/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -1,9 +1,8 @@
//===- PostOrderCFGView.h - Post order view of CFG blocks -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h
index d79f1b03df7b..514b9458d331 100644
--- a/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/include/clang/Analysis/Analyses/ReachableCode.h
@@ -1,9 +1,8 @@
//===- ReachableCode.h -----------------------------------------*- C++ --*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index c72db6f2b24b..18659aa4e5bb 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -1,9 +1,8 @@
//===- ThreadSafety.h -------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -120,18 +119,22 @@ public:
/// \param Kind -- the capability's name parameter (role, mutex, etc).
/// \param Expected -- the kind of lock expected.
/// \param Received -- the kind of lock received.
- /// \param Loc -- The SourceLocation of the Unlock.
+ /// \param LocLocked -- The SourceLocation of the Lock.
+ /// \param LocUnlock -- The SourceLocation of the Unlock.
virtual void handleIncorrectUnlockKind(StringRef Kind, Name LockName,
LockKind Expected, LockKind Received,
- SourceLocation Loc) {}
+ SourceLocation LocLocked,
+ SourceLocation LocUnlock) {}
/// Warn about lock function calls for locks which are already held.
/// \param Kind -- the capability's name parameter (role, mutex, etc).
/// \param LockName -- A StringRef name for the lock expression, to be printed
/// in the error message.
- /// \param Loc -- The location of the second lock expression.
+ /// \param LocLocked -- The location of the first lock expression.
+ /// \param LocDoubleLock -- The location of the second lock expression.
virtual void handleDoubleLock(StringRef Kind, Name LockName,
- SourceLocation Loc) {}
+ SourceLocation LocLocked,
+ SourceLocation LocDoubleLock) {}
/// Warn about situations where a mutex is sometimes held and sometimes not.
/// The three situations are:
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 422a1db7f6fd..4a58fe870944 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -1,9 +1,8 @@
//===- ThreadSafetyCommon.h -------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
index 2508af1af107..8d938c1b23c0 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
@@ -1,9 +1,8 @@
//===- ThreadSafetyLogical.h -----------------------------------*- C++ --*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This file defines a representation for logical expressions with SExpr leaves
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
index 0d2458b0c893..fc4881a7f0fd 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyOps.def
+++ b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
@@ -1,9 +1,8 @@
//===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index c106a9a42731..c26d2ed99dd2 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -1,9 +1,8 @@
//===- ThreadSafetyTIL.h ----------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT in the llvm repository for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -1605,7 +1604,7 @@ public:
/// Return the index of BB, or Predecessors.size if BB is not a predecessor.
unsigned findPredecessorIndex(const BasicBlock *BB) const {
- auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
+ auto I = llvm::find(Predecessors, BB);
return std::distance(Predecessors.cbegin(), I);
}
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index 32aadf526587..e81c00d3dddb 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -1,9 +1,8 @@
//===- ThreadSafetyTraverse.h -----------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index 16583939d542..e3b6e61d3026 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -1,9 +1,8 @@
//===- ThreadSafetyUtil.h ---------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 79d89e0633fd..479be1fec048 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -1,9 +1,8 @@
//=- UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-=//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h
index 490d2ce346be..1961d571e9e1 100644
--- a/include/clang/Analysis/AnalysisDeclContext.h
+++ b/include/clang/Analysis/AnalysisDeclContext.h
@@ -1,9 +1,8 @@
// AnalysisDeclContext.h - Analysis context for Path Sens analysis -*- C++ -*-//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -275,11 +274,17 @@ public:
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
void dumpStack(
- raw_ostream &OS, StringRef Indent = {}, const char *NL = "\n",
- const char *Sep = "",
+ raw_ostream &Out, const char *NL = "\n",
std::function<void(const LocationContext *)> printMoreInfoPerContext =
[](const LocationContext *) {}) const;
- void dumpStack() const;
+
+ void printJson(
+ raw_ostream &Out, const char *NL = "\n", unsigned int Space = 0,
+ bool IsDot = false,
+ std::function<void(const LocationContext *)> printMoreInfoPerContext =
+ [](const LocationContext *) {}) const;
+
+ void dump() const;
public:
static void ProfileCommon(llvm::FoldingSetNodeID &ID,
@@ -460,6 +465,7 @@ public:
bool addCXXNewAllocator = true,
bool addRichCXXConstructors = true,
bool markElidedCXXConstructors = true,
+ bool addVirtualBaseBranches = true,
CodeInjector *injector = nullptr);
AnalysisDeclContext *getContext(const Decl *D);
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index 087ffdcde90c..fd5f2ffe6483 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -1,9 +1,8 @@
//===--- DiagnosticAnalysis.h - Diagnostics for libanalysis -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/AnyCall.h b/include/clang/Analysis/AnyCall.h
new file mode 100644
index 000000000000..97a94d299e64
--- /dev/null
+++ b/include/clang/Analysis/AnyCall.h
@@ -0,0 +1,209 @@
+//=== AnyCall.h - Abstraction over different callables --------*- C++ -*--//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// A utility class for performing generic operations over different callables.
+//
+//===----------------------------------------------------------------------===//
+//
+#ifndef LLVM_CLANG_ANALYSIS_ANY_CALL_H
+#define LLVM_CLANG_ANALYSIS_ANY_CALL_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+
+namespace clang {
+
+/// An instance of this class corresponds to a call.
+/// It might be a syntactically-concrete call, done as a part of evaluating an
+/// expression, or it may be an abstract callee with no associated expression.
+class AnyCall {
+public:
+ enum Kind {
+ /// A function, function pointer, or a C++ method call
+ Function,
+
+ /// A call to an Objective-C method
+ ObjCMethod,
+
+ /// A call to an Objective-C block
+ Block,
+
+ /// An implicit C++ destructor call (called implicitly
+ /// or by operator 'delete')
+ Destructor,
+
+ /// An implicit or explicit C++ constructor call
+ Constructor,
+
+ /// A C++ allocation function call (operator `new`), via C++ new-expression
+ Allocator,
+
+ /// A C++ deallocation function call (operator `delete`), via C++
+ /// delete-expression
+ Deallocator
+ };
+
+private:
+ /// Either expression or declaration (but not both at the same time)
+ /// can be null.
+
+ /// Call expression, is null when is not known (then declaration is non-null),
+ /// or for implicit destructor calls (when no expression exists.)
+ const Expr *E = nullptr;
+
+ /// Corresponds to a statically known declaration of the called function,
+ /// or null if it is not known (e.g. for a function pointer).
+ const Decl *D = nullptr;
+ Kind K;
+
+public:
+ AnyCall(const CallExpr *CE) : E(CE) {
+ D = CE->getCalleeDecl();
+ K = (CE->getCallee()->getType()->getAs<BlockPointerType>()) ? Block
+ : Function;
+ if (D && ((K == Function && !isa<FunctionDecl>(D)) ||
+ (K == Block && !isa<BlockDecl>(D))))
+ D = nullptr;
+ }
+
+ AnyCall(const ObjCMessageExpr *ME)
+ : E(ME), D(ME->getMethodDecl()), K(ObjCMethod) {}
+
+ AnyCall(const CXXNewExpr *NE)
+ : E(NE), D(NE->getOperatorNew()), K(Allocator) {}
+
+ AnyCall(const CXXDeleteExpr *NE)
+ : E(NE), D(NE->getOperatorDelete()), K(Deallocator) {}
+
+ AnyCall(const CXXConstructExpr *NE)
+ : E(NE), D(NE->getConstructor()), K(Constructor) {}
+
+ AnyCall(const CXXDestructorDecl *D) : E(nullptr), D(D), K(Destructor) {}
+
+ AnyCall(const CXXConstructorDecl *D) : E(nullptr), D(D), K(Constructor) {}
+
+ AnyCall(const ObjCMethodDecl *D) : E(nullptr), D(D), K(ObjCMethod) {}
+
+ AnyCall(const FunctionDecl *D) : E(nullptr), D(D) {
+ if (isa<CXXConstructorDecl>(D)) {
+ K = Constructor;
+ } else if (isa <CXXDestructorDecl>(D)) {
+ K = Destructor;
+ } else {
+ K = Function;
+ }
+
+ }
+
+ /// If {@code E} is a generic call (to ObjC method /function/block/etc),
+ /// return a constructed {@code AnyCall} object. Return None otherwise.
+ static Optional<AnyCall> forExpr(const Expr *E) {
+ if (const auto *ME = dyn_cast<ObjCMessageExpr>(E)) {
+ return AnyCall(ME);
+ } else if (const auto *CE = dyn_cast<CallExpr>(E)) {
+ return AnyCall(CE);
+ } else if (const auto *CXNE = dyn_cast<CXXNewExpr>(E)) {
+ return AnyCall(CXNE);
+ } else if (const auto *CXDE = dyn_cast<CXXDeleteExpr>(E)) {
+ return AnyCall(CXDE);
+ } else if (const auto *CXCE = dyn_cast<CXXConstructExpr>(E)) {
+ return AnyCall(CXCE);
+ } else {
+ return None;
+ }
+ }
+
+ /// If {@code D} is a callable (Objective-C method or a function), return
+ /// a constructed {@code AnyCall} object. Return None otherwise.
+ // FIXME: block support.
+ static Optional<AnyCall> forDecl(const Decl *D) {
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ return AnyCall(FD);
+ } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ return AnyCall(MD);
+ }
+ return None;
+ }
+
+ /// \returns formal parameters for direct calls (including virtual calls)
+ ArrayRef<ParmVarDecl *> parameters() const {
+ if (!D)
+ return None;
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ return FD->parameters();
+ } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ return MD->parameters();
+ } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
+ return BD->parameters();
+ } else {
+ return None;
+ }
+ }
+
+ using param_const_iterator = ArrayRef<ParmVarDecl *>::const_iterator;
+ param_const_iterator param_begin() const { return parameters().begin(); }
+ param_const_iterator param_end() const { return parameters().end(); }
+ size_t param_size() const { return parameters().size(); }
+ bool param_empty() const { return parameters().empty(); }
+
+ QualType getReturnType(ASTContext &Ctx) const {
+ switch (K) {
+ case Function:
+ if (E)
+ return cast<CallExpr>(E)->getCallReturnType(Ctx);
+ return cast<FunctionDecl>(D)->getReturnType();
+ case ObjCMethod:
+ if (E)
+ return cast<ObjCMessageExpr>(E)->getCallReturnType(Ctx);
+ return cast<ObjCMethodDecl>(D)->getReturnType();
+ case Block:
+ // FIXME: BlockDecl does not know its return type,
+ // hence the asymmetry with the function and method cases above.
+ return cast<CallExpr>(E)->getCallReturnType(Ctx);
+ case Destructor:
+ case Constructor:
+ case Allocator:
+ case Deallocator:
+ return cast<FunctionDecl>(D)->getReturnType();
+ }
+ llvm_unreachable("Unknown AnyCall::Kind");
+ }
+
+ /// \returns Function identifier if it is a named declaration,
+ /// {@code nullptr} otherwise.
+ const IdentifierInfo *getIdentifier() const {
+ if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
+ return ND->getIdentifier();
+ return nullptr;
+ }
+
+ const Decl *getDecl() const {
+ return D;
+ }
+
+ const Expr *getExpr() const {
+ return E;
+ }
+
+ Kind getKind() const {
+ return K;
+ }
+
+ void dump() const {
+ if (E)
+ E->dump();
+ if (D)
+ D->dump();
+ }
+};
+
+}
+
+#endif // LLVM_CLANG_ANALYSIS_ANY_CALL_H
diff --git a/include/clang/Analysis/BodyFarm.h b/include/clang/Analysis/BodyFarm.h
index ff0859bc662d..72607f8839f5 100644
--- a/include/clang/Analysis/BodyFarm.h
+++ b/include/clang/Analysis/BodyFarm.h
@@ -1,9 +1,8 @@
//== BodyFarm.h - Factory for conjuring up fake bodies -------------*- C++ -*-//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index bf81d8358a54..277b2292e5ea 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -1,9 +1,8 @@
//===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -495,33 +494,51 @@ private:
/// Represents CFGBlock terminator statement.
///
-/// TemporaryDtorsBranch bit is set to true if the terminator marks a branch
-/// in control flow of destructors of temporaries. In this case terminator
-/// statement is the same statement that branches control flow in evaluation
-/// of matching full expression.
class CFGTerminator {
- llvm::PointerIntPair<Stmt *, 1> Data;
+public:
+ enum Kind {
+ /// A branch that corresponds to a statement in the code,
+ /// such as an if-statement.
+ StmtBranch,
+ /// A branch in control flow of destructors of temporaries. In this case
+ /// terminator statement is the same statement that branches control flow
+ /// in evaluation of matching full expression.
+ TemporaryDtorsBranch,
+ /// A shortcut around virtual base initializers. It gets taken when
+ /// virtual base classes have already been initialized by the constructor
+ /// of the most derived class while we're in the base class.
+ VirtualBaseBranch,
+
+ /// Number of different kinds, for sanity checks. We subtract 1 so that
+ /// to keep receiving compiler warnings when we don't cover all enum values
+ /// in a switch.
+ NumKindsMinusOne = VirtualBaseBranch
+ };
+
+private:
+ static constexpr int KindBits = 2;
+ static_assert((1 << KindBits) > NumKindsMinusOne,
+ "Not enough room for kind!");
+ llvm::PointerIntPair<Stmt *, KindBits> Data;
public:
- CFGTerminator() = default;
- CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false)
- : Data(S, TemporaryDtorsBranch) {}
+ CFGTerminator() { assert(!isValid()); }
+ CFGTerminator(Stmt *S, Kind K = StmtBranch) : Data(S, K) {}
+ bool isValid() const { return Data.getOpaqueValue() != nullptr; }
Stmt *getStmt() { return Data.getPointer(); }
const Stmt *getStmt() const { return Data.getPointer(); }
+ Kind getKind() const { return static_cast<Kind>(Data.getInt()); }
- bool isTemporaryDtorsBranch() const { return Data.getInt(); }
-
- operator Stmt *() { return getStmt(); }
- operator const Stmt *() const { return getStmt(); }
-
- Stmt *operator->() { return getStmt(); }
- const Stmt *operator->() const { return getStmt(); }
-
- Stmt &operator*() { return *getStmt(); }
- const Stmt &operator*() const { return *getStmt(); }
-
- explicit operator bool() const { return getStmt(); }
+ bool isStmtBranch() const {
+ return getKind() == StmtBranch;
+ }
+ bool isTemporaryDtorsBranch() const {
+ return getKind() == TemporaryDtorsBranch;
+ }
+ bool isVirtualBaseBranch() const {
+ return getKind() == VirtualBaseBranch;
+ }
};
/// Represents a single basic block in a source-level CFG.
@@ -542,11 +559,12 @@ public:
/// Successors: the order in the set of successors is NOT arbitrary. We
/// currently have the following orderings based on the terminator:
///
-/// Terminator Successor Ordering
-/// -----------------------------------------------------
-/// if Then Block; Else Block
-/// ? operator LHS expression; RHS expression
-/// &&, || expression that uses result of && or ||, RHS
+/// Terminator | Successor Ordering
+/// ------------------|------------------------------------
+/// if | Then Block; Else Block
+/// ? operator | LHS expression; RHS expression
+/// logical and/or | expression that consumes the op, RHS
+/// vbase inits | already handled by the most derived class; not yet
///
/// But note that any of that may be NULL in case of optimized-out edges.
class CFGBlock {
@@ -837,8 +855,18 @@ public:
void setLoopTarget(const Stmt *loopTarget) { LoopTarget = loopTarget; }
void setHasNoReturnElement() { HasNoReturnElement = true; }
- CFGTerminator getTerminator() { return Terminator; }
- const CFGTerminator getTerminator() const { return Terminator; }
+ CFGTerminator getTerminator() const { return Terminator; }
+
+ Stmt *getTerminatorStmt() { return Terminator.getStmt(); }
+ const Stmt *getTerminatorStmt() const { return Terminator.getStmt(); }
+
+ /// \returns the last (\c rbegin()) condition, e.g. observe the following code
+ /// snippet:
+ /// if (A && B && C)
+ /// A block would be created for \c A, \c B, and \c C. For the latter,
+ /// \c getTerminatorStmt() would retrieve the entire condition, rather than
+ /// C itself, while this method would only return C.
+ const Expr *getLastCondition() const;
Stmt *getTerminatorCondition(bool StripParens = true);
@@ -862,7 +890,11 @@ public:
void dump(const CFG *cfg, const LangOptions &LO, bool ShowColors = false) const;
void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO,
bool ShowColors) const;
+
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
+ void printTerminatorJson(raw_ostream &Out, const LangOptions &LO,
+ bool AddQuotes) const;
+
void printAsOperand(raw_ostream &OS, bool /*PrintType*/) {
OS << "BB#" << getBlockID();
}
@@ -1027,6 +1059,7 @@ public:
bool AddCXXDefaultInitExprInCtors = false;
bool AddRichCXXConstructors = false;
bool MarkElidedCXXConstructors = false;
+ bool AddVirtualBaseBranches = false;
BuildOptions() = default;
@@ -1173,6 +1206,12 @@ public:
/// implementation needs such an interface.
unsigned size() const { return NumBlockIDs; }
+ /// Returns true if the CFG has no branches. Usually it boils down to the CFG
+ /// having exactly three blocks (entry, the actual code, exit), but sometimes
+ /// more blocks appear due to having control flow that can be fully
+ /// resolved in compile time.
+ bool isLinear() const;
+
//===--------------------------------------------------------------------===//
// CFG Debugging: Pretty-Printing and Visualization.
//===--------------------------------------------------------------------===//
@@ -1246,6 +1285,9 @@ template <> struct GraphTraits< ::clang::CFGBlock *> {
static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
};
+template <> struct GraphTraits<clang::CFGBlock>
+ : GraphTraits<clang::CFGBlock *> {};
+
template <> struct GraphTraits< const ::clang::CFGBlock *> {
using NodeRef = const ::clang::CFGBlock *;
using ChildIteratorType = ::clang::CFGBlock::const_succ_iterator;
@@ -1255,6 +1297,9 @@ template <> struct GraphTraits< const ::clang::CFGBlock *> {
static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); }
};
+template <> struct GraphTraits<const clang::CFGBlock>
+ : GraphTraits<clang::CFGBlock *> {};
+
template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> {
using NodeRef = ::clang::CFGBlock *;
using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator;
@@ -1267,6 +1312,9 @@ template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> {
static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
+template <> struct GraphTraits<Inverse<clang::CFGBlock>>
+ : GraphTraits<clang::CFGBlock *> {};
+
template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> {
using NodeRef = const ::clang::CFGBlock *;
using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator;
@@ -1279,6 +1327,9 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> {
static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); }
};
+template <> struct GraphTraits<const Inverse<clang::CFGBlock>>
+ : GraphTraits<clang::CFGBlock *> {};
+
// Traits for: CFG
template <> struct GraphTraits< ::clang::CFG* >
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
index 78e637daf379..8cf02372ff0f 100644
--- a/include/clang/Analysis/CFGStmtMap.h
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -1,9 +1,8 @@
//===--- CFGStmtMap.h - Map from Stmt* to CFGBlock* -----------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index e230930b59e0..49c04490fed2 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -1,9 +1,8 @@
//===- CallGraph.h - AST-based Call graph -----------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h
index fadca137b88d..db827c3a6d6f 100644
--- a/include/clang/Analysis/CloneDetection.h
+++ b/include/clang/Analysis/CloneDetection.h
@@ -1,9 +1,8 @@
//===--- CloneDetection.h - Finds code clones in an AST ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
diff --git a/include/clang/Analysis/CodeInjector.h b/include/clang/Analysis/CodeInjector.h
index 2c87cde996f2..a59dc0a94159 100644
--- a/include/clang/Analysis/CodeInjector.h
+++ b/include/clang/Analysis/CodeInjector.h
@@ -1,9 +1,8 @@
//===-- CodeInjector.h ------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h
index 27c1d5b9f1a5..f1564f9fe740 100644
--- a/include/clang/Analysis/ConstructionContext.h
+++ b/include/clang/Analysis/ConstructionContext.h
@@ -1,9 +1,8 @@
//===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
index 9326d1abbac1..8531d17767ba 100644
--- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h
+++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -1,9 +1,8 @@
//===- CocoaConventions.h - Special handling of Cocoa conventions -*- C++ -*--//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
index e304d83615d4..80d7cb8e03a1 100644
--- a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
+++ b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
@@ -1,9 +1,8 @@
//= ObjCNoReturn.h - Handling of Cocoa APIs known not to return --*- C++ -*---//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/FlowSensitive/DataflowValues.h b/include/clang/Analysis/FlowSensitive/DataflowValues.h
index f86b2b0bfea1..709753339eb5 100644
--- a/include/clang/Analysis/FlowSensitive/DataflowValues.h
+++ b/include/clang/Analysis/FlowSensitive/DataflowValues.h
@@ -1,9 +1,8 @@
//===--- DataflowValues.h - Data structure for dataflow values --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index d78174ecd70e..546224bfd58d 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -1,9 +1,8 @@
//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -43,12 +42,11 @@ public:
virtual ~ProgramPointTag();
virtual StringRef getTagDescription() const = 0;
-protected:
/// Used to implement 'isKind' in subclasses.
- const void *getTagKind() { return TagKind; }
+ const void *getTagKind() const { return TagKind; }
private:
- const void *TagKind;
+ const void *const TagKind;
};
class SimpleProgramPointTag : public ProgramPointTag {
@@ -215,7 +213,7 @@ public:
ID.AddPointer(getTag());
}
- void print(StringRef CR, llvm::raw_ostream &Out) const;
+ void printJson(llvm::raw_ostream &Out, const char *NL = "\n") const;
LLVM_DUMP_METHOD void dump() const;
@@ -259,7 +257,7 @@ public:
}
const Stmt *getTerminator() const {
- return getBlock()->getTerminator();
+ return getBlock()->getTerminatorStmt();
}
private:
@@ -778,9 +776,6 @@ static bool isEqual(const clang::ProgramPoint &L,
};
-template <>
-struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
-
} // end namespace llvm
#endif
diff --git a/include/clang/Analysis/RetainSummaryManager.h b/include/clang/Analysis/RetainSummaryManager.h
new file mode 100644
index 000000000000..6acefb563d8c
--- /dev/null
+++ b/include/clang/Analysis/RetainSummaryManager.h
@@ -0,0 +1,767 @@
+//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines summaries implementation for retain counting, which
+// implements a reference count checker for Core Foundation and Cocoa
+// on (Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
+#define LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/Analysis/AnyCall.h"
+#include "clang/Analysis/SelectorExtras.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+
+namespace clang {
+namespace ento {
+
+/// Determines the object kind of a tracked object.
+enum class ObjKind {
+ /// Indicates that the tracked object is a CF object.
+ CF,
+
+ /// Indicates that the tracked object is an Objective-C object.
+ ObjC,
+
+ /// Indicates that the tracked object could be a CF or Objective-C object.
+ AnyObj,
+
+ /// Indicates that the tracked object is a generalized object.
+ Generalized,
+
+ /// Indicates that the tracking object is a descendant of a
+ /// referenced-counted OSObject, used in the Darwin kernel.
+ OS
+};
+
+enum ArgEffectKind {
+ /// There is no effect.
+ DoNothing,
+
+ /// The argument is treated as if an -autorelease message had been sent to
+ /// the referenced object.
+ Autorelease,
+
+ /// The argument is treated as if the referenced object was deallocated.
+ Dealloc,
+
+ /// The argument has its reference count decreased by 1.
+ DecRef,
+
+ /// The argument has its reference count decreased by 1 to model
+ /// a transferred bridge cast under ARC.
+ DecRefBridgedTransferred,
+
+ /// The argument has its reference count increased by 1.
+ IncRef,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +0 value.
+ UnretainedOutParameter,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value.
+ RetainedOutParameter,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value iff the return code is zero.
+ RetainedOutParameterOnZero,
+
+ /// The argument is a pointer to a retain-counted object; on exit, the new
+ /// value of the pointer is a +1 value iff the return code is non-zero.
+ RetainedOutParameterOnNonZero,
+
+ /// The argument is treated as potentially escaping, meaning that
+ /// even when its reference count hits 0 it should be treated as still
+ /// possibly being alive as someone else *may* be holding onto the object.
+ MayEscape,
+
+ /// All typestate tracking of the object ceases. This is usually employed
+ /// when the effect of the call is completely unknown.
+ StopTracking,
+
+ /// All typestate tracking of the object ceases. Unlike StopTracking,
+ /// this is also enforced when the method body is inlined.
+ ///
+ /// In some cases, we obtain a better summary for this checker
+ /// by looking at the call site than by inlining the function.
+ /// Signifies that we should stop tracking the symbol even if
+ /// the function is inlined.
+ StopTrackingHard,
+
+ /// Performs the combined functionality of DecRef and StopTrackingHard.
+ ///
+ /// The models the effect that the called function decrements the reference
+ /// count of the argument and all typestate tracking on that argument
+ /// should cease.
+ DecRefAndStopTrackingHard,
+};
+
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+class ArgEffect {
+ ArgEffectKind K;
+ ObjKind O;
+public:
+ explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
+ : K(K), O(O) {}
+
+ ArgEffectKind getKind() const { return K; }
+ ObjKind getObjKind() const { return O; }
+
+ ArgEffect withKind(ArgEffectKind NewK) {
+ return ArgEffect(NewK, O);
+ }
+
+ bool operator==(const ArgEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+};
+
+/// RetEffect summarizes a call's retain/release behavior with respect
+/// to its return value.
+class RetEffect {
+public:
+ enum Kind {
+ /// Indicates that no retain count information is tracked for
+ /// the return value.
+ NoRet,
+
+ /// Indicates that the returned value is an owned (+1) symbol.
+ OwnedSymbol,
+
+ /// Indicates that the returned value is an object with retain count
+ /// semantics but that it is not owned (+0). This is the default
+ /// for getters, etc.
+ NotOwnedSymbol,
+
+ /// Indicates that the return value is an owned object when the
+ /// receiver is also a tracked object.
+ OwnedWhenTrackedReceiver,
+
+ // Treat this function as returning a non-tracked symbol even if
+ // the function has been inlined. This is used where the call
+ // site summary is more precise than the summary indirectly produced
+ // by inlining the function
+ NoRetHard
+ };
+
+private:
+ Kind K;
+ ObjKind O;
+
+ RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
+
+public:
+ Kind getKind() const { return K; }
+
+ ObjKind getObjKind() const { return O; }
+
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
+ }
+
+ bool notOwned() const {
+ return K == NotOwnedSymbol;
+ }
+
+ bool operator==(const RetEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+
+ static RetEffect MakeOwnedWhenTrackedReceiver() {
+ return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
+ }
+
+ static RetEffect MakeOwned(ObjKind o) {
+ return RetEffect(OwnedSymbol, o);
+ }
+ static RetEffect MakeNotOwned(ObjKind o) {
+ return RetEffect(NotOwnedSymbol, o);
+ }
+ static RetEffect MakeNoRet() {
+ return RetEffect(NoRet);
+ }
+ static RetEffect MakeNoRetHard() {
+ return RetEffect(NoRetHard);
+ }
+};
+
+/// A key identifying a summary.
+class ObjCSummaryKey {
+ IdentifierInfo* II;
+ Selector S;
+public:
+ ObjCSummaryKey(IdentifierInfo* ii, Selector s)
+ : II(ii), S(s) {}
+
+ ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
+ : II(d ? d->getIdentifier() : nullptr), S(s) {}
+
+ ObjCSummaryKey(Selector s)
+ : II(nullptr), S(s) {}
+
+ IdentifierInfo *getIdentifier() const { return II; }
+ Selector getSelector() const { return S; }
+};
+
+} // end namespace ento
+} // end namespace clang
+
+using namespace ento;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+// Adapters for FoldingSet.
+//===----------------------------------------------------------------------===//
+template <> struct FoldingSetTrait<ArgEffect> {
+static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
+ ID.AddInteger((unsigned) X.getKind());
+ ID.AddInteger((unsigned) X.getObjKind());
+}
+};
+template <> struct FoldingSetTrait<RetEffect> {
+ static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
+ ID.AddInteger((unsigned) X.getKind());
+ ID.AddInteger((unsigned) X.getObjKind());
+}
+};
+
+template <> struct DenseMapInfo<ObjCSummaryKey> {
+ static inline ObjCSummaryKey getEmptyKey() {
+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
+ DenseMapInfo<Selector>::getEmptyKey());
+ }
+
+ static inline ObjCSummaryKey getTombstoneKey() {
+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
+ DenseMapInfo<Selector>::getTombstoneKey());
+ }
+
+ static unsigned getHashValue(const ObjCSummaryKey &V) {
+ typedef std::pair<IdentifierInfo*, Selector> PairTy;
+ return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
+ V.getSelector()));
+ }
+
+ static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
+ return LHS.getIdentifier() == RHS.getIdentifier() &&
+ LHS.getSelector() == RHS.getSelector();
+ }
+
+};
+
+} // end llvm namespace
+
+
+namespace clang {
+namespace ento {
+
+/// ArgEffects summarizes the effects of a function/method call on all of
+/// its arguments.
+typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
+
+/// Summary for a function with respect to ownership changes.
+class RetainSummary {
+ /// Args - a map of (index, ArgEffect) pairs, where index
+ /// specifies the argument (starting from 0). This can be sparsely
+ /// populated; arguments with no entry in Args use 'DefaultArgEffect'.
+ ArgEffects Args;
+
+ /// DefaultArgEffect - The default ArgEffect to apply to arguments that
+ /// do not have an entry in Args.
+ ArgEffect DefaultArgEffect;
+
+ /// Receiver - If this summary applies to an Objective-C message expression,
+ /// this is the effect applied to the state of the receiver.
+ ArgEffect Receiver;
+
+ /// Effect on "this" pointer - applicable only to C++ method calls.
+ ArgEffect This;
+
+ /// Ret - The effect on the return value. Used to indicate if the
+ /// function/method call returns a new tracked symbol.
+ RetEffect Ret;
+
+public:
+ RetainSummary(ArgEffects A,
+ RetEffect R,
+ ArgEffect defaultEff,
+ ArgEffect ReceiverEff,
+ ArgEffect ThisEff)
+ : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
+ This(ThisEff), Ret(R) {}
+
+ /// getArg - Return the argument effect on the argument specified by
+ /// idx (starting from 0).
+ ArgEffect getArg(unsigned idx) const {
+ if (const ArgEffect *AE = Args.lookup(idx))
+ return *AE;
+
+ return DefaultArgEffect;
+ }
+
+ void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
+ Args = af.add(Args, idx, e);
+ }
+
+ /// setDefaultArgEffect - Set the default argument effect.
+ void setDefaultArgEffect(ArgEffect E) {
+ DefaultArgEffect = E;
+ }
+
+ /// getRetEffect - Returns the effect on the return value of the call.
+ RetEffect getRetEffect() const { return Ret; }
+
+ /// setRetEffect - Set the effect of the return value of the call.
+ void setRetEffect(RetEffect E) { Ret = E; }
+
+
+ /// Sets the effect on the receiver of the message.
+ void setReceiverEffect(ArgEffect e) { Receiver = e; }
+
+ /// getReceiverEffect - Returns the effect on the receiver of the call.
+ /// This is only meaningful if the summary applies to an ObjCMessageExpr*.
+ ArgEffect getReceiverEffect() const { return Receiver; }
+
+ /// \return the effect on the "this" receiver of the method call.
+ /// This is only meaningful if the summary applies to CXXMethodDecl*.
+ ArgEffect getThisEffect() const { return This; }
+
+ ArgEffect getDefaultEffect() const { return DefaultArgEffect; }
+
+ /// Set the effect of the method on "this".
+ void setThisEffect(ArgEffect e) { This = e; }
+
+ bool isNoop() const {
+ return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
+ && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
+ && Args.isEmpty();
+ }
+
+ /// Test if two retain summaries are identical. Note that merely equivalent
+ /// summaries are not necessarily identical (for example, if an explicit
+ /// argument effect matches the default effect).
+ bool operator==(const RetainSummary &Other) const {
+ return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
+ Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
+ }
+
+ /// Profile this summary for inclusion in a FoldingSet.
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ ID.Add(Args);
+ ID.Add(DefaultArgEffect);
+ ID.Add(Receiver);
+ ID.Add(This);
+ ID.Add(Ret);
+ }
+
+ /// A retain summary is simple if it has no ArgEffects other than the default.
+ bool isSimple() const {
+ return Args.isEmpty();
+ }
+
+ ArgEffects getArgEffects() const { return Args; }
+
+private:
+ ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
+
+ friend class RetainSummaryManager;
+};
+
+class ObjCSummaryCache {
+ typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
+ MapTy M;
+public:
+ ObjCSummaryCache() {}
+
+ const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
+ // Do a lookup with the (D,S) pair. If we find a match return
+ // the iterator.
+ ObjCSummaryKey K(D, S);
+ MapTy::iterator I = M.find(K);
+
+ if (I != M.end())
+ return I->second;
+ if (!D)
+ return nullptr;
+
+ // Walk the super chain. If we find a hit with a parent, we'll end
+ // up returning that summary. We actually allow that key (null,S), as
+ // we cache summaries for the null ObjCInterfaceDecl* to allow us to
+ // generate initial summaries without having to worry about NSObject
+ // being declared.
+ // FIXME: We may change this at some point.
+ for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
+ if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
+ break;
+
+ if (!C)
+ return nullptr;
+ }
+
+ // Cache the summary with original key to make the next lookup faster
+ // and return the iterator.
+ const RetainSummary *Summ = I->second;
+ M[K] = Summ;
+ return Summ;
+ }
+
+ const RetainSummary *find(IdentifierInfo* II, Selector S) {
+ // FIXME: Class method lookup. Right now we don't have a good way
+ // of going between IdentifierInfo* and the class hierarchy.
+ MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
+
+ if (I == M.end())
+ I = M.find(ObjCSummaryKey(S));
+
+ return I == M.end() ? nullptr : I->second;
+ }
+
+ const RetainSummary *& operator[](ObjCSummaryKey K) {
+ return M[K];
+ }
+
+ const RetainSummary *& operator[](Selector S) {
+ return M[ ObjCSummaryKey(S) ];
+ }
+};
+
+class RetainSummaryTemplate;
+
+class RetainSummaryManager {
+ typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
+ FuncSummariesTy;
+
+ typedef ObjCSummaryCache ObjCMethodSummariesTy;
+
+ typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
+
+ /// Ctx - The ASTContext object for the analyzed ASTs.
+ ASTContext &Ctx;
+
+ /// Records whether or not the analyzed code runs in ARC mode.
+ const bool ARCEnabled;
+
+ /// Track Objective-C and CoreFoundation objects.
+ const bool TrackObjCAndCFObjects;
+
+ /// Track sublcasses of OSObject.
+ const bool TrackOSObjects;
+
+ /// FuncSummaries - A map from FunctionDecls to summaries.
+ FuncSummariesTy FuncSummaries;
+
+ /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
+ /// to summaries.
+ ObjCMethodSummariesTy ObjCClassMethodSummaries;
+
+ /// ObjCMethodSummaries - A map from selectors to summaries.
+ ObjCMethodSummariesTy ObjCMethodSummaries;
+
+ /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
+ /// and all other data used by the checker.
+ llvm::BumpPtrAllocator BPAlloc;
+
+ /// AF - A factory for ArgEffects objects.
+ ArgEffects::Factory AF;
+
+ /// ObjCAllocRetE - Default return effect for methods returning Objective-C
+ /// objects.
+ RetEffect ObjCAllocRetE;
+
+ /// ObjCInitRetE - Default return effect for init methods returning
+ /// Objective-C objects.
+ RetEffect ObjCInitRetE;
+
+ /// SimpleSummaries - Used for uniquing summaries that don't have special
+ /// effects.
+ llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
+
+ /// Create an OS object at +1.
+ const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
+
+ /// Get an OS object at +0.
+ const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
+
+ /// Increment the reference count on OS object.
+ const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
+
+ /// Decrement the reference count on OS object.
+ const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
+
+ /// Free the OS object.
+ const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
+
+ const RetainSummary *getUnarySummary(const FunctionType* FT,
+ ArgEffectKind AE);
+
+ const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
+ const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
+ const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
+
+ const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
+
+ const RetainSummary *
+ getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
+ ArgEffect ReceiverEff = ArgEffect(DoNothing),
+ ArgEffect DefaultEff = ArgEffect(MayEscape),
+ ArgEffect ThisEff = ArgEffect(DoNothing)) {
+ RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
+ return getPersistentSummary(Summ);
+ }
+
+ const RetainSummary *getDoNothingSummary() {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ArgEffects(AF.getEmptyMap()),
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
+ }
+
+ const RetainSummary *getDefaultSummary() {
+ return getPersistentSummary(RetEffect::MakeNoRet(),
+ ArgEffects(AF.getEmptyMap()),
+ ArgEffect(DoNothing), ArgEffect(MayEscape));
+ }
+
+ const RetainSummary *getPersistentStopSummary() {
+ return getPersistentSummary(
+ RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
+ ArgEffect(StopTracking), ArgEffect(StopTracking));
+ }
+
+ void InitializeClassMethodSummaries();
+ void InitializeMethodSummaries();
+
+ void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
+ ObjCClassMethodSummaries[S] = Summ;
+ }
+
+ void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
+ ObjCMethodSummaries[S] = Summ;
+ }
+
+ void addClassMethSummary(const char* Cls, const char* name,
+ const RetainSummary *Summ, bool isNullary = true) {
+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+ Selector S = isNullary ? GetNullarySelector(name, Ctx)
+ : GetUnarySelector(name, Ctx);
+ ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ void addInstMethSummary(const char* Cls, const char* nullaryName,
+ const RetainSummary *Summ) {
+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
+ Selector S = GetNullarySelector(nullaryName, Ctx);
+ ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ template <typename... Keywords>
+ void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
+ const RetainSummary *Summ, Keywords *... Kws) {
+ Selector S = getKeywordSelector(Ctx, Kws...);
+ Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
+ }
+
+ template <typename... Keywords>
+ void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
+ Keywords *... Kws) {
+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
+ }
+
+ template <typename... Keywords>
+ void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
+ Keywords *... Kws) {
+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
+ Kws...);
+ }
+
+ template <typename... Keywords>
+ void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
+ Keywords *... Kws) {
+ addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
+ }
+
+ const RetainSummary * generateSummary(const FunctionDecl *FD,
+ bool &AllowAnnotations);
+
+ /// Return a summary for OSObject, or nullptr if not found.
+ const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
+ StringRef FName, QualType RetTy);
+
+ /// Return a summary for Objective-C or CF object, or nullptr if not found.
+ const RetainSummary *getSummaryForObjCOrCFObject(
+ const FunctionDecl *FD,
+ StringRef FName,
+ QualType RetTy,
+ const FunctionType *FT,
+ bool &AllowAnnotations);
+
+ /// Apply the annotation of {@code pd} in function {@code FD}
+ /// to the resulting summary stored in out-parameter {@code Template}.
+ /// \return whether an annotation was applied.
+ bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
+ const NamedDecl *FD,
+ RetainSummaryTemplate &Template);
+
+public:
+ RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
+ bool trackOSObjects)
+ : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
+ TrackObjCAndCFObjects(trackObjCAndCFObjects),
+ TrackOSObjects(trackOSObjects), AF(BPAlloc),
+ ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
+ : RetEffect::MakeOwned(ObjKind::ObjC)),
+ ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
+ : RetEffect::MakeOwnedWhenTrackedReceiver()) {
+ InitializeClassMethodSummaries();
+ InitializeMethodSummaries();
+ }
+
+ enum class BehaviorSummary {
+ // Function does not return.
+ NoOp,
+
+ // Function returns the first argument.
+ Identity,
+
+ // Function returns "this" argument.
+ IdentityThis,
+
+ // Function either returns zero, or the input parameter.
+ IdentityOrZero
+ };
+
+ Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
+ bool &hasTrustedImplementationAnnotation);
+
+ /// \return Whether the type corresponds to a known smart pointer
+ /// implementation (that is, everything about it is inlineable).
+ static bool isKnownSmartPointer(QualType QT);
+
+ bool isTrustedReferenceCountImplementation(const Decl *FD);
+
+ const RetainSummary *getSummary(AnyCall C,
+ bool HasNonZeroCallbackArg=false,
+ bool IsReceiverUnconsumedSelf=false,
+ QualType ReceiverType={});
+
+ RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
+private:
+
+ /// getMethodSummary - This version of getMethodSummary is used to query
+ /// the summary for the current method being analyzed.
+ const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
+
+ const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
+
+ const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy,
+ ObjCMethodSummariesTy &CachedSummaries);
+
+ const RetainSummary *
+ getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
+
+ const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
+
+ const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
+ Selector S, QualType RetTy);
+
+ /// Determine if there is a special return effect for this function or method.
+ Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
+ const Decl *D);
+
+ void updateSummaryFromAnnotations(const RetainSummary *&Summ,
+ const ObjCMethodDecl *MD);
+
+ void updateSummaryFromAnnotations(const RetainSummary *&Summ,
+ const FunctionDecl *FD);
+
+ const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
+ AnyCall &C);
+
+ /// Special case '[super init];' and '[self init];'
+ ///
+ /// Even though calling '[super init]' without assigning the result to self
+ /// and checking if the parent returns 'nil' is a bad pattern, it is common.
+ /// Additionally, our Self Init checker already warns about it. To avoid
+ /// overwhelming the user with messages from both checkers, we model the case
+ /// of '[super init]' in cases when it is not consumed by another expression
+ /// as if the call preserves the value of 'self'; essentially, assuming it can
+ /// never fail and return 'nil'.
+ /// Note, we don't want to just stop tracking the value since we want the
+ /// RetainCount checker to report leaks and use-after-free if SelfInit checker
+ /// is turned off.
+ void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
+
+ /// Set argument types for arguments which are not doing anything.
+ void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);
+
+ /// Determine whether a declaration {@code D} of correspondent type (return
+ /// type for functions/methods) {@code QT} has any of the given attributes,
+ /// provided they pass necessary validation checks AND tracking the given
+ /// attribute is enabled.
+ /// Returns the object kind corresponding to the present attribute, or None,
+ /// if none of the specified attributes are present.
+ /// Crashes if passed an attribute which is not explicitly handled.
+ template <class T>
+ Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
+
+ template <class T1, class T2, class... Others>
+ Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
+
+ friend class RetainSummaryTemplate;
+};
+
+
+// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
+// summaries. If a function or method looks like it has a default summary, but
+// it has annotations, the annotations are added to the stack-based template
+// and then copied into managed memory.
+class RetainSummaryTemplate {
+ RetainSummaryManager &Manager;
+ const RetainSummary *&RealSummary;
+ RetainSummary ScratchSummary;
+ bool Accessed;
+public:
+ RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
+ : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
+
+ ~RetainSummaryTemplate() {
+ if (Accessed)
+ RealSummary = Manager.getPersistentSummary(ScratchSummary);
+ }
+
+ RetainSummary &operator*() {
+ Accessed = true;
+ return ScratchSummary;
+ }
+
+ RetainSummary *operator->() {
+ Accessed = true;
+ return &ScratchSummary;
+ }
+};
+
+} // end namespace ento
+} // end namespace clang
+
+#endif
diff --git a/include/clang/Analysis/SelectorExtras.h b/include/clang/Analysis/SelectorExtras.h
index 767063e835e4..d26e9159a937 100644
--- a/include/clang/Analysis/SelectorExtras.h
+++ b/include/clang/Analysis/SelectorExtras.h
@@ -1,9 +1,8 @@
//=== SelectorExtras.h - Helpers for checkers using selectors -----*- C++ -*-=//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 00a7417e20f9..74092dabbfda 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -1,9 +1,8 @@
//===- BumpVector.h - Vector-like ADT that uses bump allocation -*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//