1//===- ASTMapping.cpp - AST to SSAF Entity mapping --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements utilities for mapping AST declarations to SSAF entities.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Analysis/Scalable/ASTEntityMapping.h"
14#include "clang/AST/Decl.h"
15#include "clang/Analysis/Scalable/Model/BuildNamespace.h"
16#include "clang/Index/USRGeneration.h"
17#include "llvm/ADT/SmallString.h"
18
19namespace clang::ssaf {
20
21std::optional<EntityName> getEntityName(const Decl *D) {
22 if (!D)
23 return std::nullopt;
24
25 if (D->isImplicit())
26 return std::nullopt;
27
28 if (isa<FunctionDecl>(Val: D) && cast<FunctionDecl>(Val: D)->getBuiltinID())
29 return std::nullopt;
30
31 if (!isa<FunctionDecl, ParmVarDecl, VarDecl, FieldDecl, RecordDecl>(Val: D))
32 return std::nullopt;
33
34 llvm::SmallString<16> Suffix;
35 const Decl *USRDecl = D;
36
37 // For parameters, use the parent function's USR with parameter index as
38 // suffix
39 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: D)) {
40 const auto *FD =
41 dyn_cast_or_null<FunctionDecl>(Val: PVD->getParentFunctionOrMethod());
42 if (!FD)
43 return std::nullopt;
44 USRDecl = FD;
45
46 const auto ParamIdx = PVD->getFunctionScopeIndex();
47 llvm::raw_svector_ostream OS(Suffix);
48 // Parameter uses function's USR with 1-based index as suffix
49 OS << (ParamIdx + 1);
50 }
51
52 llvm::SmallString<128> USRBuf;
53 if (clang::index::generateUSRForDecl(D: USRDecl, Buf&: USRBuf))
54 return std::nullopt;
55
56 if (USRBuf.empty())
57 return std::nullopt;
58
59 return EntityName(USRBuf.str(), Suffix, {});
60}
61
62std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD) {
63 if (!FD)
64 return std::nullopt;
65
66 if (FD->isImplicit())
67 return std::nullopt;
68
69 if (FD->getBuiltinID())
70 return std::nullopt;
71
72 llvm::SmallString<128> USRBuf;
73 if (clang::index::generateUSRForDecl(D: FD, Buf&: USRBuf)) {
74 return std::nullopt;
75 }
76
77 if (USRBuf.empty())
78 return std::nullopt;
79
80 return EntityName(USRBuf.str(), /*Suffix=*/"0", /*Namespace=*/{});
81}
82
83} // namespace clang::ssaf
84