1010#include " clang/AST/ASTContext.h"
1111#include " clang/AST/Decl.h"
1212#include " clang/AST/StmtVisitor.h"
13+ #include " clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
1314#include " clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
1415#include " clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
16+ #include < optional>
1517
1618using namespace clang ;
1719using namespace ssaf ;
1820
19- static bool hasPointerType (const Expr *E) {
20- auto Ty = E->getType ();
21- return !Ty.isNull () && !Ty->isFunctionPointerType () &&
22- (Ty->isPointerType () || Ty->isArrayType ());
21+ namespace {
22+ template <typename DeclOrExpr> bool hasPtrOrArrType (const DeclOrExpr *E) {
23+ return llvm::isa<PointerType, ArrayType>(E->getType ().getCanonicalType ());
2324}
2425
25- static llvm::Error makeUnsupportedStmtKindError (const Stmt *Unsupported) {
26- return llvm::createStringError (
27- " unsupported expression kind for translation to "
28- " EntityPointerLevel: %s" ,
29- Unsupported->getStmtClassName ());
26+ template <typename NodeTy, typename ... Ts>
27+ llvm::Error makeErrAtNode (ASTContext &Ctx, const NodeTy &N, StringRef Fmt,
28+ const Ts &...Args) {
29+ std::string LocStr = N.getBeginLoc ().printToString (Ctx.getSourceManager ());
30+ return llvm::createStringError ((Fmt + " at %s" ).str ().c_str (), Args...,
31+ LocStr.c_str ());
3032}
3133
32- static llvm::Error makeCreateEntityNameError (const NamedDecl *FailedDecl,
33- ASTContext &Ctx) {
34- std::string LocStr = FailedDecl->getSourceRange ().getBegin ().printToString (
35- Ctx.getSourceManager ());
36- return llvm::createStringError (
37- " failed to create entity name for %s declared at %s" ,
38- FailedDecl->getNameAsString ().c_str (), LocStr.c_str ());
34+ llvm::Error makeEntityNameErr (ASTContext &Ctx, const NamedDecl &D) {
35+ return makeErrAtNode (Ctx, D, " failed to create entity name for %s" ,
36+ D.getNameAsString ().data ());
3937}
38+ } // namespace
4039
4140namespace clang ::ssaf {
4241// Translate a pointer type expression 'E' to a (set of) EntityPointerLevel(s)
@@ -65,26 +64,19 @@ class EntityPointerLevelTranslator
6564
6665 // Fallback method for all unsupported expression kind:
6766 llvm::Error fallback (const Stmt *E) {
68- return makeUnsupportedStmtKindError (E);
69- }
70-
71- static EntityPointerLevel incrementPointerLevel (const EntityPointerLevel &E) {
72- return EntityPointerLevel (E.getEntity (), E.getPointerLevel () + 1 );
73- }
74-
75- static EntityPointerLevel decrementPointerLevel (const EntityPointerLevel &E) {
76- assert (E.getPointerLevel () > 0 );
77- return EntityPointerLevel (E.getEntity (), E.getPointerLevel () - 1 );
67+ return makeErrAtNode (Ctx, *E,
68+ " attempt to translate %s to EntityPointerLevels" ,
69+ E->getStmtClassName ());
7870 }
7971
8072 EntityPointerLevel createEntityPointerLevelFor (const EntityName &Name) {
81- return EntityPointerLevel (AddEntity (Name), 1 );
73+ return EntityPointerLevel ({ AddEntity (Name), 1 } );
8274 }
8375
8476 // The common helper function for Translate(*base):
8577 // Translate(*base) -> Translate(base) with .pointerLevel + 1
8678 Expected<EntityPointerLevelSet> translateDereferencePointer (const Expr *Ptr) {
87- assert (hasPointerType (Ptr));
79+ assert (hasPtrOrArrType (Ptr));
8880
8981 Expected<EntityPointerLevelSet> SubResult = Visit (Ptr);
9082 if (!SubResult)
@@ -103,6 +95,29 @@ class EntityPointerLevelTranslator
10395 : AddEntity(AddEntity), Ctx(Ctx) {}
10496
10597 Expected<EntityPointerLevelSet> translate (const Expr *E) { return Visit (E); }
98+ Expected<EntityPointerLevel> translate (const NamedDecl *D, bool IsRet) {
99+ if (IsRet && !isa<FunctionDecl>(D))
100+ return makeErrAtNode (
101+ Ctx, *D,
102+ " attempt to call getEntityNameForReturn on a NamedDecl of %s kind" ,
103+ D->getDeclKindName ());
104+
105+ std::optional<EntityName> EN =
106+ IsRet ? getEntityNameForReturn (cast<FunctionDecl>(D))
107+ : getEntityName (D);
108+ if (EN)
109+ return createEntityPointerLevelFor (*EN);
110+ return makeEntityNameErr (Ctx, *D);
111+ }
112+
113+ static EntityPointerLevel incrementPointerLevel (const EntityPointerLevel &E) {
114+ return EntityPointerLevel ({E.getEntity (), E.getPointerLevel () + 1 });
115+ }
116+
117+ static EntityPointerLevel decrementPointerLevel (const EntityPointerLevel &E) {
118+ assert (E.getPointerLevel () > 0 );
119+ return EntityPointerLevel ({E.getEntity (), E.getPointerLevel () - 1 });
120+ }
106121
107122private:
108123 Expected<EntityPointerLevelSet> VisitStmt (const Stmt *E) {
@@ -117,7 +132,7 @@ class EntityPointerLevelTranslator
117132 Expected<EntityPointerLevelSet> VisitBinaryOperator (const BinaryOperator *E) {
118133 switch (E->getOpcode ()) {
119134 case clang::BO_Add:
120- if (hasPointerType (E->getLHS ()))
135+ if (hasPtrOrArrType (E->getLHS ()))
121136 return Visit (E->getLHS ());
122137 return Visit (E->getRHS ());
123138 case clang::BO_Sub:
@@ -162,7 +177,7 @@ class EntityPointerLevelTranslator
162177 // Translate((T*)base) -> Translate(p) if p has pointer type
163178 // -> {} otherwise
164179 Expected<EntityPointerLevelSet> VisitCastExpr (const CastExpr *E) {
165- if (hasPointerType (E->getSubExpr ()))
180+ if (hasPtrOrArrType (E->getSubExpr ()))
166181 return Visit (E->getSubExpr ());
167182 return EntityPointerLevelSet{};
168183 }
@@ -215,14 +230,14 @@ class EntityPointerLevelTranslator
215230 Expected<EntityPointerLevelSet> VisitDeclRefExpr (const DeclRefExpr *E) {
216231 if (auto EntityName = getEntityName (E->getDecl ()))
217232 return EntityPointerLevelSet{createEntityPointerLevelFor (*EntityName)};
218- return makeCreateEntityNameError ( E->getDecl (), Ctx );
233+ return makeEntityNameErr (Ctx, * E->getDecl ());
219234 }
220235
221236 // Translate({., ->}f) -> {(MemberDecl, 1)}
222237 Expected<EntityPointerLevelSet> VisitMemberExpr (const MemberExpr *E) {
223238 if (auto EntityName = getEntityName (E->getMemberDecl ()))
224239 return EntityPointerLevelSet{createEntityPointerLevelFor (*EntityName)};
225- return makeCreateEntityNameError ( E->getMemberDecl (), Ctx );
240+ return makeEntityNameErr (Ctx, * E->getMemberDecl ());
226241 }
227242
228243 Expected<EntityPointerLevelSet>
@@ -234,13 +249,68 @@ class EntityPointerLevelTranslator
234249
235250Expected<EntityPointerLevelSet> clang::ssaf::translateEntityPointerLevel (
236251 const Expr *E, ASTContext &Ctx,
237- std::function <EntityId(EntityName EN)> AddEntity) {
252+ llvm::function_ref <EntityId(EntityName EN)> AddEntity) {
238253 EntityPointerLevelTranslator Translator (AddEntity, Ctx);
239254
240255 return Translator.translate (E);
241256}
242257
258+ // / Create an EntityPointerLevel from a ValueDecl of a pointer type.
259+ Expected<EntityPointerLevel> clang::ssaf::creatEntityPointerLevel (
260+ const NamedDecl *ND, llvm::function_ref<EntityId(EntityName EN)> AddEntity,
261+ bool IsFunRet) {
262+ EntityPointerLevelTranslator Translator (AddEntity, ND->getASTContext ());
263+
264+ return Translator.translate (ND, IsFunRet);
265+ }
266+
267+ EntityPointerLevel
268+ clang::ssaf::incrementPointerLevel (const EntityPointerLevel &E) {
269+ return EntityPointerLevelTranslator::incrementPointerLevel (E);
270+ }
271+
243272EntityPointerLevel clang::ssaf::buildEntityPointerLevel (EntityId Id,
244273 unsigned PtrLv) {
245274 return EntityPointerLevel ({Id, PtrLv});
246275}
276+
277+ // Writes an EntityPointerLevel as
278+ // Array [
279+ // Object { "@" : [entity-id]},
280+ // [pointer-level-integer]
281+ // ]
282+ llvm::json::Value clang::ssaf::entityPointerLevelToJSON (
283+ const EntityPointerLevel &EPL, JSONFormat::EntityIdToJSONFn EntityId2JSON) {
284+ return llvm::json::Array{EntityId2JSON (EPL.getEntity ()),
285+ llvm::json::Value (EPL.getPointerLevel ())};
286+ }
287+
288+ Expected<EntityPointerLevel> clang::ssaf::entityPointerLevelFromJSON (
289+ const llvm::json::Value &EPLData,
290+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
291+ auto *AsArr = EPLData.getAsArray ();
292+
293+ if (!AsArr || AsArr->size () != 2 )
294+ return makeSawButExpectedError (
295+ EPLData, " an array with exactly two elements representing "
296+ " EntityId and PointerLevel, respectively" );
297+
298+ auto *EntityIdObj = (*AsArr)[0 ].getAsObject ();
299+
300+ if (!EntityIdObj)
301+ return makeSawButExpectedError ((*AsArr)[0 ],
302+ " an object representing EntityId" );
303+
304+ Expected<EntityId> Id = EntityIdFromJSON (*EntityIdObj);
305+
306+ if (!Id)
307+ return Id.takeError ();
308+
309+ std::optional<uint64_t > PtrLv = (*AsArr)[1 ].getAsInteger ();
310+
311+ if (!PtrLv)
312+ return makeSawButExpectedError ((*AsArr)[1 ],
313+ " an integer representing PointerLevel" );
314+
315+ return buildEntityPointerLevel (*Id, *PtrLv);
316+ }
0 commit comments