24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/STLFunctionalExtras.h"
26#include "llvm/Support/Error.h"
33class PointerFlowMatcher {
37 TUSummaryExtractor &Extractor;
39 PointerFlowMatcher(ASTContext &Ctx, TUSummaryExtractor &Extractor)
40 : Ctx(Ctx), Extractor(Extractor) {}
42 llvm::Error
matches(
const DynTypedNode &DynNode,
const NamedDecl *RootDecl);
44 llvm::Error matchesInitializerList(
const ValueDecl *Base,
46 unsigned ArrayElementIndirectLevel = 0);
48 llvm::Error matchesStmt(
const Stmt *S,
const NamedDecl *RootDecl);
50 llvm::Error matchesDecl(
const Decl *D,
const NamedDecl *RootDecl);
53 llvm::Error addEdges(Expected<DeclPointerLevelVec> &&LHS,
54 Expected<DeclPointerLevelVec> &&RHS);
56 Expected<DeclPointerLevelVec> toDPL(
const Expr *N)
const {
57 return translateDeclPointerLevel(N, Ctx, Extractor);
60 static DeclPointerLevel toDPL(
const NamedDecl *N,
bool IsRet =
false) {
64 template <
typename ParmsProv
ider,
typename ArgsProv
ider>
65 llvm::Error matchesArgsWithParams(
unsigned ArgIdxStart, ParmsProvider *PP,
67 unsigned ArgIdx = ArgIdxStart;
69 for (
unsigned ParmIdx = 0;
70 ParmIdx < PP->getNumParams() && ArgIdx < AP->getNumArgs();
71 ++ArgIdx, ++ParmIdx) {
72 if (
const ParmVarDecl *PD = PP->getParamDecl(ParmIdx);
75 toDPL(AP->getArg(ArgIdx))))
79 return llvm::Error::success();
86 return llvm::joinErrors(LHS.takeError(), RHS.takeError());
88 return LHS.takeError();
90 return RHS.takeError();
92 return llvm::Error::success();
94 std::vector<DeclPointerLevelVec> LVecs, RVecs;
96 LVecs.reserve(LHS->size());
97 for (
const auto &L : *LHS)
99 RVecs.reserve(RHS->size());
100 for (
const auto &R : *RHS)
119 for (
const auto &[LDPL, RDPL] : llvm::zip(L, R)) {
120 auto LEPL = toEntityPointerLevel(LDPL, Ctx, Extractor);
122 return LEPL.takeError();
123 auto REPL = toEntityPointerLevel(RDPL, Ctx, Extractor);
125 return REPL.takeError();
126 Results[*LEPL].insert(*REPL);
128 return llvm::Error::success();
146llvm::Error PointerFlowMatcher::matches(
const DynTypedNode &DynNode,
147 const NamedDecl *RootDecl) {
148 if (
const Stmt *S = DynNode.
get<Stmt>())
149 return matchesStmt(S, RootDecl);
150 if (
const Decl *D = DynNode.
get<Decl>())
151 return matchesDecl(D, RootDecl);
152 return llvm::Error::success();
155llvm::Error PointerFlowMatcher::matchesStmt(
const Stmt *S,
156 const NamedDecl *RootDecl) {
158 if (
const auto *BO = dyn_cast<BinaryOperator>(S);
160 return addEdges(toDPL(BO->getLHS()), toDPL(BO->getRHS()));
164 if (
const auto *CE = dyn_cast<CallExpr>(S)) {
165 const FunctionDecl *FD = CE->getDirectCallee();
168 return llvm::Error::success();
173 if (
auto *MD = dyn_cast<CXXMethodDecl>(FD);
174 MD && !MD->isExplicitObjectMemberFunction())
176 return matchesArgsWithParams(ArgIdx, FD, CE);
180 if (
const auto *CCE = dyn_cast<CXXConstructExpr>(S)) {
181 return matchesArgsWithParams(0, CCE->getConstructor(), CCE);
183 if (
const auto *RS = dyn_cast<ReturnStmt>(S)) {
184 const Expr *RetExpr = RS->getRetValue();
186 return llvm::Error::success();
189 return llvm::Error::success();
192llvm::Error PointerFlowMatcher::matchesDecl(
const Decl *D,
193 const NamedDecl *RootDecl) {
194 const Expr *InitExpr =
nullptr;
196 if (
const auto *VD = dyn_cast<ValueDecl>(D)) {
197 if (
const auto *Var = dyn_cast<VarDecl>(VD))
198 InitExpr = Var->getInit();
199 if (
const auto *Fd = dyn_cast<FieldDecl>(VD))
200 InitExpr = Fd->getInClassInitializer();
203 if (
auto *InitLst = dyn_cast_or_null<InitListExpr>(InitExpr))
204 return matchesInitializerList(VD, InitLst);
212 if (
const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) {
213 for (
auto *E : CtorD->inits()) {
214 if (E->isDelegatingInitializer())
215 return matches(DynTypedNode::create(*E->getInit()), RootDecl);
218 toDPL(E->getInit())))
223 return llvm::Error::success();
227llvm::Error matchInitializerListForRecordDecl(PointerFlowMatcher &Matcher,
228 const RecordDecl *RecordTy,
229 const InitListExpr *ILE) {
230 if (
auto *CXXRD = dyn_cast<CXXRecordDecl>(RecordTy))
231 if (CXXRD->getNumBases() != 0) {
235 "attempt to create pointer assignment edges between "
236 "CXXRecordDecls with base classes and initializer-lists");
242 if (!InitField || ILE->
inits().empty())
243 return llvm::Error::success();
244 return Matcher.matchesInitializerList(InitField, ILE->
getInit(0));
253 if (
auto Err = Matcher.matchesInitializerList(*(FieldIter++),
Init))
255 return llvm::Error::success();
259llvm::Error matchInitializerListForArray(PointerFlowMatcher &Matcher,
260 const ValueDecl *
Array,
261 const InitListExpr *ILE,
262 unsigned ArrayIndirectLevel = 0) {
263 for (
auto *E : ILE->
inits())
265 Matcher.matchesInitializerList(
Array, E, ArrayIndirectLevel + 1))
267 return llvm::Error::success();
285PointerFlowMatcher::matchesInitializerList(
const ValueDecl *Base,
286 const Expr *InitExpr,
287 unsigned ArrayElementIndirectLevel) {
288 const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr);
292 return llvm::Error::success();
294 auto BaseDPL = toDPL(Base);
296 BaseDPL.PointerLevel += ArrayElementIndirectLevel;
303 if (
auto *RD =
Type->getAsRecordDecl())
304 return matchInitializerListForRecordDecl(*
this, RD, ILE);
305 if (
Type->isArrayType())
306 return matchInitializerListForArray(*
this, Base, ILE,
307 ArrayElementIndirectLevel);
312 return llvm::Error::success();
313 return matchesInitializerList(Base, ILE->
getInit(0));
316class PointerFlowTUSummaryExtractor :
public TUSummaryExtractor {
321 std::unique_ptr<PointerFlowEntitySummary>
322 extractEntitySummary(
const std::vector<const NamedDecl *> &ContributorDecls,
323 ASTContext &Ctx, TUSummaryExtractor &Extractor) {
324 PointerFlowMatcher Matcher(Ctx, Extractor);
326 for (
const auto *Contrib : ContributorDecls) {
327 auto MatchAction = [&Matcher, Contrib](
const DynTypedNode &Node) {
328 if (
auto Err = Matcher.matches(Node, Contrib))
334 return std::make_unique<PointerFlowEntitySummary>(
338 void HandleTranslationUnit(ASTContext &Ctx)
override {
340 *
this, SummaryBuilder, Ctx,
341 [&](
const std::vector<const NamedDecl *> &Decls) {
342 return extractEntitySummary(Decls, Ctx, *
this);
349namespace clang::ssaf {
354static TUSummaryExtractorRegistry::Add<PointerFlowTUSummaryExtractor>
356 "Extract pointer flow information");
Defines the clang::ASTContext interface.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
C Language Family Type Representation.
const T * get() const
Retrieve the stored node as type T.
FieldDecl * getInitializedFieldInUnion()
If this initializes a union, specifies which field in the union to initialize.
unsigned getNumInits() const
bool isSemanticForm() const
InitListExpr * getSemanticForm() const
const Expr * getInit(unsigned Init) const
ArrayRef< Expr * > inits() const
unsigned getNumFields() const
Returns the number of fields (non-static data members) in this record.
field_iterator field_begin() const
static constexpr llvm::StringLiteral Name
DynTypedNode DynTypedNode
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I)
1) Pops the value from the stack 2) Peeks a pointer from the stack 3) Pushes the value to field I of ...
void extractAndAddSummaries(TUSummaryExtractor &Extractor, TUSummaryBuilder &Builder, ASTContext &Ctx, ExtractorFnT ExtractFn, llvm::StringRef ExtractorName="")
The standard contributor-summary extraction procedure:
bool hasPtrOrArrType(const Expr *E)
void logWarningFromError(llvm::Error Err)
Log a warning from an llvm::Error.
llvm::Error makeErrAtNode(clang::ASTContext &Ctx, const NodeTy *N, llvm::StringRef Fmt, const Ts &...Args)
std::map< EntityPointerLevel, EntityPointerLevelSet > EdgeSet
Maps each LHS pointer (source / assignee) to the set of RHS pointers (destinations / assigned values)...
DeclPointerLevel createDeclPointerLevel(const NamedDecl *ND, bool IsFunRet=false)
Create an DeclPointerLevel (DPL) from a NamedDecl of a pointer/array type.
DeclPointerLevelVec elaborateHigherDeclPointerLevels(const DeclPointerLevel &DPL)
void findMatchesIn(const NamedDecl *Contributor, llvm::function_ref< void(const DynTypedNode &)> MatchActionRef)
Perform "MatchAction" on each Stmt and Decl belonging to the Contributor.
PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges)
volatile int PointerFlowExtractorAnchorSource
llvm::SmallVector< DeclPointerLevel, 2 > DeclPointerLevelVec
bool matches(const til::SExpr *E1, const til::SExpr *E2)
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
@ Type
The name was classified as a type.