Skip to content

Commit 305bf48

Browse files
Merge branch 'main' into fix-delay-alu-regression
2 parents 6c7de02 + 1e45ea1 commit 305bf48

File tree

124 files changed

+1729
-742
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+1729
-742
lines changed

clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ SizeofExpressionCheck::SizeofExpressionCheck(StringRef Name,
7272
Options.get("WarnOnSizeOfPointerToAggregate", true)),
7373
WarnOnSizeOfPointer(Options.get("WarnOnSizeOfPointer", false)),
7474
WarnOnOffsetDividedBySizeOf(
75-
Options.get("WarnOnOffsetDividedBySizeOf", true)) {}
75+
Options.get("WarnOnOffsetDividedBySizeOf", true)),
76+
WarnOnSizeOfInLoopTermination(
77+
Options.get("WarnOnSizeOfInLoopTermination", true)) {}
7678

7779
void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
7880
Options.store(Opts, "WarnOnSizeOfConstant", WarnOnSizeOfConstant);
@@ -86,13 +88,22 @@ void SizeofExpressionCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
8688
Options.store(Opts, "WarnOnSizeOfPointer", WarnOnSizeOfPointer);
8789
Options.store(Opts, "WarnOnOffsetDividedBySizeOf",
8890
WarnOnOffsetDividedBySizeOf);
91+
Options.store(Opts, "WarnOnSizeOfInLoopTermination",
92+
WarnOnSizeOfInLoopTermination);
8993
}
9094

9195
void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
9296
// FIXME:
9397
// Some of the checks should not match in template code to avoid false
9498
// positives if sizeof is applied on template argument.
9599

100+
auto LoopCondExpr =
101+
[](const ast_matchers::internal::Matcher<Stmt> &InnerMatcher) {
102+
return stmt(anyOf(forStmt(hasCondition(InnerMatcher)),
103+
whileStmt(hasCondition(InnerMatcher)),
104+
doStmt(hasCondition(InnerMatcher))));
105+
};
106+
96107
const auto IntegerExpr = ignoringParenImpCasts(integerLiteral());
97108
const auto ConstantExpr = ignoringParenImpCasts(
98109
anyOf(integerLiteral(), unaryOperator(hasUnaryOperand(IntegerExpr)),
@@ -130,6 +141,14 @@ void SizeofExpressionCheck::registerMatchers(MatchFinder *Finder) {
130141
this);
131142
}
132143

144+
if (WarnOnSizeOfInLoopTermination) {
145+
auto CondExpr = binaryOperator(
146+
allOf(has(SizeOfExpr.bind("sizeof-expr")), isComparisonOperator()));
147+
Finder->addMatcher(LoopCondExpr(anyOf(CondExpr, hasDescendant(CondExpr)))
148+
.bind("loop-expr"),
149+
this);
150+
}
151+
133152
// Detect sizeof(kPtr) where kPtr is 'const char* kPtr = "abc"';
134153
const auto CharPtrType = pointerType(pointee(isAnyCharacter()));
135154
const auto ConstStrLiteralDecl =
@@ -349,6 +368,23 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
349368
diag(E->getBeginLoc(),
350369
"suspicious usage of 'sizeof(char*)'; do you mean 'strlen'?")
351370
<< E->getSourceRange();
371+
} else if (Result.Nodes.getNodeAs<Stmt>("loop-expr")) {
372+
auto *SizeofArgTy = Result.Nodes.getNodeAs<Type>("sizeof-arg-type");
373+
if (const auto member = dyn_cast<MemberPointerType>(SizeofArgTy))
374+
SizeofArgTy = member->getPointeeType().getTypePtr();
375+
376+
const auto *SzOfExpr = Result.Nodes.getNodeAs<Expr>("sizeof-expr");
377+
378+
if (const auto type = dyn_cast<ArrayType>(SizeofArgTy)) {
379+
// check if the array element size is larger than one. If true,
380+
// the size of the array is higher than the number of elements
381+
CharUnits sSize = Ctx.getTypeSizeInChars(type->getElementType());
382+
if (!sSize.isOne()) {
383+
diag(SzOfExpr->getBeginLoc(),
384+
"suspicious usage of 'sizeof' in the loop")
385+
<< SzOfExpr->getSourceRange();
386+
}
387+
}
352388
} else if (const auto *E = Result.Nodes.getNodeAs<Expr>("sizeof-pointer")) {
353389
diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
354390
"of pointer type")

clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class SizeofExpressionCheck : public ClangTidyCheck {
3232
const bool WarnOnSizeOfPointerToAggregate;
3333
const bool WarnOnSizeOfPointer;
3434
const bool WarnOnOffsetDividedBySizeOf;
35+
const bool WarnOnSizeOfInLoopTermination;
3536
};
3637

