Skip to content

Commit cfb89f7

Browse files
authored
Merge branch 'main' into multidim_replicated_const_composites_fix
2 parents f0ef523 + 6752415 commit cfb89f7

File tree

1,195 files changed

+61783
-23702
lines changed

Some content is hidden

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

1,195 files changed

+61783
-23702
lines changed

bolt/lib/Core/Relocation.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,15 +1018,15 @@ void Relocation::print(raw_ostream &OS) const {
10181018
OS << "RType:" << Twine::utohexstr(Type);
10191019
break;
10201020

1021-
case Triple::aarch64:
1021+
case Triple::aarch64: {
10221022
static const char *const AArch64RelocNames[] = {
10231023
#define ELF_RELOC(name, value) #name,
10241024
#include "llvm/BinaryFormat/ELFRelocs/AArch64.def"
10251025
#undef ELF_RELOC
10261026
};
10271027
assert(Type < ArrayRef(AArch64RelocNames).size());
10281028
OS << AArch64RelocNames[Type];
1029-
break;
1029+
} break;
10301030

10311031
case Triple::riscv64:
10321032
// RISC-V relocations are not sequentially numbered so we cannot use an
@@ -1043,15 +1043,15 @@ void Relocation::print(raw_ostream &OS) const {
10431043
}
10441044
break;
10451045

1046-
case Triple::x86_64:
1046+
case Triple::x86_64: {
10471047
static const char *const X86RelocNames[] = {
10481048
#define ELF_RELOC(name, value) #name,
10491049
#include "llvm/BinaryFormat/ELFRelocs/x86_64.def"
10501050
#undef ELF_RELOC
10511051
};
10521052
assert(Type < ArrayRef(X86RelocNames).size());
10531053
OS << X86RelocNames[Type];
1054-
break;
1054+
} break;
10551055
}
10561056
OS << ", 0x" << Twine::utohexstr(Offset);
10571057
if (Symbol) {

bolt/lib/Rewrite/RewriteInstance.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,20 @@ void RewriteInstance::discoverFileObjects() {
896896
continue;
897897

898898
MarkerSymType MarkerType = BC->getMarkerType(SymInfo.Symbol);
899+
900+
// Treat ST_Function as code.
901+
Expected<object::SymbolRef::Type> TypeOrError = SymInfo.Symbol.getType();
902+
consumeError(TypeOrError.takeError());
903+
if (TypeOrError && *TypeOrError == SymbolRef::ST_Function) {
904+
if (IsData) {
905+
Expected<StringRef> NameOrError = SymInfo.Symbol.getName();
906+
consumeError(NameOrError.takeError());
907+
BC->errs() << "BOLT-WARNING: function symbol " << *NameOrError
908+
<< " lacks code marker\n";
909+
}
910+
MarkerType = MarkerSymType::CODE;
911+
}
912+
899913
if (MarkerType != MarkerSymType::NONE) {
900914
SortedMarkerSymbols.push_back(MarkerSym{SymInfo.Address, MarkerType});
901915
LastAddr = SymInfo.Address;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## Check that llvm-bolt is able to recover a missing code marker.
2+
3+
# RUN: %clang %cflags %s -o %t.exe -nostdlib -fuse-ld=lld -Wl,-q
4+
# RUN: llvm-bolt %t.exe -o %t.bolt 2>&1 | FileCheck %s
5+
6+
# CHECK: BOLT-WARNING: function symbol foo lacks code marker
7+
8+
.text
9+
.balign 4
10+
11+
.word 0
12+
13+
## Function foo starts immediately after a data object and does not have
14+
## a matching "$x" symbol to indicate the start of code.
15+
.global foo
16+
.type foo, %function
17+
foo:
18+
.word 0xd65f03c0
19+
.size foo, .-foo
20+
21+
.global _start
22+
.type _start, %function
23+
_start:
24+
bl foo
25+
ret
26+
.size _start, .-_start

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "IncorrectRoundingsCheck.h"
3939
#include "InfiniteLoopCheck.h"
4040
#include "IntegerDivisionCheck.h"
41+
#include "InvalidEnumDefaultInitializationCheck.h"
4142
#include "LambdaFunctionNameCheck.h"
4243
#include "MacroParenthesesCheck.h"
4344
#include "MacroRepeatedSideEffectsCheck.h"
@@ -165,6 +166,8 @@ class BugproneModule : public ClangTidyModule {
165166
CheckFactories.registerCheck<InfiniteLoopCheck>("bugprone-infinite-loop");
166167
CheckFactories.registerCheck<IntegerDivisionCheck>(
167168
"bugprone-integer-division");
169+
CheckFactories.registerCheck<InvalidEnumDefaultInitializationCheck>(
170+
"bugprone-invalid-enum-default-initialization");
168171
CheckFactories.registerCheck<LambdaFunctionNameCheck>(
169172
"bugprone-lambda-function-name");
170173
CheckFactories.registerCheck<MacroParenthesesCheck>(

clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ add_clang_library(clangTidyBugproneModule STATIC
3030
InaccurateEraseCheck.cpp
3131
IncorrectEnableIfCheck.cpp
3232
IncorrectEnableSharedFromThisCheck.cpp
33+
InvalidEnumDefaultInitializationCheck.cpp
3334
UnintendedCharOstreamOutputCheck.cpp
3435
ReturnConstRefFromParameterCheck.cpp
3536
SuspiciousStringviewDataUsageCheck.cpp
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
//===--- InvalidEnumDefaultInitializationCheck.cpp - clang-tidy -----------===//
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 "InvalidEnumDefaultInitializationCheck.h"
10+
#include "clang/AST/ASTContext.h"
11+
#include "clang/AST/TypeVisitor.h"
12+
#include "clang/ASTMatchers/ASTMatchFinder.h"
13+
#include <algorithm>
14+
15+
using namespace clang::ast_matchers;
16+
17+
namespace clang::tidy::bugprone {
18+
19+
namespace {
20+
21+
bool isCompleteAndHasNoZeroValue(const EnumDecl *D) {
22+
const EnumDecl *Definition = D->getDefinition();
23+
return Definition && Definition->isComplete() &&
24+
!Definition->enumerators().empty() &&
25+
std::none_of(Definition->enumerator_begin(),
26+
Definition->enumerator_end(),
27+
[](const EnumConstantDecl *Value) {
28+
return Value->getInitVal().isZero();
29+
});
30+
}
31+
32+
AST_MATCHER(EnumDecl, isCompleteAndHasNoZeroValue) {
33+
return isCompleteAndHasNoZeroValue(&Node);
34+
}
35+
36+
// Find an initialization which initializes the value (if it has enum type) to a
37+
// default zero value.
38+
AST_MATCHER(Expr, isEmptyInit) {
39+
if (isa<CXXScalarValueInitExpr, ImplicitValueInitExpr>(&Node))
40+
return true;
41+
if (const auto *Init = dyn_cast<InitListExpr>(&Node)) {
42+
if (Init->getNumInits() == 0)
43+
return true;
44+
}
45+
return false;
46+
}
47+
48+
AST_MATCHER(InitListExpr, hasArrayFiller) { return Node.hasArrayFiller(); }
49+
50+
// Check if any type has a "child" type that is an enum without zero value.
51+
// The "child" type can be an array element type or member type of a record
52+
// type (or a recursive combination of these). In this case, if the "root" type
53+
// is statically initialized, the enum component is initialized to zero.
54+
class FindEnumMember : public TypeVisitor<FindEnumMember, bool> {
55+
public:
56+
const EnumType *FoundEnum = nullptr;
57+
58+
bool VisitType(const Type *T) {
59+
const Type *DesT = T->getUnqualifiedDesugaredType();
60+
if (DesT != T)
61+
return Visit(DesT);
62+
return false;
63+
}
64+
bool VisitArrayType(const ArrayType *T) {
65+
return Visit(T->getElementType().getTypePtr());
66+
}
67+
bool VisitConstantArrayType(const ConstantArrayType *T) {
68+
return Visit(T->getElementType().getTypePtr());
69+
}
70+
bool VisitEnumType(const EnumType *T) {
71+
if (isCompleteAndHasNoZeroValue(T->getDecl())) {
72+
FoundEnum = T;
73+
return true;
74+
}
75+
return false;
76+
}
77+
bool VisitRecordType(const RecordType *T) {
78+
const RecordDecl *RD = T->getDecl();
79+
if (RD->isUnion())
80+
return false;
81+
auto VisitField = [this](const FieldDecl *F) {
82+
return Visit(F->getType().getTypePtr());
83+
};
84+
return llvm::any_of(RD->fields(), VisitField);
85+
}
86+
};
87+
88+
} // namespace
89+
90+
InvalidEnumDefaultInitializationCheck::InvalidEnumDefaultInitializationCheck(
91+
StringRef Name, ClangTidyContext *Context)
92+
: ClangTidyCheck(Name, Context) {}
93+
94+
void InvalidEnumDefaultInitializationCheck::registerMatchers(
95+
MatchFinder *Finder) {
96+
auto EnumWithoutZeroValue = enumType(
97+
hasDeclaration(enumDecl(isCompleteAndHasNoZeroValue()).bind("enum")));
98+
auto EnumOrArrayOfEnum = qualType(hasUnqualifiedDesugaredType(
99+
anyOf(EnumWithoutZeroValue,
100+
arrayType(hasElementType(qualType(
101+
hasUnqualifiedDesugaredType(EnumWithoutZeroValue)))))));
102+
Finder->addMatcher(
103+
expr(isEmptyInit(), hasType(EnumOrArrayOfEnum)).bind("expr"), this);
104+
105+
// Array initialization can contain an "array filler" for the (syntactically)
106+
// unspecified elements. This expression is not found by AST matchers and can
107+
// have any type (the array's element type). This is an implicitly generated
108+
// initialization, so if the type contains somewhere an enum without zero
109+
// enumerator, the zero initialization applies here. We search this array
110+
// element type for the specific enum type manually when this matcher matches.
111+
Finder->addMatcher(initListExpr(hasArrayFiller()).bind("array_filler_expr"),
112+
this);
113+
}
114+
115+
void InvalidEnumDefaultInitializationCheck::check(
116+
const MatchFinder::MatchResult &Result) {
117+
const auto *InitExpr = Result.Nodes.getNodeAs<Expr>("expr");
118+
const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("enum");
119+
if (!InitExpr) {
120+
const auto *InitList =
121+
Result.Nodes.getNodeAs<InitListExpr>("array_filler_expr");
122+
// Initialization of omitted array elements with array filler was found.
123+
// Check the type for enum without zero value.
124+
// FIXME: In this way only one enum-typed value is found, not all of these.
125+
FindEnumMember Finder;
126+
if (!Finder.Visit(InitList->getArrayFiller()->getType().getTypePtr()))
127+
return;
128+
InitExpr = InitList;
129+
Enum = Finder.FoundEnum->getDecl();
130+
}
131+
132+
if (!InitExpr || !Enum)
133+
return;
134+
135+
ASTContext &ACtx = Enum->getASTContext();
136+
SourceLocation Loc = InitExpr->getExprLoc();
137+
if (Loc.isInvalid()) {
138+
if (isa<ImplicitValueInitExpr, InitListExpr>(InitExpr)) {
139+
DynTypedNodeList Parents = ACtx.getParents(*InitExpr);
140+
if (Parents.empty())
141+
return;
142+
143+
if (const auto *Ctor = Parents[0].get<CXXConstructorDecl>()) {
144+
// Try to find member initializer with the found expression and get the
145+
// source location from it.
146+
CXXCtorInitializer *const *CtorInit = std::find_if(
147+
Ctor->init_begin(), Ctor->init_end(),
148+
[InitExpr](const CXXCtorInitializer *Init) {
149+
return Init->isMemberInitializer() && Init->getInit() == InitExpr;
150+
});
151+
if (!CtorInit)
152+
return;
153+
Loc = (*CtorInit)->getLParenLoc();
154+
} else if (const auto *InitList = Parents[0].get<InitListExpr>()) {
155+
// The expression may be implicitly generated for an initialization.
156+
// Search for a parent initialization list with valid source location.
157+
while (InitList->getExprLoc().isInvalid()) {
158+
DynTypedNodeList Parents = ACtx.getParents(*InitList);
159+
if (Parents.empty())
160+
return;
161+
InitList = Parents[0].get<InitListExpr>();
162+
if (!InitList)
163+
return;
164+
}
165+
Loc = InitList->getExprLoc();
166+
}
167+
}
168+
// If still not found a source location, omit the warning.
169+
// Ideally all such cases (if they exist) should be handled to make the
170+
// check more precise.
171+
if (Loc.isInvalid())
172+
return;
173+
}
174+
diag(Loc, "enum value of type %0 initialized with invalid value of 0, "
175+
"enum doesn't have a zero-value enumerator")
176+
<< Enum;
177+
diag(Enum->getLocation(), "enum is defined here", DiagnosticIDs::Note);
178+
}
179+
180+
} // namespace clang::tidy::bugprone
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===--- InvalidEnumDefaultInitializationCheck.h - clang-tidy -*- 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+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INVALIDENUMDEFAULTINITIALIZATIONCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INVALIDENUMDEFAULTINITIALIZATIONCHECK_H
11+
12+
#include "../ClangTidyCheck.h"
13+
14+
namespace clang::tidy::bugprone {
15+
16+
/// Detects default initialization (to 0) of variables with `enum` type where
17+
/// the enum has no enumerator with value of 0.
18+
///
19+
/// For the user-facing documentation see:
20+
/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone/invalid-enum-default-initialization.html
21+
class InvalidEnumDefaultInitializationCheck : public ClangTidyCheck {
22+
public:
23+
InvalidEnumDefaultInitializationCheck(StringRef Name,
24+
ClangTidyContext *Context);
25+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
26+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
27+
};
28+
29+
} // namespace clang::tidy::bugprone
30+
31+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INVALIDENUMDEFAULTINITIALIZATIONCHECK_H

clang-tools-extra/clangd/FindSymbols.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "SourceCode.h"
1515
#include "index/Index.h"
1616
#include "support/Logger.h"
17+
#include "clang/AST/DeclFriend.h"
1718
#include "clang/AST/DeclTemplate.h"
1819
#include "clang/Index/IndexSymbol.h"
1920
#include "llvm/ADT/ArrayRef.h"
@@ -391,6 +392,17 @@ class DocumentOutline {
391392
D = TD;
392393
}
393394

395+
// FriendDecls don't act as DeclContexts, but they might wrap a function
396+
// definition that won't be visible through other means in the AST. Hence
397+
// unwrap it here instead.
398+
if (auto *Friend = llvm::dyn_cast<FriendDecl>(D)) {
399+
if (auto *Func =
400+
llvm::dyn_cast_or_null<FunctionDecl>(Friend->getFriendDecl())) {
401+
if (Func->isThisDeclarationADefinition())
402+
D = Func;
403+
}
404+
}
405+
394406
VisitKind Visit = shouldVisit(D);
395407
if (Visit == VisitKind::No)
396408
return;

0 commit comments

Comments
 (0)