2323#include " clang/StaticAnalyzer/Core/CheckerManager.h"
2424#include " clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
2525#include " llvm/ADT/SmallString.h"
26- #include " llvm/CHERI/CompressedCapability .h"
26+ #include " llvm/CHERI/CapabilityFormat .h"
2727#include " llvm/Support/raw_ostream.h"
2828
2929using namespace clang ;
3030using namespace ento ;
3131
3232namespace {
3333
34- template <llvm::CompressedCapability::CapabilityFormat>
35- std::unique_ptr<BugReport> checkFieldImpl ( const FieldDecl *D, BugReporter &BR ,
36- const BugType &BT );
34+ std::unique_ptr<BugReport> checkField ( const FieldDecl *D, BugReporter &BR,
35+ const BugType &BT ,
36+ llvm::CHERICapabilityFormat CapFormat );
3737
3838class SubObjectRepresentabilityChecker
3939 : public Checker<check::ASTDecl<RecordDecl>, check::ASTCodeBody> {
@@ -49,11 +49,8 @@ class SubObjectRepresentabilityChecker
4949 BugReporter &BR) const ;
5050
5151private:
52- using CheckFieldFn = std::unique_ptr<BugReport> (*)(const FieldDecl *D,
53- BugReporter &BR,
54- const BugType &BT);
55-
56- CheckFieldFn getCheckFieldFn (ASTContext &ASTCtx) const ;
52+ std::optional<llvm::CHERICapabilityFormat>
53+ getCapabilityFormat (ASTContext &ASTCtx) const ;
5754};
5855
5956} // namespace
@@ -97,9 +94,9 @@ reportExposedFields(const FieldDecl *D, ASTContext &ASTCtx, BugReporter &BR,
9794 return Report;
9895}
9996
100- template <llvm::CompressedCapability::CapabilityFormat CapFormat>
101- std::unique_ptr<BugReport> checkFieldImpl ( const FieldDecl *D, BugReporter &BR ,
102- const BugType &BT ) {
97+ std::unique_ptr<BugReport> checkField ( const FieldDecl *D, BugReporter &BR,
98+ const BugType &BT ,
99+ llvm::CHERICapabilityFormat CapFormat ) {
103100 QualType T = D->getType ();
104101
105102 // If the parent struct is explicitly marked as packed, then don't emit a
@@ -111,9 +108,7 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D, BugReporter &BR,
111108 uint64_t Offset = ASTCtx.getFieldOffset (D) / 8 ;
112109 if (Offset > 0 ) {
113110 uint64_t Size = ASTCtx.getTypeSize (T) / 8 ;
114- uint64_t ReqAlign =
115- llvm::CompressedCapability::GetRequiredAlignment (Size, CapFormat)
116- .value ();
111+ uint64_t ReqAlign = CapFormat.getRequiredAlignment (Size).value ();
117112 uint64_t CurAlign = 1 << llvm::countr_zero (Offset);
118113 if (CurAlign < ReqAlign) {
119114 /* Emit warning */
@@ -131,9 +126,8 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D, BugReporter &BR,
131126 uint64_t OffsetToAlign = Offset % ReqAlign;
132127 uint64_t Base = Offset - OffsetToAlign;
133128 uint64_t AlignedSize = Size + OffsetToAlign;
134- uint64_t TailPadding = static_cast <uint64_t >(
135- llvm::CompressedCapability::GetRequiredTailPadding (AlignedSize,
136- CapFormat));
129+ uint64_t TailPadding =
130+ static_cast <uint64_t >(CapFormat.getRequiredTailPadding (AlignedSize));
137131 uint64_t Top = Base + AlignedSize + TailPadding;
138132 OS << " Current bounds: " << Base << " -" << Top;
139133
@@ -156,40 +150,40 @@ std::unique_ptr<BugReport> checkFieldImpl(const FieldDecl *D, BugReporter &BR,
156150
157151} // namespace
158152
159- SubObjectRepresentabilityChecker::CheckFieldFn
160- SubObjectRepresentabilityChecker::getCheckFieldFn (ASTContext &ASTCtx) const {
153+ std::optional<llvm::CHERICapabilityFormat>
154+ SubObjectRepresentabilityChecker::getCapabilityFormat (
155+ ASTContext &ASTCtx) const {
161156 const TargetInfo &TI = ASTCtx.getTargetInfo ();
162157 if (!TI.areAllPointersCapabilities ())
163- return nullptr ;
158+ return std:: nullopt ;
164159
165160 const auto &T = TI.getTriple ();
166161 if (T.getArch () == llvm::Triple::riscv32 && TI.hasFeature (" xcheriot" )) {
167- return &checkFieldImpl< llvm::CompressedCapability ::Cheriot64> ;
162+ return llvm::CHERICapabilityFormat ::Cheriot64;
168163 }
169164
170- static constexpr std::array CheckFieldFnMap = {
171- std::make_pair (llvm::Triple::mips,
172- &checkFieldImpl<llvm::CompressedCapability::Cheri64>),
165+ static constexpr std::array CapabilityFormatMap = {
166+ std::make_pair (llvm::Triple::mips, &llvm::CHERICapabilityFormat::Cheri64),
173167 std::make_pair (llvm::Triple::mips64,
174- &checkFieldImpl< llvm::CompressedCapability ::Cheri128> ),
168+ &llvm::CHERICapabilityFormat ::Cheri128),
175169 std::make_pair (llvm::Triple::riscv32,
176- &checkFieldImpl< llvm::CompressedCapability ::Cheri64> ),
170+ &llvm::CHERICapabilityFormat ::Cheri64),
177171 std::make_pair (llvm::Triple::riscv64,
178- &checkFieldImpl< llvm::CompressedCapability ::Cheri128> ),
172+ &llvm::CHERICapabilityFormat ::Cheri128),
179173 };
180174
181- auto It = std::find_if (CheckFieldFnMap .begin (), CheckFieldFnMap .end (),
175+ auto It = std::find_if (CapabilityFormatMap .begin (), CapabilityFormatMap .end (),
182176 [A = T.getArch ()](auto p) { return p.first == A; });
183- if (It == CheckFieldFnMap .end ())
184- return nullptr ;
185- return It->second ;
177+ if (It == CapabilityFormatMap .end ())
178+ return std:: nullopt ;
179+ return * It->second ;
186180}
187181
188182void SubObjectRepresentabilityChecker::checkASTDecl (const RecordDecl *R,
189183 AnalysisManager &mgr,
190184 BugReporter &BR) const {
191- CheckFieldFn checkField = getCheckFieldFn (mgr.getASTContext ());
192- if (!checkField )
185+ auto CapFormat = getCapabilityFormat (mgr.getASTContext ());
186+ if (!CapFormat )
193187 return ; // skip this target
194188
195189 if (!R->isCompleteDefinition () || R->isDependentType ())
@@ -199,7 +193,7 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
199193 return ;
200194
201195 for (FieldDecl *D : R->fields ()) {
202- auto Report = checkField (D, BR, BT_1);
196+ auto Report = checkField (D, BR, BT_1, *CapFormat );
203197 if (Report)
204198 BR.emitReport (std::move (Report));
205199 }
@@ -208,8 +202,8 @@ void SubObjectRepresentabilityChecker::checkASTDecl(const RecordDecl *R,
208202void SubObjectRepresentabilityChecker::checkASTCodeBody (const Decl *D,
209203 AnalysisManager &mgr,
210204 BugReporter &BR) const {
211- CheckFieldFn checkField = getCheckFieldFn (mgr.getASTContext ());
212- if (!checkField )
205+ auto CapFormat = getCapabilityFormat (mgr.getASTContext ());
206+ if (!CapFormat )
213207 return ; // skip this target
214208
215209 using namespace ast_matchers ;
@@ -228,7 +222,7 @@ void SubObjectRepresentabilityChecker::checkASTCodeBody(const Decl *D,
228222 if (const MemberExpr *ME = Match.getNodeAs <MemberExpr>(" member" )) {
229223 ValueDecl *VD = ME->getMemberDecl ();
230224 if (FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
231- auto Report = checkField (FD, BR, BT_2);
225+ auto Report = checkField (FD, BR, BT_2, *CapFormat );
232226 if (Report) {
233227 PathDiagnosticLocation LN = PathDiagnosticLocation::createBegin (
234228 CE, BR.getSourceManager (), mgr.getAnalysisDeclContext (D));
@@ -242,7 +236,7 @@ void SubObjectRepresentabilityChecker::checkASTCodeBody(const Decl *D,
242236 if (const MemberExpr *ME = Match.getNodeAs <MemberExpr>(" member" )) {
243237 ValueDecl *VD = ME->getMemberDecl ();
244238 if (FieldDecl *FD = dyn_cast<FieldDecl>(VD)) {
245- auto Report = checkField (FD, BR, BT_2);
239+ auto Report = checkField (FD, BR, BT_2, *CapFormat );
246240 if (Report) {
247241 PathDiagnosticLocation LN = PathDiagnosticLocation::createBegin (
248242 UO, BR.getSourceManager (), mgr.getAnalysisDeclContext (D));
0 commit comments