3738
} // namespace clang::tidy::bugprone

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ Changes in existing checks
173173
<clang-tidy/checks/bugprone/optional-value-conversion>` check to detect
174174
conversion in argument of ``std::make_optional``.
175175

176+
- Improved :doc: `bugprone-sizeof-expression
177+
<clang-tidy/checks/bugprone/bugprone-sizeof-expression>` check by adding
178+
`WarnOnSizeOfInLoopTermination` option to detect misuses of ``sizeof``
179+
expression in loop conditions.
180+
176181
- Improved :doc:`bugprone-string-constructor
177182
<clang-tidy/checks/bugprone/string-constructor>` check to find suspicious
178183
calls of ``std::string`` constructor with char pointer, start position and

clang-tools-extra/docs/clang-tidy/checks/bugprone/sizeof-expression.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,12 @@ Options
316316
When `true`, the check will warn on pointer arithmetic where the
317317
element count is obtained from a division with ``sizeof(...)``,
318318
e.g., ``Ptr + Bytes / sizeof(*T)``. Default is `true`.
319+
320+
.. option:: WarnOnSizeOfInLoopTermination
321+
322+
When `true`, the check will warn about incorrect use of sizeof expression
323+
in loop termination condition. The warning triggers if the ``sizeof``
324+
expression appears to be incorrectly used to determine the number of
325+
array/buffer elements.
326+
e.g, ``long arr[10]; for(int i = 0; i < sizeof(arr); i++) { ... }``. Default
327+
is `true`.

clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,69 @@ int Test2(MyConstChar* A) {
164164
return sum;
165165
}
166166

167+
struct A {
168+
int array[10];
169+
};
170+
171+
struct B {
172+
struct A a;
173+
};
174+
175+
void loop_access_elements(int num, struct B b) {
176+
struct A arr[10];
177+
char buf[20];
178+
179+
// CHECK-MESSAGES: :[[@LINE+1]]:22: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
180+
for(int i = 0; i < sizeof(arr); i++) {
181+
struct A a = arr[i];
182+
}
183+
184+
// Loop warning should not trigger here, even though this code is incorrect
185+
// CHECK-MESSAGES: :[[@LINE+2]]:22: warning: suspicious usage of 'sizeof(K)'; did you mean 'K'? [bugprone-sizeof-expression]
186+
// CHECK-MESSAGES: :[[@LINE+1]]:32: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator [bugprone-sizeof-expression]
187+
for(int i = 0; i < sizeof(10)/sizeof(A); i++) {
188+
struct A a = arr[i];
189+
}
190+
191+
// Should not warn here
192+
for(int i = 0; i < sizeof(arr)/sizeof(A); i++) {}
193+
194+
// Should not warn here
195+
for (int i = 0; i < 10; i++) {
196+
if (sizeof(arr) != 0) {
197+
198+
}
199+
}
200+
201+
for (int i = 0; i < 10; i++) {
202+
// CHECK-MESSAGES: :[[@LINE+1]]:25: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
203+
for (int j = 0; j < sizeof(arr); j++) {
204+
}
205+
}
206+
207+
// CHECK-MESSAGES: :[[@LINE+1]]:22: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
208+
for(int j = 0; j < sizeof(b.a.array); j++) {}
209+
210+
// Should not warn here
211+
for(int i = 0; i < sizeof(buf); i++) {}
212+
213+
// Should not warn here
214+
for(int i = 0; i < (sizeof(arr) << 3); i++) {}
215+
216+
int i = 0;
217+
// CHECK-MESSAGES: :[[@LINE+1]]:14: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
218+
while(i <= sizeof(arr)) {i++;}
219+
220+
i = 0;
221+
do {
222+
i++;
223+
// CHECK-MESSAGES: :[[@LINE+1]]:16: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
224+
} while(i <= sizeof(arr));
225+
226+
// CHECK-MESSAGES: :[[@LINE+1]]:29: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression]
227+
for(int i = 0, j = 0; i < sizeof(arr) && j < sizeof(buf); i++, j++) {}
228+
}
229+
167230
template <int T>
168231
int Foo() { int A[T]; return sizeof(T); }
169232
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,25 +1737,51 @@ def GetMemberOp : CIR_Op<"get_member"> {
17371737

17381738
def FuncOp : CIR_Op<"func", [
17391739
AutomaticAllocationScope, CallableOpInterface, FunctionOpInterface,
1740+
DeclareOpInterfaceMethods<CIRGlobalValueInterface>,
17401741
IsolatedFromAbove
17411742
]> {
17421743
let summary = "Declare or define a function";
17431744
let description = [{
17441745
The `cir.func` operation defines a function, similar to the `mlir::FuncOp`
17451746
built-in.
1747+
1748+
The function linkage information is specified by `linkage`, as defined by
1749+
`GlobalLinkageKind` attribute.
1750+
1751+
Example:
1752+
1753+
```mlir
1754+
// External function definitions.
1755+
cir.func @abort()
1756+
1757+
// A function with internal linkage.
1758+
cir.func internal @count(%x: i64) -> (i64)
1759+
return %x : i64
1760+
1761+
// Linkage information
1762+
cir.func linkonce_odr @some_method(...)
1763+
```
17461764
}];
17471765

17481766
let arguments = (ins SymbolNameAttr:$sym_name,
1767+
CIR_VisibilityAttr:$global_visibility,
17491768
TypeAttrOf<CIR_FuncType>:$function_type,
1769+
UnitAttr:$dso_local,
1770+
DefaultValuedAttr<CIR_GlobalLinkageKind,
1771+
"cir::GlobalLinkageKind::ExternalLinkage">:$linkage,
1772+
OptionalAttr<StrAttr>:$sym_visibility,
1773+
UnitAttr:$comdat,
17501774
OptionalAttr<DictArrayAttr>:$arg_attrs,
17511775
OptionalAttr<DictArrayAttr>:$res_attrs);
17521776

17531777
let regions = (region AnyRegion:$body);
17541778

17551779
let skipDefaultBuilders = 1;
17561780

1757-
let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
1758-
"FuncType":$type)>];
1781+
let builders = [OpBuilder<(ins
1782+
"llvm::StringRef":$sym_name, "FuncType":$type,
1783+
CArg<"cir::GlobalLinkageKind", "cir::GlobalLinkageKind::ExternalLinkage">:$linkage)
1784+
>];
17591785

17601786
let extraClassDeclaration = [{
17611787
/// Returns the region on the current operation that is callable. This may
@@ -2371,6 +2397,64 @@ def ComplexCreateOp : CIR_Op<"complex.create", [Pure, SameTypeOperands]> {
23712397
let hasFolder = 1;
23722398
}
23732399

2400+
//===----------------------------------------------------------------------===//
2401+
// ComplexRealOp
2402+
//===----------------------------------------------------------------------===//
2403+
2404+
def ComplexRealOp : CIR_Op<"complex.real", [Pure]> {
2405+
let summary = "Extract the real part of a complex value";
2406+
let description = [{
2407+
`cir.complex.real` operation takes an operand of `!cir.complex` type and
2408+
yields the real part of it.
2409+
2410+
Example:
2411+
2412+
```mlir
2413+
%1 = cir.complex.real %0 : !cir.complex<!cir.float> -> !cir.float
2414+
```
2415+
}];
2416+
2417+
let results = (outs CIR_AnyIntOrFloatType:$result);
2418+
let arguments = (ins CIR_ComplexType:$operand);
2419+
2420+
let assemblyFormat = [{
2421+
$operand `:` qualified(type($operand)) `->` qualified(type($result))
2422+
attr-dict
2423+
}];
2424+
2425+
let hasVerifier = 1;
2426+
let hasFolder = 1;
2427+
}
2428+
2429+
//===----------------------------------------------------------------------===//
2430+
// ComplexImagOp
2431+
//===----------------------------------------------------------------------===//
2432+
2433+
def ComplexImagOp : CIR_Op<"complex.imag", [Pure]> {
2434+
let summary = "Extract the imaginary part of a complex value";
2435+
let description = [{
2436+
`cir.complex.imag` operation takes an operand of `!cir.complex` type and
2437+
yields the imaginary part of it.
2438+
2439+
Example:
2440+
2441+
```mlir
2442+
%1 = cir.complex.imag %0 : !cir.complex<!cir.float> -> !cir.float
2443+
```
2444+
}];
2445+
2446+
let results = (outs CIR_AnyIntOrFloatType:$result);
2447+
let arguments = (ins CIR_ComplexType:$operand);
2448+
2449+
let assemblyFormat = [{
2450+
$operand `:` qualified(type($operand)) `->` qualified(type($result))
2451+
attr-dict
2452+
}];
2453+
2454+
let hasVerifier = 1;
2455+
let hasFolder = 1;
2456+
}
2457+
23742458
//===----------------------------------------------------------------------===//
23752459
// Assume Operations
23762460
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,18 @@ struct MissingFeatures {
7272

7373
// FuncOp handling
7474
static bool opFuncOpenCLKernelMetadata() { return false; }
75+
static bool opFuncAstDeclAttr() { return false; }
7576
static bool opFuncCallingConv() { return false; }
7677
static bool opFuncExtraAttrs() { return false; }
77-
static bool opFuncDsoLocal() { return false; }
78-
static bool opFuncLinkage() { return false; }
79-
static bool opFuncVisibility() { return false; }
8078
static bool opFuncNoProto() { return false; }
8179
static bool opFuncCPUAndFeaturesAttributes() { return false; }
8280
static bool opFuncSection() { return false; }
83-
static bool opFuncSetComdat() { return false; }
81+
static bool opFuncMultipleReturnVals() { return false; }
8482
static bool opFuncAttributesForDefinition() { return false; }
83+
static bool opFuncMaybeHandleStaticInExternC() { return false; }
84+
static bool opFuncGlobalAliases() { return false; }
85+
static bool setLLVMFunctionFEnvAttributes() { return false; }
86+
static bool setFunctionAttributes() { return false; }
8587

8688
// CallOp handling
8789
static bool opCallPseudoDtor() { return false; }

clang/include/clang/Lex/Preprocessor.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,7 +2304,9 @@ class Preprocessor {
23042304

23052305
/// Check whether the next pp-token is one of the specificed token kind. this
23062306
/// method should have no observable side-effect on the lexed tokens.
2307-
template <tok::TokenKind K, tok::TokenKind... Ks> bool isNextPPTokenOneOf() {
2307+
template <typename... Ts> bool isNextPPTokenOneOf(Ts... Ks) {
2308+
static_assert(sizeof...(Ts) > 0,
2309+
"requires at least one tok::TokenKind specified");
23082310
// Do some quick tests for rejection cases.
23092311
std::optional<Token> Val;
23102312
if (CurLexer)
@@ -2335,7 +2337,7 @@ class Preprocessor {
23352337

23362338
// Okay, we found the token and return. Otherwise we found the end of the
23372339
// translation unit.
2338-
return Val->is(K) || (... || Val->is(Ks));
2340+
return Val->isOneOf(Ks...);
23392341
}
23402342

23412343
private:

clang/include/clang/Lex/Token.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,10 @@ class Token {
101101
/// "if (Tok.is(tok::l_brace)) {...}".
102102
bool is(tok::TokenKind K) const { return Kind == K; }
103103
bool isNot(tok::TokenKind K) const { return Kind != K; }
104-
bool isOneOf(tok::TokenKind K1, tok::TokenKind K2) const {
105-
return is(K1) || is(K2);
106-
}
107-
template <typename... Ts> bool isOneOf(tok::TokenKind K1, Ts... Ks) const {
108-
return is(K1) || isOneOf(Ks...);
104+
template <typename... Ts> bool isOneOf(Ts... Ks) const {
105+
static_assert(sizeof...(Ts) > 0,
106+
"requires at least one tok::TokenKind specified");
107+
return (is(Ks) || ...);
109108
}
110109

111110
/// Return true if this is a raw identifier (when lexing

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,16 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
366366
return create<cir::ComplexCreateOp>(loc, resultComplexTy, real, imag);
367367
}
368368

369+
mlir::Value createComplexReal(mlir::Location loc, mlir::Value operand) {
370+
auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
371+
return create<cir::ComplexRealOp>(loc, operandTy.getElementType(), operand);
372+
}
373+
374+
mlir::Value createComplexImag(mlir::Location loc, mlir::Value operand) {
375+
auto operandTy = mlir::cast<cir::ComplexType>(operand.getType());
376+
return create<cir::ComplexImagOp>(loc, operandTy.getElementType(), operand);
377+
}
378+
369379
/// Create a cir.ptr_stride operation to get access to an array element.
370380
/// \p idx is the index of the element to access, \p shouldDecay is true if
371381
/// the result should decay to a pointer to the element type.

clang/lib/CIR/CodeGen/CIRGenCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ cir::FuncOp CIRGenModule::codegenCXXStructor(GlobalDecl gd) {
2525
cir::FuncType funcType = getTypes().getFunctionType(fnInfo);
2626
cir::FuncOp fn = getAddrOfCXXStructor(gd, &fnInfo, /*FnType=*/nullptr,
2727
/*DontDefer=*/true, ForDefinition);
28-
assert(!cir::MissingFeatures::opFuncLinkage());
28+
setFunctionLinkage(gd, fn);
2929
CIRGenFunction cgf{*this, builder};
3030
curCGF = &cgf;
3131
{

0 commit comments

Comments
 (0)