clang 20.0.0git
CheckerHelpers.cpp
Go to the documentation of this file.
1//===---- CheckerHelpers.cpp - Helper functions for checkers ----*- 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 defines several static functions for use in checkers.
10//
11//===----------------------------------------------------------------------===//
12
14#include "clang/AST/Decl.h"
15#include "clang/AST/Expr.h"
18#include <optional>
19
20namespace clang {
21
22namespace ento {
23
24// Recursively find any substatements containing macros
25bool containsMacro(const Stmt *S) {
26 if (S->getBeginLoc().isMacroID())
27 return true;
28
29 if (S->getEndLoc().isMacroID())
30 return true;
31
32 for (const Stmt *Child : S->children())
33 if (Child && containsMacro(Child))
34 return true;
35
36 return false;
37}
38
39// Recursively find any substatements containing enum constants
40bool containsEnum(const Stmt *S) {
41 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
42
43 if (DR && isa<EnumConstantDecl>(DR->getDecl()))
44 return true;
45
46 for (const Stmt *Child : S->children())
47 if (Child && containsEnum(Child))
48 return true;
49
50 return false;
51}
52
53// Recursively find any substatements containing static vars
54bool containsStaticLocal(const Stmt *S) {
55 const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(S);
56
57 if (DR)
58 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
59 if (VD->isStaticLocal())
60 return true;
61
62 for (const Stmt *Child : S->children())
63 if (Child && containsStaticLocal(Child))
64 return true;
65
66 return false;
67}
68
69// Recursively find any substatements containing __builtin_offsetof
71 if (isa<OffsetOfExpr>(S))
72 return true;
73
74 for (const Stmt *Child : S->children())
75 if (Child && containsBuiltinOffsetOf(Child))
76 return true;
77
78 return false;
79}
80
81// Extract lhs and rhs from assignment statement
82std::pair<const clang::VarDecl *, const clang::Expr *>
84 const VarDecl *VD = nullptr;
85 const Expr *RHS = nullptr;
86
87 if (auto Assign = dyn_cast_or_null<BinaryOperator>(S)) {
88 if (Assign->isAssignmentOp()) {
89 // Ordinary assignment
90 RHS = Assign->getRHS();
91 if (auto DE = dyn_cast_or_null<DeclRefExpr>(Assign->getLHS()))
92 VD = dyn_cast_or_null<VarDecl>(DE->getDecl());
93 }
94 } else if (auto PD = dyn_cast_or_null<DeclStmt>(S)) {
95 // Initialization
96 assert(PD->isSingleDecl() && "We process decls one by one");
97 VD = cast<VarDecl>(PD->getSingleDecl());
98 RHS = VD->getAnyInitializer();
99 }
100
101 return std::make_pair(VD, RHS);
102}
103
105 const auto *AttrType = Type->getAs<AttributedType>();
106 if (!AttrType)