1//===- TUSummaryExtractor.cpp ---------------------------------------------===//
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#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
10#include "clang/AST/Decl.h"
11#include "clang/AST/DeclBase.h"
12#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
13#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
14#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
15#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
16#include "llvm/Support/Casting.h"
17#include <optional>
18
19using namespace clang;
20using namespace ssaf;
21
22static EntityLinkageType getLinkageForDecl(const Decl *D) {
23 const auto *ND = dyn_cast<NamedDecl>(Val: D);
24 if (!ND)
25 return EntityLinkageType::None;
26
27 // Parameters have no linkage in C++, but SSAF needs them to inherit
28 // the external linkage from their parent functions.
29 // Here is why:
30 // SSAF treats parameters as entities and may not always associate them back
31 // to their parent functions. Therefore, it needs to identify parameters of
32 // functions with external linkage across different TUs. Treating them as
33 // having no linkage (as in C++) causes the same parameter in different TUs
34 // to be assigned different EntityIDs. As a result, the behavior of the
35 // parameter across multiple TUs cannot be correlated.
36 if (const auto *PVD = dyn_cast<ParmVarDecl>(Val: D)) {
37 if (const auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(
38 Val: PVD->getParentFunctionOrMethod())) {
39 return getLinkageForDecl(D: FD);
40 }
41 }
42
43 switch (ND->getFormalLinkage()) {
44 case Linkage::Invalid: {
45 llvm_unreachable("Shouldn't be invalid");
46 }
47 case Linkage::None:
48 return EntityLinkageType::None;
49 case Linkage::Internal:
50 return EntityLinkageType::Internal;
51 case Linkage::UniqueExternal:
52 return EntityLinkageType::Internal;
53 case Linkage::VisibleNone:
54 return EntityLinkageType::Internal;
55 case Linkage::Module:
56 return EntityLinkageType::External;
57 case Linkage::External:
58 return EntityLinkageType::External;
59 }
60 llvm_unreachable("Unhandled clang::Linkage kind");
61}
62
63std::optional<EntityId> TUSummaryExtractor::addEntity(const NamedDecl *D) {
64 auto Name = getEntityName(D);
65 if (!Name)
66 return std::nullopt;
67 return SummaryBuilder.addEntity(EN: *Name, Linkage: getLinkageForDecl(D));
68}
69
70std::optional<EntityId>
71TUSummaryExtractor::addEntityForReturn(const FunctionDecl *FD) {
72 auto Name = getEntityNameForReturn(FD);
73 if (!Name)
74 return std::nullopt;
75 return SummaryBuilder.addEntity(EN: *Name, Linkage: getLinkageForDecl(D: FD));
76}
77
78const SSAFOptions &TUSummaryExtractor::getOptions() const {
79 return SummaryBuilder.getOptions();
80}
81