14 changes: 13 additions & 1 deletion bolt/test/X86/bolt-address-translation-yaml.test
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ RUN: | FileCheck --check-prefix CHECK-BOLT-YAML %s

WRITE-BAT-CHECK: BOLT-INFO: Wrote 5 BAT maps
WRITE-BAT-CHECK: BOLT-INFO: Wrote 4 function and 22 basic block hashes
WRITE-BAT-CHECK: BOLT-INFO: BAT section size (bytes): 380
WRITE-BAT-CHECK: BOLT-INFO: BAT section size (bytes): 384

READ-BAT-CHECK-NOT: BOLT-ERROR: unable to save profile in YAML format for input file processed by BOLT
READ-BAT-CHECK: BOLT-INFO: Parsed 5 BAT entries
Expand All @@ -36,6 +36,18 @@ YAML-BAT-CHECK-NEXT: - bid: 0
YAML-BAT-CHECK-NEXT: insns: 26
YAML-BAT-CHECK-NEXT: hash: 0xA900AE79CFD40000
YAML-BAT-CHECK-NEXT: succ: [ { bid: 3, cnt: 0 }, { bid: 1, cnt: 0 } ]
# Function covered by BAT with calls
YAML-BAT-CHECK: - name: SolveCubic
YAML-BAT-CHECK-NEXT: fid: [[#]]
YAML-BAT-CHECK-NEXT: hash: 0x6AF7E61EA3966722
YAML-BAT-CHECK-NEXT: exec: 25
YAML-BAT-CHECK-NEXT: nblocks: 15
YAML-BAT-CHECK-NEXT: blocks:
YAML-BAT-CHECK: - bid: 3
YAML-BAT-CHECK-NEXT: insns: [[#]]
YAML-BAT-CHECK-NEXT: hash: 0xDDA1DC5F69F900AC
YAML-BAT-CHECK-NEXT: calls: [ { off: 0x26, fid: [[#]], cnt: [[#]] } ]
YAML-BAT-CHECK-NEXT: succ: [ { bid: 5, cnt: [[#]] }
# Function covered by BAT - doesn't have insns in basic block
YAML-BAT-CHECK: - name: usqrt
YAML-BAT-CHECK-NEXT: fid: [[#]]
Expand Down
2 changes: 1 addition & 1 deletion bolt/test/X86/bolt-address-translation.test
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
# CHECK: BOLT: 3 out of 7 functions were overwritten.
# CHECK: BOLT-INFO: Wrote 6 BAT maps
# CHECK: BOLT-INFO: Wrote 3 function and 58 basic block hashes
# CHECK: BOLT-INFO: BAT section size (bytes): 920
# CHECK: BOLT-INFO: BAT section size (bytes): 924
#
# usqrt mappings (hot part). We match against any key (left side containing
# the bolted binary offsets) because BOLT may change where it puts instructions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) {
anyOf(binaryOperator(anyOf(isComparisonOperator(), isLogicalOperator())),
cxxOperatorCallExpr(isComparisonOperator())));

auto IsInUnevaluatedContext =
expr(anyOf(hasAncestor(expr(matchers::hasUnevaluatedContext())),
hasAncestor(typeLoc())));

Finder->addMatcher(
expr(
OperatorMatcher, unless(isExpansionInSystemHeader()),
Expand All @@ -42,12 +46,14 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) {
cxxOperatorCallExpr(
isPrePostOperator(),
hasUnaryOperand(expr().bind("operand")))),
unless(IsInUnevaluatedContext),
hasAncestor(
expr(equalsBoundNode("parent"),
hasDescendant(
expr(unless(equalsBoundNode("operand")),
matchers::isStatementIdenticalToBoundNode(
"operand"))
"operand"),
unless(IsInUnevaluatedContext))
.bind("second")))))
.bind("operator"))),
this);
Expand Down
41 changes: 33 additions & 8 deletions clang-tools-extra/clang-tidy/google/IntegerTypesCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,34 @@ namespace {
AST_MATCHER(FunctionDecl, isUserDefineLiteral) {
return Node.getLiteralIdentifier() != nullptr;
}

AST_MATCHER(TypeLoc, isValidAndNotInMacro) {
const SourceLocation Loc = Node.getBeginLoc();
return Loc.isValid() && !Loc.isMacroID();
}

AST_MATCHER(TypeLoc, isBuiltinType) {
TypeLoc TL = Node;
if (auto QualLoc = Node.getAs<QualifiedTypeLoc>())
TL = QualLoc.getUnqualifiedLoc();

const auto BuiltinLoc = TL.getAs<BuiltinTypeLoc>();
if (!BuiltinLoc)
return false;

switch (BuiltinLoc.getTypePtr()->getKind()) {
case BuiltinType::Short:
case BuiltinType::Long:
case BuiltinType::LongLong:
case BuiltinType::UShort:
case BuiltinType::ULong:
case BuiltinType::ULongLong:
return true;
default:
return false;
}
}

} // namespace

namespace tidy::google::runtime {
Expand All @@ -63,11 +91,11 @@ void IntegerTypesCheck::registerMatchers(MatchFinder *Finder) {
// "Where possible, avoid passing arguments of types specified by
// bitwidth typedefs to printf-based APIs."
Finder->addMatcher(
typeLoc(loc(isInteger()),
unless(anyOf(hasAncestor(callExpr(
callee(functionDecl(hasAttr(attr::Format))))),
hasParent(parmVarDecl(hasAncestor(
functionDecl(isUserDefineLiteral())))))))
typeLoc(loc(isInteger()), isValidAndNotInMacro(), isBuiltinType(),
unless(hasAncestor(
callExpr(callee(functionDecl(hasAttr(attr::Format)))))),
unless(hasParent(parmVarDecl(
hasAncestor(functionDecl(isUserDefineLiteral()))))))
.bind("tl"),
this);
IdentTable = std::make_unique<IdentifierTable>(getLangOpts());
Expand All @@ -77,9 +105,6 @@ void IntegerTypesCheck::check(const MatchFinder::MatchResult &Result) {
auto TL = *Result.Nodes.getNodeAs<TypeLoc>("tl");
SourceLocation Loc = TL.getBeginLoc();

if (Loc.isInvalid() || Loc.isMacroID())
return;

// Look through qualification.
if (auto QualLoc = TL.getAs<QualifiedTypeLoc>())
TL = QualLoc.getUnqualifiedLoc();
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/google/IntegerTypesCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ class IntegerTypesCheck : public ClangTidyCheck {
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
}

private:
const StringRef UnsignedTypePrefix;
Expand Down
24 changes: 21 additions & 3 deletions clang-tools-extra/clang-tidy/modernize/UseUsingCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "UseUsingCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Lex/Lexer.h"

using namespace clang::ast_matchers;
Expand All @@ -24,6 +25,7 @@ static constexpr llvm::StringLiteral ExternCDeclName = "extern-c-decl";
static constexpr llvm::StringLiteral ParentDeclName = "parent-decl";
static constexpr llvm::StringLiteral TagDeclName = "tag-decl";
static constexpr llvm::StringLiteral TypedefName = "typedef";
static constexpr llvm::StringLiteral DeclStmtName = "decl-stmt";

UseUsingCheck::UseUsingCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
Expand All @@ -41,7 +43,8 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
unless(isInstantiated()),
optionally(hasAncestor(
linkageSpecDecl(isExternCLinkage()).bind(ExternCDeclName))),
hasParent(decl().bind(ParentDeclName)))
anyOf(hasParent(decl().bind(ParentDeclName)),
hasParent(declStmt().bind(DeclStmtName))))
.bind(TypedefName),
this);

Expand All @@ -51,17 +54,32 @@ void UseUsingCheck::registerMatchers(MatchFinder *Finder) {
tagDecl(
anyOf(allOf(unless(anyOf(isImplicit(),
classTemplateSpecializationDecl())),
hasParent(decl().bind(ParentDeclName))),
anyOf(hasParent(decl().bind(ParentDeclName)),
hasParent(declStmt().bind(DeclStmtName)))),
// We want the parent of the ClassTemplateDecl, not the parent
// of the specialization.
classTemplateSpecializationDecl(hasAncestor(classTemplateDecl(
hasParent(decl().bind(ParentDeclName)))))))
anyOf(hasParent(decl().bind(ParentDeclName)),
hasParent(declStmt().bind(DeclStmtName))))))))
.bind(TagDeclName),
this);
}

void UseUsingCheck::check(const MatchFinder::MatchResult &Result) {
const auto *ParentDecl = Result.Nodes.getNodeAs<Decl>(ParentDeclName);

if (!ParentDecl) {
const auto *ParentDeclStmt = Result.Nodes.getNodeAs<DeclStmt>(DeclStmtName);
if (ParentDeclStmt) {
if (ParentDeclStmt->isSingleDecl())
ParentDecl = ParentDeclStmt->getSingleDecl();
else
ParentDecl =
ParentDeclStmt->getDeclGroup().getDeclGroup()
[ParentDeclStmt->getDeclGroup().getDeclGroup().size() - 1];
}
}

if (!ParentDecl)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ class StaticDefinitionInAnonymousNamespaceCheck : public ClangTidyCheck {
: ClangTidyCheck(Name, Context) {}
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
std::optional<TraversalKind> getCheckTraversalKind() const override {
return TK_IgnoreUnlessSpelledInSource;
}
};

} // namespace clang::tidy::readability
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/ClangdLSPServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1390,7 +1390,7 @@ void ClangdLSPServer::onClangdInlayHints(const InlayHintsParams &Params,
// Extension doesn't have paddingLeft/Right so adjust the label
// accordingly.
{"label",
((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.label) +
((Hint.paddingLeft ? " " : "") + llvm::StringRef(Hint.joinLabels()) +
(Hint.paddingRight ? " " : ""))
.str()},
});
Expand Down
5 changes: 3 additions & 2 deletions clang-tools-extra/clangd/InlayHints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -977,8 +977,9 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
return;
bool PadLeft = Prefix.consume_front(" ");
bool PadRight = Suffix.consume_back(" ");
Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind,
PadLeft, PadRight, LSPRange});
Results.push_back(InlayHint{LSPPos,
/*label=*/{(Prefix + Label + Suffix).str()},
Kind, PadLeft, PadRight, LSPRange});
}

// Get the range of the main file that *exactly* corresponds to R.
Expand Down
31 changes: 31 additions & 0 deletions clang-tools-extra/clangd/Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,10 @@ bool operator<(const InlayHint &A, const InlayHint &B) {
return std::tie(A.position, A.range, A.kind, A.label) <
std::tie(B.position, B.range, B.kind, B.label);
}
std::string InlayHint::joinLabels() const {
return llvm::join(llvm::map_range(label, [](auto &L) { return L.value; }),
"");
}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) {
auto ToString = [](InlayHintKind K) {
Expand All @@ -1519,6 +1523,33 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, InlayHintKind Kind) {
return OS << ToString(Kind);
}

llvm::json::Value toJSON(const InlayHintLabelPart &L) {
llvm::json::Object Result{{"value", L.value}};
if (L.tooltip)
Result["tooltip"] = *L.tooltip;
if (L.location)
Result["location"] = *L.location;
if (L.command)
Result["command"] = *L.command;
return Result;
}

bool operator==(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) {
return std::tie(LHS.value, LHS.location) == std::tie(RHS.value, RHS.location);
}

bool operator<(const InlayHintLabelPart &LHS, const InlayHintLabelPart &RHS) {
return std::tie(LHS.value, LHS.location) < std::tie(RHS.value, RHS.location);
}

llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
const InlayHintLabelPart &L) {
OS << L.value;
if (L.location)
OS << " (" << L.location << ")";
return OS;
}

static const char *toString(OffsetEncoding OE) {
switch (OE) {
case OffsetEncoding::UTF8:
Expand Down
47 changes: 46 additions & 1 deletion clang-tools-extra/clangd/Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,48 @@ enum class InlayHintKind {
};
llvm::json::Value toJSON(const InlayHintKind &);

/// An inlay hint label part allows for interactive and composite labels
/// of inlay hints.
struct InlayHintLabelPart {

InlayHintLabelPart() = default;

InlayHintLabelPart(std::string value,
std::optional<Location> location = std::nullopt)
: value(std::move(value)), location(std::move(location)) {}

/// The value of this label part.
std::string value;

/// The tooltip text when you hover over this label part. Depending on
/// the client capability `inlayHint.resolveSupport`, clients might resolve
/// this property late using the resolve request.
std::optional<MarkupContent> tooltip;

/// An optional source code location that represents this
/// label part.
///
/// The editor will use this location for the hover and for code navigation
/// features: This part will become a clickable link that resolves to the
/// definition of the symbol at the given location (not necessarily the
/// location itself), it shows the hover that shows at the given location,
/// and it shows a context menu with further code navigation commands.
///
/// Depending on the client capability `inlayHint.resolveSupport` clients
/// might resolve this property late using the resolve request.
std::optional<Location> location;

/// An optional command for this label part.
///
/// Depending on the client capability `inlayHint.resolveSupport` clients
/// might resolve this property late using the resolve request.
std::optional<Command> command;
};
llvm::json::Value toJSON(const InlayHintLabelPart &);
bool operator==(const InlayHintLabelPart &, const InlayHintLabelPart &);
bool operator<(const InlayHintLabelPart &, const InlayHintLabelPart &);
llvm::raw_ostream &operator<<(llvm::raw_ostream &, const InlayHintLabelPart &);

/// Inlay hint information.
struct InlayHint {
/// The position of this hint.
Expand All @@ -1698,7 +1740,7 @@ struct InlayHint {
/// InlayHintLabelPart label parts.
///
/// *Note* that neither the string nor the label part can be empty.
std::string label;
std::vector<InlayHintLabelPart> label;

/// The kind of this hint. Can be omitted in which case the client should fall
/// back to a reasonable default.
Expand All @@ -1724,6 +1766,9 @@ struct InlayHint {
/// The range allows clients more flexibility of when/how to display the hint.
/// This is an (unserialized) clangd extension.
Range range;

/// Join the label[].value together.
std::string joinLabels() const;
};
llvm::json::Value toJSON(const InlayHint &);
bool operator==(const InlayHint &, const InlayHint &);
Expand Down
6 changes: 5 additions & 1 deletion clang-tools-extra/clangd/test/inlayHints.test
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@
# CHECK-NEXT: "result": [
# CHECK-NEXT: {
# CHECK-NEXT: "kind": 2,
# CHECK-NEXT: "label": "bar:",
# CHECK-NEXT: "label": [
# CHECK-NEXT: {
# CHECK-NEXT: "value": "bar:"
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "paddingLeft": false,
# CHECK-NEXT: "paddingRight": true,
# CHECK-NEXT: "position": {
Expand Down
8 changes: 7 additions & 1 deletion clang-tools-extra/clangd/tool/Check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,13 @@ class Checker {
auto Hints = inlayHints(*AST, LineRange);

for (const auto &Hint : Hints) {
vlog(" {0} {1} {2}", Hint.kind, Hint.position, Hint.label);
vlog(" {0} {1} [{2}]", Hint.kind, Hint.position, [&] {
return llvm::join(llvm::map_range(Hint.label,
[&](auto &L) {
return llvm::formatv("{{{0}}", L);
}),
", ");
}());
}
}

Expand Down
9 changes: 5 additions & 4 deletions clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace clangd {

llvm::raw_ostream &operator<<(llvm::raw_ostream &Stream,
const InlayHint &Hint) {
return Stream << Hint.label << "@" << Hint.range;
return Stream << Hint.joinLabels() << "@" << Hint.range;
}

namespace {
Expand Down Expand Up @@ -57,10 +57,11 @@ struct ExpectedHint {

MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) {
llvm::StringRef ExpectedView(Expected.Label);
if (arg.label != ExpectedView.trim(" ") ||
std::string ResultLabel = arg.joinLabels();
if (ResultLabel != ExpectedView.trim(" ") ||
arg.paddingLeft != ExpectedView.starts_with(" ") ||
arg.paddingRight != ExpectedView.ends_with(" ")) {
*result_listener << "label is '" << arg.label << "'";
*result_listener << "label is '" << ResultLabel << "'";
return false;
}
if (arg.range != Code.range(Expected.RangeName)) {
Expand All @@ -72,7 +73,7 @@ MATCHER_P2(HintMatcher, Expected, Code, llvm::to_string(Expected)) {
return true;
}

MATCHER_P(labelIs, Label, "") { return arg.label == Label; }
MATCHER_P(labelIs, Label, "") { return arg.joinLabels() == Label; }

Config noHintsConfig() {
Config C;
Expand Down
35 changes: 25 additions & 10 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ Changes in existing checks
<clang-tidy/checks/bugprone/assert-side-effect>` check by detecting side
effect from calling a method with non-const reference parameters.

- Improved :doc:`bugprone-inc-dec-in-conditions
<clang-tidy/checks/bugprone/inc-dec-in-conditions>` check to ignore code
within unevaluated contexts, such as ``decltype``.

- Improved :doc:`bugprone-non-zero-enum-to-bool-conversion
<clang-tidy/checks/bugprone/non-zero-enum-to-bool-conversion>` check by
eliminating false positives resulting from direct usage of bitwise operators
Expand Down Expand Up @@ -176,13 +180,13 @@ Changes in existing checks
<clang-tidy/checks/cppcoreguidelines/owning-memory>` check to properly handle
return type in lambdas and in nested functions.

- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>`
- Improved :doc:`cppcoreguidelines-prefer-member-initializer
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>` check
by removing enforcement of rule `C.48
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c48-prefer-in-class-initializers-to-member-initializers-in-constructors-for-constant-initializers>`_,
which was deprecated since :program:`clang-tidy` 17. This rule is now covered
by :doc:`cppcoreguidelines-use-default-member-init
<clang-tidy/checks/cppcoreguidelines/use-default-member-init>` and fixes
<clang-tidy/checks/cppcoreguidelines/use-default-member-init>`. Fixed
incorrect hints when using list-initialization.

- Improved :doc:`google-build-namespaces
Expand All @@ -197,6 +201,9 @@ Changes in existing checks
<clang-tidy/checks/google/global-names-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`google-runtime-int <clang-tidy/checks/google/runtime-int>`
check performance through optimizations.

- Improved :doc:`llvm-header-guard
<clang-tidy/checks/llvm/header-guard>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.
Expand Down Expand Up @@ -229,12 +236,20 @@ Changes in existing checks
<clang-tidy/checks/modernize/use-override>` check to also remove any trailing
whitespace when deleting the ``virtual`` keyword.

- Improved :doc:`modernize-use-using <clang-tidy/checks/modernize/use-using>`
check by adding support for detection of typedefs declared on function level.

- Improved :doc:`performance-unnecessary-copy-initialization
<clang-tidy/checks/performance/unnecessary-copy-initialization>` check by
detecting more cases of constant access. In particular, pointers can be
analyzed, se the check now handles the common patterns
`const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`.

- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check in `GetConfigPerFile`
mode by resolving symbolic links to header files. Fixed handling of Hungarian
Prefix when configured to `LowerCase`.

- Improved :doc:`readability-implicit-bool-conversion
<clang-tidy/checks/readability/implicit-bool-conversion>` check to provide
valid fix suggestions for ``static_cast`` without a preceding space and
Expand All @@ -244,10 +259,10 @@ Changes in existing checks
<clang-tidy/checks/readability/redundant-inline-specifier>` check to properly
emit warnings for static data member with an in-class initializer.

- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check in `GetConfigPerFile`
mode by resolving symbolic links to header files. Fixed handling of Hungarian
Prefix when configured to `LowerCase`.
- Improved :doc:`readability-static-definition-in-anonymous-namespace
<clang-tidy/checks/readability/static-definition-in-anonymous-namespace>`
check by resolving fix-it overlaps in template code by disregarding implicit
instances.

Removed checks
^^^^^^^^^^^^^^
Expand All @@ -258,9 +273,9 @@ Removed checks
Miscellaneous
^^^^^^^^^^^^^

- Fixed incorrect formatting in ``clang-apply-replacements`` when no ``--format``
option is specified. Now ``clang-apply-replacements`` applies formatting only with
the option.
- Fixed incorrect formatting in :program:`clang-apply-replacements` when no
``--format`` option is specified. Now :program:`clang-apply-replacements`
applies formatting only with the option.

Improvements to include-fixer
-----------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,13 @@ bool doubleCheck(Container<int> x) {
// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: decrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions]
// CHECK-MESSAGES: :[[@LINE-2]]:31: warning: incrementing and referencing a variable in a complex condition can cause unintended side-effects due to C++'s order of evaluation, consider moving the modification outside of the condition to avoid misunderstandings [bugprone-inc-dec-in-conditions]
}

namespace PR85838 {
void test()
{
auto foo = 0;
auto bar = 0;
if (++foo < static_cast<decltype(foo)>(bar)) {}
if (static_cast<decltype(++foo)>(bar) < foo) {}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -I %S/Inputs/use-using/
// RUN: %check_clang_tidy %s modernize-use-using %t -- -- -fno-delayed-template-parsing -I %S/Inputs/use-using/

typedef int Type;
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use 'using' instead of 'typedef' [modernize-use-using]
Expand Down Expand Up @@ -342,3 +342,44 @@ typedef int InExternCPP;
// CHECK-FIXES: using InExternCPP = int;

}

namespace ISSUE_72179
{
void foo()
{
typedef int a;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using]
// CHECK-FIXES: using a = int;

}

void foo2()
{
typedef struct { int a; union { int b; }; } c;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using]
// CHECK-FIXES: using c = struct { int a; union { int b; }; };
}

template <typename T>
void foo3()
{
typedef T b;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use 'using' instead of 'typedef' [modernize-use-using]
// CHECK-FIXES: using b = T;
}

template <typename T>
class MyClass
{
void foo()
{
typedef MyClass c;
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use 'using' instead of 'typedef' [modernize-use-using]
// CHECK-FIXES: using c = MyClass;
}
};

const auto foo4 = [](int a){typedef int d;};
// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: use 'using' instead of 'typedef' [modernize-use-using]
// CHECK-FIXES: const auto foo4 = [](int a){using d = int;};
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ static int c = 1;
} // namespace deep_inner
} // namespace inner

template<typename T>
static void printTemplate(T&&) {}
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: 'printTemplate' is a static definition in anonymous namespace; static is redundant here [readability-static-definition-in-anonymous-namespace]
// CHECK-FIXES: {{^}}void printTemplate(T&&) {}

void testTemplate() {
printTemplate(5);
printTemplate(5U);
printTemplate("some string");
}

} // namespace

namespace N {
Expand Down
2 changes: 1 addition & 1 deletion clang/cmake/caches/HLSL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set(LLVM_TARGETS_TO_BUILD Native CACHE STRING "")

# Include the DirectX target for DXIL code generation, eventually we'll include
# SPIR-V here too.
set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD DirectX CACHE STRING "")
set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "DirectX;SPIRV" CACHE STRING "")

# HLSL support is currently limted to clang, eventually it will expand to
# clang-tools-extra too.
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5420,10 +5420,12 @@ The following builtin intrinsics can be used in constant expressions:
* ``__builtin_clzl``
* ``__builtin_clzll``
* ``__builtin_clzs``
* ``__builtin_clzg``
* ``__builtin_ctz``
* ``__builtin_ctzl``
* ``__builtin_ctzll``
* ``__builtin_ctzs``
* ``__builtin_ctzg``
* ``__builtin_ffs``
* ``__builtin_ffsl``
* ``__builtin_ffsll``
Expand Down
20 changes: 20 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ ABI Changes in This Version
inline member function that contains a static local variable with a dynamic
initializer is declared with ``__declspec(dllimport)``. (#GH83616).

- Fixed Microsoft name mangling of lifetime extended temporary objects. This
change corrects missing back reference registrations that could result in
incorrect back reference indexes and suprising demangled name results. Since
MSVC uses a different mangling for these objects, compatibility is not affected.
(#GH85423).

AST Dumping Potentially Breaking Changes
----------------------------------------

Expand Down Expand Up @@ -182,6 +188,11 @@ Non-comprehensive list of changes in this release

- Lambda expressions are now accepted in C++03 mode as an extension.

- Added ``__builtin_clzg`` and ``__builtin_ctzg`` as type-generic alternatives
to ``__builtin_clz{,s,l,ll}`` and ``__builtin_ctz{,s,l,ll}`` respectively,
with support for any unsigned integer type. Like the previous builtins, these
new builtins are constexpr and may be used in constant expressions.

New Compiler Flags
------------------

Expand Down Expand Up @@ -289,6 +300,10 @@ Improvements to Clang's diagnostics
- Clang now correctly diagnoses no arguments to a variadic macro parameter as a C23/C++20 extension.
Fixes #GH84495.

- Clang no longer emits a ``-Wexit-time destructors`` warning on static variables explicitly
annotated with the ``clang::always_destroy`` attribute.
Fixes #GH68686, #GH86486

Improvements to Clang's time-trace
----------------------------------

Expand Down Expand Up @@ -439,6 +454,7 @@ Bug Fixes to C++ Support
- Fix a crash when instantiating a lambda that captures ``this`` outside of its context. Fixes (#GH85343).
- Fix an issue where a namespace alias could be defined using a qualified name (all name components
following the first `::` were ignored).
- Fix an out-of-bounds crash when checking the validity of template partial specializations. (part of #GH86757).

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -611,6 +627,10 @@ Sanitizers
manually disable potentially noisy signed integer overflow checks with
``-fno-sanitize=signed-integer-overflow``

- ``-fsanitize=cfi -fsanitize-cfi-cross-dso`` (cross-DSO CFI instrumentation)
now generates the ``__cfi_check`` function with proper target-specific
attributes, for example allowing unwind table generation.

Python Binding Changes
----------------------

Expand Down
60 changes: 47 additions & 13 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2441,20 +2441,39 @@ usual build cycle when using sample profilers for optimization:

1. Build the code with source line table information. You can use all the
usual build flags that you always build your application with. The only
requirement is that you add ``-gline-tables-only`` or ``-g`` to the
command line. This is important for the profiler to be able to map
instructions back to source line locations.
requirement is that DWARF debug info including source line information is
generated. This DWARF information is important for the profiler to be able
to map instructions back to source line locations.

On Linux, ``-g`` or just ``-gline-tables-only`` is sufficient:

.. code-block:: console
$ clang++ -O2 -gline-tables-only code.cc -o code
While MSVC-style targets default to CodeView debug information, DWARF debug
information is required to generate source-level LLVM profiles. Use
``-gdwarf`` to include DWARF debug information:

.. code-block:: console
$ clang-cl -O2 -gdwarf -gline-tables-only coff-profile.cpp -fuse-ld=lld -link -debug:dwarf
2. Run the executable under a sampling profiler. The specific profiler
you use does not really matter, as long as its output can be converted
into the format that the LLVM optimizer understands. Currently, there
exists a conversion tool for the Linux Perf profiler
(https://perf.wiki.kernel.org/), so these examples assume that you
are using Linux Perf to profile your code.
into the format that the LLVM optimizer understands.

Two such profilers are the the Linux Perf profiler
(https://perf.wiki.kernel.org/) and Intel's Sampling Enabling Product (SEP),
available as part of `Intel VTune
<https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/vtune-profiler.html>`_.
While Perf is Linux-specific, SEP can be used on Linux, Windows, and FreeBSD.

The LLVM tool ``llvm-profgen`` can convert output of either Perf or SEP. An
external project, `AutoFDO <https://github.com/google/autofdo>`_, also
provides a ``create_llvm_prof`` tool which supports Linux Perf output.

When using Perf:

.. code-block:: console
Expand All @@ -2465,11 +2484,19 @@ usual build cycle when using sample profilers for optimization:
it provides better call information, which improves the accuracy of
the profile data.

3. Convert the collected profile data to LLVM's sample profile format.
This is currently supported via the AutoFDO converter ``create_llvm_prof``.
It is available at https://github.com/google/autofdo. Once built and
installed, you can convert the ``perf.data`` file to LLVM using
the command:
When using SEP:

.. code-block:: console
$ sep -start -out code.tb7 -ec BR_INST_RETIRED.NEAR_TAKEN:precise=yes:pdir -lbr no_filter:usr -perf-script brstack -app ./code
This produces a ``code.perf.data.script`` output which can be used with
``llvm-profgen``'s ``--perfscript`` input option.

3. Convert the collected profile data to LLVM's sample profile format. This is
currently supported via the `AutoFDO <https://github.com/google/autofdo>`_
converter ``create_llvm_prof``. Once built and installed, you can convert
the ``perf.data`` file to LLVM using the command:

.. code-block:: console
Expand All @@ -2485,7 +2512,14 @@ usual build cycle when using sample profilers for optimization:

.. code-block:: console
$ llvm-profgen --binary=./code --output=code.prof--perfdata=perf.data
$ llvm-profgen --binary=./code --output=code.prof --perfdata=perf.data
When using SEP the output is in the textual format corresponding to
``llvm-profgen --perfscript``. For example:

.. code-block:: console
$ llvm-profgen --binary=./code --output=code.prof --perfscript=code.perf.data.script
4. Build the code again using the collected profile. This step feeds
Expand Down
152 changes: 126 additions & 26 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,51 @@ cplusplus
C++ Checkers.
.. _cplusplus-ArrayDelete:
cplusplus.ArrayDelete (C++)
"""""""""""""""""""""""""""
Reports destructions of arrays of polymorphic objects that are destructed as
their base class. If the dynamic type of the array is different from its static
type, calling `delete[]` is undefined.
This checker corresponds to the SEI CERT rule `EXP51-CPP: Do not delete an array through a pointer of the incorrect type <https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP51-CPP.+Do+not+delete+an+array+through+a+pointer+of+the+incorrect+type>`_.
.. code-block:: cpp
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {};
Base *create() {
Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here
return x;
}
void foo() {
Base *x = create();
delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined
}
**Limitations**
The checker does not emit note tags when casting to and from reference types,
even though the pointer values are tracked across references.
.. code-block:: cpp
void foo() {
Derived *d = new Derived[10];
Derived &dref = *d;
Base &bref = static_cast<Base&>(dref); // no note
Base *b = &bref;
delete[] b; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined
}
.. _cplusplus-InnerPointer:
cplusplus.InnerPointer (C++)
Expand Down Expand Up @@ -804,10 +849,89 @@ Check for performance anti-patterns when using Grand Central Dispatch.
.. _optin-performance-Padding:
optin.performance.Padding
"""""""""""""""""""""""""
optin.performance.Padding (C, C++, ObjC)
""""""""""""""""""""""""""""""""""""""""
Check for excessively padded structs.
This checker detects structs with excessive padding, which can lead to wasted
memory thus decreased performance by reducing the effectiveness of the
processor cache. Padding bytes are added by compilers to align data accesses
as some processors require data to be aligned to certain boundaries. On others,
unaligned data access are possible, but impose significantly larger latencies.
To avoid padding bytes, the fields of a struct should be ordered by decreasing
by alignment. Usually, its easier to think of the ``sizeof`` of the fields, and
ordering the fields by ``sizeof`` would usually also lead to the same optimal
layout.
In rare cases, one can use the ``#pragma pack(1)`` directive to enforce a packed
layout too, but it can significantly increase the access times, so reordering the
fields is usually a better solution.
.. code-block:: cpp
// warn: Excessive padding in 'struct NonOptimal' (35 padding bytes, where 3 is optimal)
struct NonOptimal {
char c1;
// 7 bytes of padding
std::int64_t big1; // 8 bytes
char c2;
// 7 bytes of padding
std::int64_t big2; // 8 bytes
char c3;
// 7 bytes of padding
std::int64_t big3; // 8 bytes
char c4;
// 7 bytes of padding
std::int64_t big4; // 8 bytes
char c5;
// 7 bytes of padding
};
static_assert(sizeof(NonOptimal) == 4*8+5+5*7);
// no-warning: The fields are nicely aligned to have the minimal amount of padding bytes.
struct Optimal {
std::int64_t big1; // 8 bytes
std::int64_t big2; // 8 bytes
std::int64_t big3; // 8 bytes
std::int64_t big4; // 8 bytes
char c1;
char c2;
char c3;
char c4;
char c5;
// 3 bytes of padding
};
static_assert(sizeof(Optimal) == 4*8+5+3);
// no-warning: Bit packing representation is also accepted by this checker, but
// it can significantly increase access times, so prefer reordering the fields.
#pragma pack(1)
struct BitPacked {
char c1;
std::int64_t big1; // 8 bytes
char c2;
std::int64_t big2; // 8 bytes
char c3;
std::int64_t big3; // 8 bytes
char c4;
std::int64_t big4; // 8 bytes
char c5;
};
static_assert(sizeof(BitPacked) == 4*8+5);
The ``AllowedPad`` option can be used to specify a threshold for the number
padding bytes raising the warning. If the number of padding bytes of the struct
and the optimal number of padding bytes differ by more than the threshold value,
a warning will be raised.
By default, the ``AllowedPad`` threshold is 24 bytes.
To override this threshold to e.g. 4 bytes, use the
``-analyzer-config optin.performance.Padding:AllowedPad=4`` option.
.. _optin-portability-UnixAPI:
optin.portability.UnixAPI
Expand Down Expand Up @@ -2139,30 +2263,6 @@ Either the comparison is useless or there is division by zero.
alpha.cplusplus
^^^^^^^^^^^^^^^
.. _alpha-cplusplus-ArrayDelete:
alpha.cplusplus.ArrayDelete (C++)
"""""""""""""""""""""""""""""""""
Reports destructions of arrays of polymorphic objects that are destructed as their base class.
This checker corresponds to the CERT rule `EXP51-CPP: Do not delete an array through a pointer of the incorrect type <https://wiki.sei.cmu.edu/confluence/display/cplusplus/EXP51-CPP.+Do+not+delete+an+array+through+a+pointer+of+the+incorrect+type>`_.
.. code-block:: cpp
class Base {
virtual ~Base() {}
};
class Derived : public Base {}
Base *create() {
Base *x = new Derived[10]; // note: Casting from 'Derived' to 'Base' here
return x;
}
void foo() {
Base *x = create();
delete[] x; // warn: Deleting an array of 'Derived' objects as their base class 'Base' is undefined
}
.. _alpha-cplusplus-DeleteWithNonVirtualDtor:
alpha.cplusplus.DeleteWithNonVirtualDtor (C++)
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/DeclContextInternals.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class StoredDeclsList {
Data.setPointer(Head);
}

/// Return an array of all the decls that this list represents.
/// Return the list of all the decls.
DeclContext::lookup_result getLookupResult() const {
return DeclContext::lookup_result(Data.getPointer());
}
Expand Down
108 changes: 84 additions & 24 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1690,7 +1690,10 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {

/// Whether we have a stored size expression.
LLVM_PREFERRED_TYPE(bool)
unsigned HasStoredSizeExpr : 1;
unsigned HasExternalSize : 1;

LLVM_PREFERRED_TYPE(unsigned)
unsigned SizeWidth : 5;
};

class BuiltinTypeBitfields {
Expand Down Expand Up @@ -3338,35 +3341,93 @@ class ArrayType : public Type, public llvm::FoldingSetNode {
/// Represents the canonical version of C arrays with a specified constant size.
/// For example, the canonical type for 'int A[4 + 4*100]' is a
/// ConstantArrayType where the element type is 'int' and the size is 404.
class ConstantArrayType final
: public ArrayType,
private llvm::TrailingObjects<ConstantArrayType, const Expr *> {
class ConstantArrayType final : public ArrayType {
friend class ASTContext; // ASTContext creates these.
friend TrailingObjects;

llvm::APInt Size; // Allows us to unique the type.
struct ExternalSize {
ExternalSize(const llvm::APInt &Sz, const Expr *SE)
: Size(Sz), SizeExpr(SE) {}
llvm::APInt Size; // Allows us to unique the type.
const Expr *SizeExpr;
};

ConstantArrayType(QualType et, QualType can, const llvm::APInt &size,
const Expr *sz, ArraySizeModifier sm, unsigned tq)
: ArrayType(ConstantArray, et, can, sm, tq, sz), Size(size) {
ConstantArrayTypeBits.HasStoredSizeExpr = sz != nullptr;
if (ConstantArrayTypeBits.HasStoredSizeExpr) {
assert(!can.isNull() && "canonical constant array should not have size");
*getTrailingObjects<const Expr*>() = sz;
}
union {
uint64_t Size;
ExternalSize *SizePtr;
};

ConstantArrayType(QualType Et, QualType Can, uint64_t Width, uint64_t Sz,
ArraySizeModifier SM, unsigned TQ)
: ArrayType(ConstantArray, Et, Can, SM, TQ, nullptr), Size(Sz) {
ConstantArrayTypeBits.HasExternalSize = false;
ConstantArrayTypeBits.SizeWidth = Width / 8;
// The in-structure size stores the size in bytes rather than bits so we
// drop the three least significant bits since they're always zero anyways.
assert(Width < 0xFF && "Type width in bits must be less than 8 bits");
}

unsigned numTrailingObjects(OverloadToken<const Expr*>) const {
return ConstantArrayTypeBits.HasStoredSizeExpr;
ConstantArrayType(QualType Et, QualType Can, ExternalSize *SzPtr,
ArraySizeModifier SM, unsigned TQ)
: ArrayType(ConstantArray, Et, Can, SM, TQ, SzPtr->SizeExpr),
SizePtr(SzPtr) {
ConstantArrayTypeBits.HasExternalSize = true;
ConstantArrayTypeBits.SizeWidth = 0;

assert((SzPtr->SizeExpr == nullptr || !Can.isNull()) &&
"canonical constant array should not have size expression");
}

static ConstantArrayType *Create(const ASTContext &Ctx, QualType ET,
QualType Can, const llvm::APInt &Sz,
const Expr *SzExpr, ArraySizeModifier SzMod,
unsigned Qual);

public:
const llvm::APInt &getSize() const { return Size; }
/// Return the constant array size as an APInt.
llvm::APInt getSize() const {
return ConstantArrayTypeBits.HasExternalSize
? SizePtr->Size
: llvm::APInt(ConstantArrayTypeBits.SizeWidth * 8, Size);
}

/// Return the bit width of the size type.
unsigned getSizeBitWidth() const {
return ConstantArrayTypeBits.HasExternalSize
? SizePtr->Size.getBitWidth()
: static_cast<unsigned>(ConstantArrayTypeBits.SizeWidth * 8);
}

/// Return true if the size is zero.
bool isZeroSize() const {
return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.isZero()
: 0 == Size;
}

/// Return the size zero-extended as a uint64_t.
uint64_t getZExtSize() const {
return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.getZExtValue()
: Size;
}

/// Return the size sign-extended as a uint64_t.
int64_t getSExtSize() const {
return ConstantArrayTypeBits.HasExternalSize ? SizePtr->Size.getSExtValue()
: static_cast<int64_t>(Size);
}

/// Return the size zero-extended to uint64_t or UINT64_MAX if the value is
/// larger than UINT64_MAX.
uint64_t getLimitedSize() const {
return ConstantArrayTypeBits.HasExternalSize
? SizePtr->Size.getLimitedValue()
: Size;
}

/// Return a pointer to the size expression.
const Expr *getSizeExpr() const {
return ConstantArrayTypeBits.HasStoredSizeExpr
? *getTrailingObjects<const Expr *>()
: nullptr;
return ConstantArrayTypeBits.HasExternalSize ? SizePtr->SizeExpr : nullptr;
}

bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); }

Expand All @@ -3383,14 +3444,13 @@ class ConstantArrayType final
static unsigned getMaxSizeBits(const ASTContext &Context);

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) {
Profile(ID, Ctx, getElementType(), getSize(), getSizeExpr(),
Profile(ID, Ctx, getElementType(), getZExtSize(), getSizeExpr(),
getSizeModifier(), getIndexTypeCVRQualifiers());
}

static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx,
QualType ET, const llvm::APInt &ArraySize,
const Expr *SizeExpr, ArraySizeModifier SizeMod,
unsigned TypeQuals);
QualType ET, uint64_t ArraySize, const Expr *SizeExpr,
ArraySizeModifier SizeMod, unsigned TypeQuals);

static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray;
Expand Down
8 changes: 7 additions & 1 deletion clang/include/clang/Analysis/PathDiagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,9 @@ class PathDiagnostic : public llvm::FoldingSetNode {
PathDiagnosticLocation UniqueingLoc;
const Decl *UniqueingDecl;

/// The top-level entry point from which this issue was discovered.
const Decl *AnalysisEntryPoint = nullptr;

/// Lines executed in the path.
std::unique_ptr<FilesToLineNumsMap> ExecutedLines;

Expand All @@ -788,7 +791,7 @@ class PathDiagnostic : public llvm::FoldingSetNode {
PathDiagnostic(StringRef CheckerName, const Decl *DeclWithIssue,
StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
StringRef category, PathDiagnosticLocation LocationToUnique,
const Decl *DeclToUnique,
const Decl *DeclToUnique, const Decl *AnalysisEntryPoint,
std::unique_ptr<FilesToLineNumsMap> ExecutedLines);
~PathDiagnostic();

Expand Down Expand Up @@ -852,6 +855,9 @@ class PathDiagnostic : public llvm::FoldingSetNode {
return *ExecutedLines;
}

/// Get the top-level entry point from which this issue was discovered.
const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }

/// Return the semantic context where an issue occurred. If the
/// issue occurs along a path, this represents the "central" area
/// where the bug manifests.
Expand Down
14 changes: 14 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3088,6 +3088,20 @@ def TargetClones : InheritableAttr {
StringRef getFeatureStr(unsigned Index) const {
return *(featuresStrs_begin() + Index);
}
bool isDefaultVersion(unsigned Index) const {
return getFeatureStr(Index) == "default";
}
void getFeatures(llvm::SmallVectorImpl<StringRef> &Out,
unsigned Index) const {
if (isDefaultVersion(Index)) return;
StringRef Features = getFeatureStr(Index);
SmallVector<StringRef, 8> AttrFeatures;
Features.split(AttrFeatures, "+");
for (auto &Feature : AttrFeatures) {
Feature = Feature.trim();
Out.push_back(Feature);
}
}
// Given an index into the 'featuresStrs' sequence, compute a unique
// ID to be used with function name mangling for the associated variant.
// This mapping is necessary due to a requirement that the mangling ID
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -6069,6 +6069,9 @@ def AlwaysDestroyDocs : Documentation {
The ``always_destroy`` attribute specifies that a variable with static or thread
storage duration should have its exit-time destructor run. This attribute is the
default unless clang was invoked with -fno-c++-static-destructors.

If a variable is explicitly declared with this attribute, Clang will silence
otherwise applicable ``-Wexit-time-destructors`` warnings.
}];
}

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ def Clz : Builtin, BitShort_Int_Long_LongLongTemplate {

def Clzg : Builtin {
let Spellings = ["__builtin_clzg"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
let Prototype = "int(...)";
}

Expand All @@ -690,7 +690,7 @@ def Ctz : Builtin, BitShort_Int_Long_LongLongTemplate {

def Ctzg : Builtin {
let Spellings = ["__builtin_ctzg"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
let Prototype = "int(...)";
}

Expand Down
5 changes: 0 additions & 5 deletions clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -434,13 +434,8 @@ TARGET_BUILTIN(__builtin_amdgcn_s_get_barrier_state, "Uii", "n", "gfx12-insts")

TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b64_v2i32, "V2iV2i*1", "nc", "gfx12-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8i16, "V8sV8s*1", "nc", "gfx12-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8f16, "V8hV8h*1", "nc", "gfx12-insts,wavefrontsize32")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v8bf16, "V8yV8y*1", "nc", "gfx12-insts,wavefrontsize32")

TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b64_i32, "ii*1", "nc", "gfx12-insts,wavefrontsize64")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4i16, "V4sV4s*1", "nc", "gfx12-insts,wavefrontsize64")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4f16, "V4hV4h*1", "nc", "gfx12-insts,wavefrontsize64")
TARGET_BUILTIN(__builtin_amdgcn_global_load_tr_b128_v4bf16, "V4yV4y*1", "nc", "gfx12-insts,wavefrontsize64")

//===----------------------------------------------------------------------===//
// WMMA builtins.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ let CategoryName = "Command line" in {
def err_cannot_write_file : Error<"cannot write file '%0': %1">;
def err_no_install_name : Error<"no install name specified: add -install_name <path>">;
def err_no_output_file: Error<"no output file specified">;
def err_no_such_header_file : Error<"no such %select{public|private|project}1 header file: '%0'">;
def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public|private}0 header file: '%1'">, InGroup<InstallAPIViolation>;
def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup<InstallAPIViolation>;
} // end of command line category.

let CategoryName = "Verification" in {
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Basic/SyncScope.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,8 +252,7 @@ class AtomicScopeGenericModel : public AtomicScopeModel {
}

bool isValid(unsigned S) const override {
return S >= static_cast<unsigned>(System) &&
S <= static_cast<unsigned>(Last);
return S <= static_cast<unsigned>(Last);
}

ArrayRef<unsigned> getRuntimeValues() const override {
Expand Down
11 changes: 5 additions & 6 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4105,12 +4105,8 @@ defm strict_return : BoolFOption<"strict-return",
" of a non-void function as unreachable">,
PosFlag<SetTrue>>;

let Group = f_Group in {
let Visibility = [ClangOption,CC1Option] in {
def fptrauth_intrinsics : Flag<["-"], "fptrauth-intrinsics">,
HelpText<"Enable pointer authentication intrinsics">;
}
def fno_ptrauth_intrinsics : Flag<["-"], "fno-ptrauth-intrinsics">;
let Flags = [TargetSpecific] in {
defm ptrauth_intrinsics : OptInCC1FFlag<"ptrauth-intrinsics", "Enable pointer authentication intrinsics">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Expand Down Expand Up @@ -6688,6 +6684,9 @@ def analyzer_opt_analyze_headers : Flag<["-"], "analyzer-opt-analyze-headers">,
def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">,
MarshallingInfoFlag<AnalyzerOpts<"AnalyzerDisplayProgress">>;
def analyzer_note_analysis_entry_points : Flag<["-"], "analyzer-note-analysis-entry-points">,
HelpText<"Add a note for each bug report to denote their analysis entry points">,
MarshallingInfoFlag<AnalyzerOpts<"AnalyzerNoteAnalysisEntryPoints">>;
def analyze_function : Separate<["-"], "analyze-function">,
HelpText<"Run analysis on specific function (for C++ include parameters in name)">,
MarshallingInfoString<AnalyzerOpts<"AnalyzeSpecificFunction">>;
Expand Down
54 changes: 52 additions & 2 deletions clang/include/clang/InstallAPI/HeaderFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#ifndef LLVM_CLANG_INSTALLAPI_HEADERFILE_H
#define LLVM_CLANG_INSTALLAPI_HEADERFILE_H

#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangStandard.h"
#include "clang/InstallAPI/MachO.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Regex.h"
Expand Down Expand Up @@ -56,6 +58,10 @@ class HeaderFile {
std::string IncludeName;
/// Supported language mode for header.
std::optional<clang::Language> Language;
/// Exclude header file from processing.
bool Excluded{false};
/// Add header file to processing.
bool Extra{false};

public:
HeaderFile() = delete;
Expand All @@ -71,17 +77,48 @@ class HeaderFile {
StringRef getIncludeName() const { return IncludeName; }
StringRef getPath() const { return FullPath; }

void setExtra(bool V = true) { Extra = V; }
void setExcluded(bool V = true) { Excluded = V; }
bool isExtra() const { return Extra; }
bool isExcluded() const { return Excluded; }

bool useIncludeName() const {
return Type != HeaderType::Project && !IncludeName.empty();
}

bool operator==(const HeaderFile &Other) const {
return std::tie(Type, FullPath, IncludeName, Language) ==
return std::tie(Type, FullPath, IncludeName, Language, Excluded, Extra) ==
std::tie(Other.Type, Other.FullPath, Other.IncludeName,
Other.Language);
Other.Language, Other.Excluded, Other.Extra);
}
};

/// Glob that represents a pattern of header files to retreive.
class HeaderGlob {
private:
std::string GlobString;
llvm::Regex Rule;
HeaderType Type;
bool FoundMatch{false};

public:
HeaderGlob(StringRef GlobString, llvm::Regex &&, HeaderType Type);

/// Create a header glob from string for the header access level.
static llvm::Expected<std::unique_ptr<HeaderGlob>>
create(StringRef GlobString, HeaderType Type);

/// Query if provided header matches glob.
bool match(const HeaderFile &Header);

/// Query if a header was matched in the glob, used primarily for error
/// reporting.
bool didMatch() { return FoundMatch; }

/// Provide back input glob string.
StringRef str() { return GlobString; }
};

/// Assemble expected way header will be included by clients.
/// As in what maps inside the brackets of `#include <IncludeName.h>`
/// For example,
Expand All @@ -93,6 +130,19 @@ class HeaderFile {
std::optional<std::string> createIncludeHeaderName(const StringRef FullPath);
using HeaderSeq = std::vector<HeaderFile>;

/// Determine if Path is a header file.
/// It does not touch the file system.
///
/// \param Path File path to file.
bool isHeaderFile(StringRef Path);

/// Given input directory, collect all header files.
///
/// \param FM FileManager for finding input files.
/// \param Directory Path to directory file.
llvm::Expected<PathSeq> enumerateFiles(clang::FileManager &FM,
StringRef Directory);

} // namespace clang::installapi

#endif // LLVM_CLANG_INSTALLAPI_HEADERFILE_H
1 change: 1 addition & 0 deletions clang/include/clang/InstallAPI/MachO.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ using SymbolSet = llvm::MachO::SymbolSet;
using SimpleSymbol = llvm::MachO::SimpleSymbol;
using FileType = llvm::MachO::FileType;
using PackedVersion = llvm::MachO::PackedVersion;
using PathSeq = llvm::MachO::PathSeq;
using Target = llvm::MachO::Target;
using TargetList = llvm::MachO::TargetList;

Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
namespace llvm {
namespace orc {
class LLJIT;
class LLJITBuilder;
class ThreadSafeContext;
} // namespace orc
} // namespace llvm
Expand Down Expand Up @@ -127,6 +128,13 @@ class Interpreter {
// custom runtime.
virtual std::unique_ptr<RuntimeInterfaceBuilder> FindRuntimeInterface();

// Lazily construct thev ORCv2 JITBuilder. This called when the internal
// IncrementalExecutor is created. The default implementation populates an
// in-process JIT with debugging support. Override this to configure the JIT
// engine used for execution.
virtual llvm::Expected<std::unique_ptr<llvm::orc::LLJITBuilder>>
CreateJITBuilder(CompilerInstance &CI);

public:
virtual ~Interpreter();

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Interpreter/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class QualType;
X(bool, Bool) \
X(char, Char_S) \
X(signed char, SChar) \
X(unsigned char, Char_U) \
X(unsigned char, UChar) \
X(short, Short) \
X(unsigned short, UShort) \
Expand Down
12 changes: 6 additions & 6 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,11 @@ def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,

let ParentPackage = Cplusplus in {

def ArrayDeleteChecker : Checker<"ArrayDelete">,
HelpText<"Reports destructions of arrays of polymorphic objects that are "
"destructed as their base class.">,
Documentation<HasDocumentation>;

def InnerPointerChecker : Checker<"InnerPointer">,
HelpText<"Check for inner pointers of C++ containers used after "
"re/deallocation">,
Expand Down Expand Up @@ -777,11 +782,6 @@ def ContainerModeling : Checker<"ContainerModeling">,
Documentation<NotDocumented>,
Hidden;

def CXXArrayDeleteChecker : Checker<"ArrayDelete">,
HelpText<"Reports destructions of arrays of polymorphic objects that are "
"destructed as their base class.">,
Documentation<HasDocumentation>;

def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,
HelpText<"Reports destructions of polymorphic objects with a non-virtual "
"destructor in their base class">,
Expand Down Expand Up @@ -908,7 +908,7 @@ def PaddingChecker : Checker<"Padding">,
"24",
Released>
]>,
Documentation<NotDocumented>;
Documentation<HasDocumentation>;

} // end: "padding"

Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
unsigned ShouldEmitErrorsOnInvalidConfigValue : 1;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
unsigned AnalyzerNoteAnalysisEntryPoints : 1;

unsigned eagerlyAssumeBinOpBifurcation : 1;

Expand Down Expand Up @@ -291,10 +292,10 @@ class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
ShowCheckerOptionDeveloperList(false), ShowEnabledCheckerList(false),
ShowConfigOptionsList(false),
ShouldEmitErrorsOnInvalidConfigValue(false), AnalyzeAll(false),
AnalyzerDisplayProgress(false), eagerlyAssumeBinOpBifurcation(false),
TrimGraph(false), visualizeExplodedGraphWithGraphViz(false),
UnoptimizedCFG(false), PrintStats(false), NoRetryExhausted(false),
AnalyzerWerror(false) {}
AnalyzerDisplayProgress(false), AnalyzerNoteAnalysisEntryPoints(false),
eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {}

/// Interprets an option's string value as a boolean. The "true" string is
/// interpreted as true and the "false" string is interpreted as false.
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ class BugReporter {
private:
BugReporterData& D;

/// The top-level entry point for the issue to be reported.
const Decl *AnalysisEntryPoint = nullptr;

/// Generate and flush the diagnostics for the given bug report.
void FlushReport(BugReportEquivClass& EQ);

Expand Down Expand Up @@ -623,6 +626,14 @@ class BugReporter {

Preprocessor &getPreprocessor() { return D.getPreprocessor(); }

/// Get the top-level entry point for the issue to be reported.
const Decl *getAnalysisEntryPoint() const { return AnalysisEntryPoint; }

void setAnalysisEntryPoint(const Decl *EntryPoint) {
assert(EntryPoint);
AnalysisEntryPoint = EntryPoint;
}

/// Add the given report to the set of reports tracked by BugReporter.
///
/// The reports are usually generated by the checkers. Further, they are
Expand Down Expand Up @@ -713,6 +724,7 @@ class BugReporterContext {
virtual ~BugReporterContext() = default;

PathSensitiveBugReporter& getBugReporter() { return BR; }
const PathSensitiveBugReporter &getBugReporter() const { return BR; }

ProgramStateManager& getStateManager() const {
return BR.getStateManager();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,8 @@ class CallDescription {
/// - We also accept calls where the number of arguments or parameters is
/// greater than the specified value.
/// For the exact heuristics, see CheckerContext::isCLibraryFunction().
/// Note that functions whose declaration context is not a TU (e.g.
/// methods, functions in namespaces) are not accepted as C library
/// functions.
/// FIXME: If I understand it correctly, this discards calls where C++ code
/// refers a C library function through the namespace `std::` via headers
/// like <cstdlib>.
/// (This mode only matches functions that are declared either directly
/// within a TU or in the namespace `std`.)
CLibrary,

/// Matches "simple" functions that are not methods. (Static methods are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ class ExprEngine {

/// Returns true if there is still simulation state on the worklist.
bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
assert(L->inTopFrame());
BR.setAnalysisEntryPoint(L->getDecl());
return Engine.ExecuteWorkList(L, Steps, nullptr);
}

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/APValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,9 @@ void APValue::printPretty(raw_ostream &Out, const PrintingPolicy &Policy,
return;
}

if (const auto *AT = Ty->getAs<AtomicType>())
Ty = AT->getValueType();

switch (getKind()) {
case APValue::None:
Out << "<out of lifetime>";
Expand Down
36 changes: 15 additions & 21 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1766,7 +1766,7 @@ TypeInfoChars
static getConstantArrayInfoInChars(const ASTContext &Context,
const ConstantArrayType *CAT) {
TypeInfoChars EltInfo = Context.getTypeInfoInChars(CAT->getElementType());
uint64_t Size = CAT->getSize().getZExtValue();
uint64_t Size = CAT->getZExtSize();
assert((Size == 0 || static_cast<uint64_t>(EltInfo.Width.getQuantity()) <=
(uint64_t)(-1)/Size) &&
"Overflow in array type char size evaluation");
Expand Down Expand Up @@ -1910,7 +1910,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
// Model non-constant sized arrays as size zero, but track the alignment.
uint64_t Size = 0;
if (const auto *CAT = dyn_cast<ConstantArrayType>(T))
Size = CAT->getSize().getZExtValue();
Size = CAT->getZExtSize();

TypeInfo EltInfo = getTypeInfo(cast<ArrayType>(T)->getElementType());
assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) &&
Expand Down Expand Up @@ -3560,8 +3560,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
ArySize = ArySize.zextOrTrunc(Target->getMaxPointerWidth());

llvm::FoldingSetNodeID ID;
ConstantArrayType::Profile(ID, *this, EltTy, ArySize, SizeExpr, ASM,
IndexTypeQuals);
ConstantArrayType::Profile(ID, *this, EltTy, ArySize.getZExtValue(), SizeExpr,
ASM, IndexTypeQuals);

void *InsertPos = nullptr;
if (ConstantArrayType *ATP =
Expand All @@ -3585,11 +3585,8 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP;
}

void *Mem = Allocate(
ConstantArrayType::totalSizeToAlloc<const Expr *>(SizeExpr ? 1 : 0),
alignof(ConstantArrayType));
auto *New = new (Mem)
ConstantArrayType(EltTy, Canon, ArySize, SizeExpr, ASM, IndexTypeQuals);
auto *New = ConstantArrayType::Create(*this, EltTy, Canon, ArySize, SizeExpr,
ASM, IndexTypeQuals);
ConstantArrayTypes.InsertNode(New, InsertPos);
Types.push_back(New);
return QualType(New, 0);
Expand Down Expand Up @@ -7051,7 +7048,7 @@ uint64_t
ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const {
uint64_t ElementCount = 1;
do {
ElementCount *= CA->getSize().getZExtValue();
ElementCount *= CA->getZExtSize();
CA = dyn_cast_or_null<ConstantArrayType>(
CA->getElementType()->getAsArrayTypeUnsafe());
} while (CA);
Expand Down Expand Up @@ -8374,7 +8371,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string &S,
S += '[';

if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
S += llvm::utostr(CAT->getSize().getZExtValue());
S += llvm::utostr(CAT->getZExtSize());
else {
//Variable length arrays are encoded as a regular array with 0 elements.
assert((isa<VariableArrayType>(AT) || isa<IncompleteArrayType>(AT)) &&
Expand Down Expand Up @@ -10808,7 +10805,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer,
{
const ConstantArrayType* LCAT = getAsConstantArrayType(LHS);
const ConstantArrayType* RCAT = getAsConstantArrayType(RHS);
if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize())
if (LCAT && RCAT && RCAT->getZExtSize() != LCAT->getZExtSize())
return {};

QualType LHSElem = getAsArrayType(LHS)->getElementType();
Expand Down Expand Up @@ -13676,22 +13673,19 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
} else if (const auto *TC = FD->getAttr<TargetClonesAttr>()) {
std::vector<std::string> Features;
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
if (Target->getTriple().isAArch64()) {
// TargetClones for AArch64
if (VersionStr != "default") {
SmallVector<StringRef, 1> VersionFeatures;
VersionStr.split(VersionFeatures, "+");
for (auto &VFeature : VersionFeatures) {
VFeature = VFeature.trim();
llvm::SmallVector<StringRef, 8> Feats;
TC->getFeatures(Feats, GD.getMultiVersionIndex());
for (StringRef Feat : Feats)
if (Target->validateCpuSupports(Feat.str()))
// Use '?' to mark features that came from AArch64 TargetClones.
Features.push_back((StringRef{"?"} + VFeature).str());
}
}
Features.push_back("?" + Feat.str());
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
} else {
StringRef VersionStr = TC->getFeatureStr(GD.getMultiVersionIndex());
if (VersionStr.starts_with("arch="))
TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
else if (VersionStr != "default")
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2840,7 +2840,7 @@ bool VarDecl::hasFlexibleArrayInit(const ASTContext &Ctx) const {
auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType());
if (!InitTy)
return false;
return InitTy->getSize() != 0;
return !InitTy->isZeroSize();
}

CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const {
Expand Down
68 changes: 43 additions & 25 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ namespace {
IsArray = true;

if (auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
ArraySize = CAT->getSize().getZExtValue();
ArraySize = CAT->getZExtSize();
} else {
assert(I == 0 && "unexpected unsized array designator");
FirstEntryIsUnsizedArray = true;
Expand Down Expand Up @@ -401,7 +401,7 @@ namespace {
// This is a most-derived object.
MostDerivedType = CAT->getElementType();
MostDerivedIsArrayElement = true;
MostDerivedArraySize = CAT->getSize().getZExtValue();
MostDerivedArraySize = CAT->getZExtSize();
MostDerivedPathLength = Entries.size();
}
/// Update this designator to refer to the first element within the array of
Expand Down Expand Up @@ -3476,7 +3476,7 @@ static void expandStringLiteral(EvalInfo &Info, const StringLiteral *S,
QualType CharType = CAT->getElementType();
assert(CharType->isIntegerType() && "unexpected character type");

unsigned Elts = CAT->getSize().getZExtValue();
unsigned Elts = CAT->getZExtSize();
Result = APValue(APValue::UninitArray(),
std::min(S->getLength(), Elts), Elts);
APSInt Value(Info.Ctx.getTypeSize(CharType),
Expand Down Expand Up @@ -3619,7 +3619,7 @@ static bool CheckArraySize(EvalInfo &Info, const ConstantArrayType *CAT,
SourceLocation CallLoc = {}) {
return Info.CheckArraySize(
CAT->getSizeExpr() ? CAT->getSizeExpr()->getBeginLoc() : CallLoc,
CAT->getNumAddressingBits(Info.Ctx), CAT->getSize().getZExtValue(),
CAT->getNumAddressingBits(Info.Ctx), CAT->getZExtSize(),
/*Diag=*/true);
}

Expand Down Expand Up @@ -4908,7 +4908,7 @@ static bool handleDefaultInitValue(QualType T, APValue &Result) {

if (auto *AT =
dyn_cast_or_null<ConstantArrayType>(T->getAsArrayTypeUnsafe())) {
Result = APValue(APValue::UninitArray(), 0, AT->getSize().getZExtValue());
Result = APValue(APValue::UninitArray(), 0, AT->getZExtSize());
if (Result.hasArrayFiller())
Success &=
handleDefaultInitValue(AT->getElementType(), Result.getArrayFiller());
Expand Down Expand Up @@ -6595,7 +6595,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange,

// For arrays, destroy elements right-to-left.
if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(T)) {
uint64_t Size = CAT->getSize().getZExtValue();
uint64_t Size = CAT->getZExtSize();
QualType ElemT = CAT->getElementType();

if (!CheckArraySize(Info, CAT, CallRange.getBegin()))
Expand Down Expand Up @@ -7396,7 +7396,7 @@ class BufferToAPValueConverter {
}

std::optional<APValue> visit(const ConstantArrayType *Ty, CharUnits Offset) {
size_t Size = Ty->getSize().getLimitedValue();
size_t Size = Ty->getLimitedSize();
CharUnits ElementWidth = Info.Ctx.getTypeSizeInChars(Ty->getElementType());

APValue ArrayValue(APValue::UninitArray(), Size, Size);
Expand Down Expand Up @@ -9951,7 +9951,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
assert(CAT && "unexpected type for array initializer");

unsigned Bits =
std::max(CAT->getSize().getBitWidth(), ArrayBound.getBitWidth());
std::max(CAT->getSizeBitWidth(), ArrayBound.getBitWidth());
llvm::APInt InitBound = CAT->getSize().zext(Bits);
llvm::APInt AllocBound = ArrayBound.zext(Bits);
if (InitBound.ugt(AllocBound)) {
Expand Down Expand Up @@ -10410,7 +10410,7 @@ bool RecordExprEvaluator::VisitCXXParenListOrInitListExpr(

if (Field->getType()->isIncompleteArrayType()) {
if (auto *CAT = Info.Ctx.getAsConstantArrayType(Init->getType())) {
if (!CAT->getSize().isZero()) {
if (!CAT->isZeroSize()) {
// Bail out for now. This might sort of "work", but the rest of the
// code isn't really prepared to handle it.
Info.FFDiag(Init, diag::note_constexpr_unsupported_flexible_array);
Expand Down Expand Up @@ -10554,7 +10554,7 @@ bool RecordExprEvaluator::VisitCXXStdInitializerListExpr(
// End pointer.
if (!HandleLValueArrayAdjustment(Info, E, Array,
ArrayType->getElementType(),
ArrayType->getSize().getZExtValue()))
ArrayType->getZExtSize()))
return false;
Array.moveInto(Result.getStructField(1));
} else if (Info.Ctx.hasSameType(Field->getType(), Info.Ctx.getSizeType()))
Expand Down Expand Up @@ -10996,8 +10996,7 @@ namespace {
return Error(E);
}

Result = APValue(APValue::UninitArray(), 0,
CAT->getSize().getZExtValue());
Result = APValue(APValue::UninitArray(), 0, CAT->getZExtSize());
if (!Result.hasArrayFiller())
return true;

Expand Down Expand Up @@ -11122,7 +11121,7 @@ bool ArrayExprEvaluator::VisitCXXParenListOrInitListExpr(
Filler = Result.getArrayFiller();

unsigned NumEltsToInit = Args.size();
unsigned NumElts = CAT->getSize().getZExtValue();
unsigned NumElts = CAT->getZExtSize();

// If the initializer might depend on the array index, run it for each
// array element.
Expand Down Expand Up @@ -11180,7 +11179,7 @@ bool ArrayExprEvaluator::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {

auto *CAT = cast<ConstantArrayType>(E->getType()->castAsArrayTypeUnsafe());

uint64_t Elements = CAT->getSize().getZExtValue();
uint64_t Elements = CAT->getZExtSize();
Result = APValue(APValue::UninitArray(), Elements, Elements);

LValue Subobject = This;
Expand Down Expand Up @@ -11225,7 +11224,7 @@ bool ArrayExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
bool HadZeroInit = Value->hasValue();

if (const ConstantArrayType *CAT = Info.Ctx.getAsConstantArrayType(Type)) {
unsigned FinalSize = CAT->getSize().getZExtValue();
unsigned FinalSize = CAT->getZExtSize();

// Preserve the array filler if we had prior zero-initialization.
APValue Filler =
Expand Down Expand Up @@ -11940,7 +11939,7 @@ static bool isDesignatorAtObjectEnd(const ASTContext &Ctx, const LValue &LVal) {
return true;
const auto *CAT = cast<ConstantArrayType>(Ctx.getAsArrayType(BaseType));
uint64_t Index = Entry.getAsArrayIndex();
if (Index + 1 != CAT->getSize())
if (Index + 1 != CAT->getZExtSize())
return false;
BaseType = CAT->getElementType();
} else if (BaseType->isAnyComplexType()) {
Expand Down Expand Up @@ -12354,21 +12353,31 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BI__builtin_clzl:
case Builtin::BI__builtin_clzll:
case Builtin::BI__builtin_clzs:
case Builtin::BI__builtin_clzg:
case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
case Builtin::BI__lzcnt:
case Builtin::BI__lzcnt64: {
APSInt Val;
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;

// When the argument is 0, the result of GCC builtins is undefined, whereas
// for Microsoft intrinsics, the result is the bit-width of the argument.
bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
BuiltinOp != Builtin::BI__lzcnt &&
BuiltinOp != Builtin::BI__lzcnt64;
if (!Val) {
if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) {
if (!EvaluateInteger(E->getArg(1), Val, Info))
return false;
return Success(Val, E);
}

if (ZeroIsUndefined && !Val)
return Error(E);
// When the argument is 0, the result of GCC builtins is undefined,
// whereas for Microsoft intrinsics, the result is the bit-width of the
// argument.
bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
BuiltinOp != Builtin::BI__lzcnt &&
BuiltinOp != Builtin::BI__lzcnt64;

if (ZeroIsUndefined)
return Error(E);
}

return Success(Val.countl_zero(), E);
}
Expand Down Expand Up @@ -12410,12 +12419,21 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
case Builtin::BI__builtin_ctzll:
case Builtin::BI__builtin_ctzs: {
case Builtin::BI__builtin_ctzs:
case Builtin::BI__builtin_ctzg: {
APSInt Val;
if (!EvaluateInteger(E->getArg(0), Val, Info))
return false;
if (!Val)

if (!Val) {
if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) {
if (!EvaluateInteger(E->getArg(1), Val, Info))
return false;
return Success(Val, E);
}

return Error(E);
}

return Success(Val.countr_zero(), E);
}
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueIni
const ArrayType *AT = QT->getAsArrayTypeUnsafe();
assert(AT);
const auto *CAT = cast<ConstantArrayType>(AT);
size_t NumElems = CAT->getSize().getZExtValue();
size_t NumElems = CAT->getZExtSize();
PrimType ElemT = classifyPrim(CAT->getElementType());

for (size_t I = 0; I != NumElems; ++I) {
Expand Down Expand Up @@ -992,7 +992,7 @@ bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
if (const Expr *Filler = E->getArrayFiller()) {
const ConstantArrayType *CAT =
Ctx.getASTContext().getAsConstantArrayType(E->getType());
uint64_t NumElems = CAT->getSize().getZExtValue();
uint64_t NumElems = CAT->getZExtSize();

for (; ElementIndex != NumElems; ++ElementIndex) {
if (!this->visitArrayElemInit(ElementIndex, Filler))
Expand Down Expand Up @@ -1318,7 +1318,7 @@ bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {

// If the initializer string is too long, a diagnostic has already been
// emitted. Read only the array length from the string literal.
unsigned ArraySize = CAT->getSize().getZExtValue();
unsigned ArraySize = CAT->getZExtSize();
unsigned N = std::min(ArraySize, E->getLength());
size_t CharWidth = E->getCharByteWidth();

Expand Down Expand Up @@ -1919,7 +1919,7 @@ bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(
const ConstantArrayType *CAT =
Ctx.getASTContext().getAsConstantArrayType(E->getType());
assert(CAT);
size_t NumElems = CAT->getSize().getZExtValue();
size_t NumElems = CAT->getZExtSize();
const Function *Func = getFunction(E->getConstructor());
if (!Func || !Func->isConstexpr())
return false;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc,
const Pointer &BasePtr,
const ConstantArrayType *CAT) {
bool Result = true;
size_t NumElems = CAT->getSize().getZExtValue();
size_t NumElems = CAT->getZExtSize();
QualType ElemType = CAT->getElementType();

if (ElemType->isRecordType()) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/Program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
QualType ElemTy = ArrayType->getElementType();
// Array of well-known bounds.
if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
size_t NumElems = CAT->getSize().getZExtValue();
size_t NumElems = CAT->getZExtSize();
if (std::optional<PrimType> T = Ctx.classify(ElemTy)) {
// Arrays of primitives.
unsigned ElemSize = primSize(*T);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ void JSONNodeDumper::VisitArrayType(const ArrayType *AT) {
void JSONNodeDumper::VisitConstantArrayType(const ConstantArrayType *CAT) {
// FIXME: this should use ZExt instead of SExt, but JSON doesn't allow a
// narrowing conversion to int64_t so it cannot be expressed.
JOS.attribute("size", CAT->getSize().getSExtValue());
JOS.attribute("size", CAT->getSExtSize());
VisitArrayType(CAT);
}

Expand Down
9 changes: 4 additions & 5 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3911,7 +3911,8 @@ void MicrosoftMangleContextImpl::mangleReferenceTemporary(
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO);

Mangler.getStream() << "?$RT" << ManglingNumber << '@';
Mangler.getStream() << "?";
Mangler.mangleSourceName("$RT" + llvm::utostr(ManglingNumber));
Mangler.mangle(VD, "");
}

Expand Down Expand Up @@ -4022,10 +4023,8 @@ void MicrosoftMangleContextImpl::mangleStringLiteral(const StringLiteral *SL,
// char bar[42] = "foobar";
// Where it is truncated or zero-padded to fit the array. This is the length
// used for mangling, and any trailing null-bytes also need to be mangled.
unsigned StringLength = getASTContext()
.getAsConstantArrayType(SL->getType())
->getSize()
.getZExtValue();
unsigned StringLength =
getASTContext().getAsConstantArrayType(SL->getType())->getZExtSize();
unsigned StringByteLength = StringLength * SL->getCharByteWidth();

// <char-type>: The "kind" of string literal is encoded into the mangled name.
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/AST/ScanfFormatString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,7 @@ bool ScanfSpecifier::fixType(QualType QT, QualType RawQT,
if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) {
if (CAT->getSizeModifier() == ArraySizeModifier::Normal)
FieldWidth = OptionalAmount(OptionalAmount::Constant,
CAT->getSize().getZExtValue() - 1,
"", 0, false);

CAT->getZExtSize() - 1, "", 0, false);
}
return true;
}
Expand Down
29 changes: 20 additions & 9 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,22 @@ ArrayType::ArrayType(TypeClass tc, QualType et, QualType can,
ArrayTypeBits.SizeModifier = llvm::to_underlying(sm);
}

ConstantArrayType *
ConstantArrayType::Create(const ASTContext &Ctx, QualType ET, QualType Can,
const llvm::APInt &Sz, const Expr *SzExpr,
ArraySizeModifier SzMod, unsigned Qual) {
bool NeedsExternalSize = SzExpr != nullptr || Sz.ugt(0x0FFFFFFFFFFFFFFF) ||
Sz.getBitWidth() > 0xFF;
if (!NeedsExternalSize)
return new (Ctx, alignof(ConstantArrayType)) ConstantArrayType(
ET, Can, Sz.getBitWidth(), Sz.getZExtValue(), SzMod, Qual);

auto *SzPtr = new (Ctx, alignof(ConstantArrayType::ExternalSize))
ConstantArrayType::ExternalSize(Sz, SzExpr);
return new (Ctx, alignof(ConstantArrayType))
ConstantArrayType(ET, Can, SzPtr, SzMod, Qual);
}

unsigned ConstantArrayType::getNumAddressingBits(const ASTContext &Context,
QualType ElementType,
const llvm::APInt &NumElements) {
Expand Down Expand Up @@ -213,11 +229,10 @@ unsigned ConstantArrayType::getMaxSizeBits(const ASTContext &Context) {

void ConstantArrayType::Profile(llvm::FoldingSetNodeID &ID,
const ASTContext &Context, QualType ET,
const llvm::APInt &ArraySize,
const Expr *SizeExpr, ArraySizeModifier SizeMod,
unsigned TypeQuals) {
uint64_t ArraySize, const Expr *SizeExpr,
ArraySizeModifier SizeMod, unsigned TypeQuals) {
ID.AddPointer(ET.getAsOpaquePtr());
ID.AddInteger(ArraySize.getZExtValue());
ID.AddInteger(ArraySize);
ID.AddInteger(llvm::to_underlying(SizeMod));
ID.AddInteger(TypeQuals);
ID.AddBoolean(SizeExpr != nullptr);
Expand Down Expand Up @@ -452,12 +467,8 @@ QualType QualType::getSingleStepDesugaredTypeImpl(QualType type,
// Check that no type class has a non-trival destructor. Types are
// allocated with the BumpPtrAllocator from ASTContext and therefore
// their destructor is not executed.
//
// FIXME: ConstantArrayType is not trivially destructible because of its
// APInt member. It should be replaced in favor of ASTContext allocation.
#define TYPE(CLASS, BASE) \
static_assert(std::is_trivially_destructible<CLASS##Type>::value || \
std::is_same<CLASS##Type, ConstantArrayType>::value, \
static_assert(std::is_trivially_destructible<CLASS##Type>::value, \
#CLASS "Type should be trivially destructible!");
#include "clang/AST/TypeNodes.inc"

Expand Down
15 changes: 5 additions & 10 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ void TypePrinter::printConstantArrayAfter(const ConstantArrayType *T,
if (T->getSizeModifier() == ArraySizeModifier::Static)
OS << "static ";

OS << T->getSize().getZExtValue() << ']';
OS << T->getZExtSize() << ']';
printAfter(T->getElementType(), OS);
}

Expand Down Expand Up @@ -2303,15 +2303,10 @@ printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
} else {
if (!FirstArg)
OS << Comma;
if (!Policy.SuppressTagKeyword &&
Argument.getKind() == TemplateArgument::Type &&
isa<TagType>(Argument.getAsType()))
OS << Argument.getAsType().getAsString();
else
// Tries to print the argument with location info if exists.
printArgument(Arg, Policy, ArgOS,
TemplateParameterList::shouldIncludeTypeForArgument(
Policy, TPL, ParmIndex));
// Tries to print the argument with location info if exists.
printArgument(Arg, Policy, ArgOS,
TemplateParameterList::shouldIncludeTypeForArgument(
Policy, TPL, ParmIndex));
}
StringRef ArgString = ArgOS.str();

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Analysis/CFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2039,7 +2039,7 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) {
QualType QT = FI->getType();
// It may be a multidimensional array.
while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
if (AT->getSize() == 0)
if (AT->isZeroSize())
break;
QT = AT->getElementType();
}
Expand Down Expand Up @@ -2133,7 +2133,7 @@ bool CFGBuilder::hasTrivialDestructor(const VarDecl *VD) const {

// Check for constant size array. Set type to array element type.
while (const ConstantArrayType *AT = Context->getAsConstantArrayType(QT)) {
if (AT->getSize() == 0)
if (AT->isZeroSize())
return true;
QT = AT->getElementType();
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/FlowSensitive/AdornedCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ llvm::Expected<AdornedCFG> AdornedCFG::build(const Decl &D, Stmt &S,

// The shape of certain elements of the AST can vary depending on the
// language. We currently only support C++.
if (!C.getLangOpts().CPlusPlus)
if (!C.getLangOpts().CPlusPlus || C.getLangOpts().ObjC)
return llvm::createStringError(
std::make_error_code(std::errc::invalid_argument),
"Can only analyze C++");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ void Environment::initialize() {
assert(Parent != nullptr);

if (Parent->isLambda()) {
for (auto Capture : Parent->captures()) {
for (const auto &Capture : Parent->captures()) {
if (Capture.capturesVariable()) {
const auto *VarDecl = Capture.getCapturedVar();
assert(VarDecl != nullptr);
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Analysis/PathDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,17 @@ PathDiagnostic::PathDiagnostic(
StringRef CheckerName, const Decl *declWithIssue, StringRef bugtype,
StringRef verboseDesc, StringRef shortDesc, StringRef category,
PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique,
const Decl *AnalysisEntryPoint,
std::unique_ptr<FilesToLineNumsMap> ExecutedLines)
: CheckerName(CheckerName), DeclWithIssue(declWithIssue),
BugType(StripTrailingDots(bugtype)),
VerboseDesc(StripTrailingDots(verboseDesc)),
ShortDesc(StripTrailingDots(shortDesc)),
Category(StripTrailingDots(category)), UniqueingLoc(LocationToUnique),
UniqueingDecl(DeclToUnique), ExecutedLines(std::move(ExecutedLines)),
path(pathImpl) {}
UniqueingDecl(DeclToUnique), AnalysisEntryPoint(AnalysisEntryPoint),
ExecutedLines(std::move(ExecutedLines)), path(pathImpl) {
assert(AnalysisEntryPoint);
}

void PathDiagnosticConsumer::anchor() {}

Expand Down
8 changes: 4 additions & 4 deletions clang/lib/Analysis/UnsafeBufferUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -403,10 +403,11 @@ AST_MATCHER(CXXConstructExpr, isSafeSpanTwoParamConstruct) {
QualType Arg0Ty = Arg0->IgnoreImplicit()->getType();

if (Arg0Ty->isConstantArrayType()) {
const APInt &ConstArrSize = cast<ConstantArrayType>(Arg0Ty)->getSize();
const APSInt ConstArrSize =
APSInt(cast<ConstantArrayType>(Arg0Ty)->getSize());

// Check form 4:
return Arg1CV && APSInt::compareValues(APSInt(ConstArrSize), *Arg1CV) == 0;
return Arg1CV && APSInt::compareValues(ConstArrSize, *Arg1CV) == 0;
}
return false;
}
Expand All @@ -429,14 +430,13 @@ AST_MATCHER(ArraySubscriptExpr, isSafeArraySubscript) {
BaseDRE->getDecl()->getType());
if (!CATy)
return false;
const APInt ArrSize = CATy->getSize();

if (const auto *IdxLit = dyn_cast<IntegerLiteral>(Node.getIdx())) {
const APInt ArrIdx = IdxLit->getValue();
// FIXME: ArrIdx.isNegative() we could immediately emit an error as that's a
// bug
if (ArrIdx.isNonNegative() &&
ArrIdx.getLimitedValue() < ArrSize.getLimitedValue())
ArrIdx.getLimitedValue() < CATy->getLimitedSize())
return true;
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/ABIInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ bool ABIInfo::isZeroLengthBitfieldPermittedInHomogeneousAggregate() const {
bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
uint64_t &Members) const {
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
uint64_t NElements = AT->getSize().getZExtValue();
uint64_t NElements = AT->getZExtSize();
if (NElements == 0)
return false;
if (!isHomogeneousAggregate(AT->getElementType(), Base, Members))
Expand Down Expand Up @@ -98,7 +98,7 @@ bool ABIInfo::isHomogeneousAggregate(QualType Ty, const Type *&Base,
QualType FT = FD->getType();
while (const ConstantArrayType *AT =
getContext().getAsConstantArrayType(FT)) {
if (AT->getSize().getZExtValue() == 0)
if (AT->isZeroSize())
return false;
FT = AT->getElementType();
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/ABIInfoImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ bool CodeGen::isEmptyField(ASTContext &Context, const FieldDecl *FD,
bool WasArray = false;
if (AllowArrays)
while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
if (AT->getSize() == 0)
if (AT->isZeroSize())
return true;
FT = AT->getElementType();
// The [[no_unique_address]] special case below does not apply to
Expand Down Expand Up @@ -352,7 +352,7 @@ const Type *CodeGen::isSingleElementStruct(QualType T, ASTContext &Context) {

// Treat single element arrays as the element.
while (const ConstantArrayType *AT = Context.getAsConstantArrayType(FT)) {
if (AT->getSize().getZExtValue() != 1)
if (AT->getZExtSize() != 1)
break;
FT = AT->getElementType();
}
Expand Down
69 changes: 25 additions & 44 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,8 @@ EncompassingIntegerType(ArrayRef<struct WidthAndSignedness> Types) {

Value *CodeGenFunction::EmitVAStartEnd(Value *ArgValue, bool IsStart) {
Intrinsic::ID inst = IsStart ? Intrinsic::vastart : Intrinsic::vaend;
return Builder.CreateCall(CGM.getIntrinsic(inst), ArgValue);
return Builder.CreateCall(CGM.getIntrinsic(inst, {ArgValue->getType()}),
ArgValue);
}

/// Checks if using the result of __builtin_object_size(p, @p From) in place of
Expand Down Expand Up @@ -3018,7 +3019,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_va_copy: {
Value *DstPtr = EmitVAListRef(E->getArg(0)).getPointer();
Value *SrcPtr = EmitVAListRef(E->getArg(1)).getPointer();
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy), {DstPtr, SrcPtr});
Builder.CreateCall(CGM.getIntrinsic(Intrinsic::vacopy, {DstPtr->getType()}),
{DstPtr, SrcPtr});
return RValue::get(nullptr);
}
case Builtin::BIabs:
Expand Down Expand Up @@ -18066,15 +18068,22 @@ llvm::Value *CodeGenFunction::EmitScalarOrConstFoldImmArg(unsigned ICEArguments,
return Arg;
}

Intrinsic::ID getDotProductIntrinsic(QualType QT) {
Intrinsic::ID getDotProductIntrinsic(QualType QT, int elementCount) {
if (QT->hasFloatingRepresentation()) {
switch (elementCount) {
case 2:
return Intrinsic::dx_dot2;
case 3:
return Intrinsic::dx_dot3;
case 4:
return Intrinsic::dx_dot4;
}
}
if (QT->hasSignedIntegerRepresentation())
return Intrinsic::dx_sdot;
if (QT->hasUnsignedIntegerRepresentation())
return Intrinsic::dx_udot;

assert(QT->hasFloatingRepresentation());
return Intrinsic::dx_dot;
;
assert(QT->hasUnsignedIntegerRepresentation());
return Intrinsic::dx_udot;
}

Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Expand Down Expand Up @@ -18128,8 +18137,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
assert(T0->getScalarType() == T1->getScalarType() &&
"Dot product of vectors need the same element types.");

[[maybe_unused]] auto *VecTy0 =
E->getArg(0)->getType()->getAs<VectorType>();
auto *VecTy0 = E->getArg(0)->getType()->getAs<VectorType>();
[[maybe_unused]] auto *VecTy1 =
E->getArg(1)->getType()->getAs<VectorType>();
// A HLSLVectorTruncation should have happend
Expand All @@ -18138,7 +18146,8 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,

return Builder.CreateIntrinsic(
/*ReturnType=*/T0->getScalarType(),
getDotProductIntrinsic(E->getArg(0)->getType()),
getDotProductIntrinsic(E->getArg(0)->getType(),
VecTy0->getNumElements()),
ArrayRef<Value *>{Op0, Op1}, nullptr, "dx.dot");
} break;
case Builtin::BI__builtin_hlsl_lerp: {
Expand Down Expand Up @@ -18533,51 +18542,23 @@ Value *CodeGenFunction::EmitAMDGPUBuiltinExpr(unsigned BuiltinID,
}
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4bf16:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4f16:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8bf16:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8f16:
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16: {

llvm::Type *ArgTy;
Intrinsic::ID IID;
switch (BuiltinID) {
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_i32:
ArgTy = llvm::Type::getInt32Ty(getLLVMContext());
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b64_v2i32:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getInt32Ty(getLLVMContext()), 2);
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4bf16:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getBFloatTy(getLLVMContext()), 4);
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4f16:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getHalfTy(getLLVMContext()), 4);
IID = Intrinsic::amdgcn_global_load_tr_b64;
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v4i16:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getInt16Ty(getLLVMContext()), 4);
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8bf16:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getBFloatTy(getLLVMContext()), 8);
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8f16:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getHalfTy(getLLVMContext()), 8);
break;
case AMDGPU::BI__builtin_amdgcn_global_load_tr_b128_v8i16:
ArgTy = llvm::FixedVectorType::get(
llvm::Type::getInt16Ty(getLLVMContext()), 8);
IID = Intrinsic::amdgcn_global_load_tr_b128;
break;
}

llvm::Type *LoadTy = ConvertType(E->getType());
llvm::Value *Addr = EmitScalarExpr(E->getArg(0));
llvm::Function *F =
CGM.getIntrinsic(Intrinsic::amdgcn_global_load_tr, {ArgTy});
llvm::Function *F = CGM.getIntrinsic(IID, {LoadTy});
return Builder.CreateCall(F, {Addr});
}
case AMDGPU::BI__builtin_amdgcn_get_fpenv: {
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -933,8 +933,8 @@ struct NoExpansion : TypeExpansion {
static std::unique_ptr<TypeExpansion>
getTypeExpansion(QualType Ty, const ASTContext &Context) {
if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
return std::make_unique<ConstantArrayExpansion>(
AT->getElementType(), AT->getSize().getZExtValue());
return std::make_unique<ConstantArrayExpansion>(AT->getElementType(),
AT->getZExtSize());
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
SmallVector<const CXXBaseSpecifier *, 1> Bases;
Expand Down Expand Up @@ -3086,7 +3086,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
llvm::Align Alignment =
CGM.getNaturalTypeAlignment(ETy).getAsAlign();
AI->addAttrs(llvm::AttrBuilder(getLLVMContext()).addAlignmentAttr(Alignment));
uint64_t ArrSize = ArrTy->getSize().getZExtValue();
uint64_t ArrSize = ArrTy->getZExtSize();
if (!ETy->isIncompleteType() && ETy->isConstantSizeType() &&
ArrSize) {
llvm::AttrBuilder Attrs(getLLVMContext());
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3239,7 +3239,7 @@ llvm::DIType *CGDebugInfo::CreateType(const ArrayType *Ty, llvm::DIFile *Unit) {
// };
int64_t Count = -1; // Count == -1 is an unbounded array.
if (const auto *CAT = dyn_cast<ConstantArrayType>(Ty))
Count = CAT->getSize().getZExtValue();
Count = CAT->getZExtSize();
else if (const auto *VAT = dyn_cast<VariableArrayType>(Ty)) {
if (Expr *Size = VAT->getSizeExpr()) {
Expr::EvalResult Result;
Expand Down
21 changes: 19 additions & 2 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3663,12 +3663,29 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
// symbol in LTO mode.
void CodeGenFunction::EmitCfiCheckStub() {
llvm::Module *M = &CGM.getModule();
auto &Ctx = M->getContext();
ASTContext &C = getContext();
QualType QInt64Ty = C.getIntTypeForBitwidth(64, false);

FunctionArgList FnArgs;
ImplicitParamDecl ArgCallsiteTypeId(C, QInt64Ty, ImplicitParamKind::Other);
ImplicitParamDecl ArgAddr(C, C.VoidPtrTy, ImplicitParamKind::Other);
ImplicitParamDecl ArgCFICheckFailData(C, C.VoidPtrTy,
ImplicitParamKind::Other);
FnArgs.push_back(&ArgCallsiteTypeId);
FnArgs.push_back(&ArgAddr);
FnArgs.push_back(&ArgCFICheckFailData);
const CGFunctionInfo &FI =
CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, FnArgs);

llvm::Function *F = llvm::Function::Create(
llvm::FunctionType::get(VoidTy, {Int64Ty, Int8PtrTy, Int8PtrTy}, false),
llvm::FunctionType::get(VoidTy, {Int64Ty, VoidPtrTy, VoidPtrTy}, false),
llvm::GlobalValue::WeakAnyLinkage, "__cfi_check", M);
CGM.SetLLVMFunctionAttributes(GlobalDecl(), FI, F, /*IsThunk=*/false);
CGM.SetLLVMFunctionAttributesForDefinition(nullptr, F);
F->setAlignment(llvm::Align(4096));
CGM.setDSOLocal(F);

llvm::LLVMContext &Ctx = M->getContext();
llvm::BasicBlock *BB = llvm::BasicBlock::Create(Ctx, "entry", F);
// CrossDSOCFI pass is not executed if there is no executable code.
SmallVector<llvm::Value*> Args{F->getArg(2), F->getArg(1)};
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/CodeGen/CGExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1073,8 +1073,7 @@ void CodeGenFunction::EmitNewArrayInitializer(
// Move past these elements.
InitListElements =
cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe())
->getSize()
.getZExtValue();
->getZExtSize();
CurPtr = Builder.CreateConstInBoundsGEP(
CurPtr, InitListElements, "string.init.end");

Expand Down Expand Up @@ -1591,8 +1590,7 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
isa<StringLiteral>(IgnoreParen) || isa<ObjCEncodeExpr>(IgnoreParen)) {
minElements =
cast<ConstantArrayType>(Init->getType()->getAsArrayTypeUnsafe())
->getSize()
.getZExtValue();
->getZExtSize();
} else if (ILE || CPLIE) {
minElements = ILE ? ILE->getNumInits() : CPLIE->getInitExprs().size();
}
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
}

unsigned NumElementsToUpdate =
FillC ? CAT->getSize().getZExtValue() : Updater->getNumInits();
FillC ? CAT->getZExtSize() : Updater->getNumInits();
for (unsigned I = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) {
Expr *Init = nullptr;
if (I < Updater->getNumInits())
Expand Down Expand Up @@ -1249,7 +1249,7 @@ class ConstExprEmitter :
auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType());
assert(CAT && "can't emit array init for non-constant-bound array");
unsigned NumInitElements = ILE->getNumInits();
unsigned NumElements = CAT->getSize().getZExtValue();
unsigned NumElements = CAT->getZExtSize();

// Initialising an array requires us to automatically
// initialise any elements that have not been initialised explicitly
Expand Down Expand Up @@ -1374,7 +1374,7 @@ class ConstExprEmitter :

// Resize the string to the right size, adding zeros at the end, or
// truncating as needed.
Str.resize(CAT->getSize().getZExtValue(), '\0');
Str.resize(CAT->getZExtSize(), '\0');
return llvm::ConstantDataArray::getString(VMContext, Str, false);
}

Expand Down Expand Up @@ -2382,7 +2382,7 @@ llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {

llvm::Constant *Element =
ConstantEmitter::emitNullForMemory(*this, ElementTy);
unsigned NumElements = CAT->getSize().getZExtValue();
unsigned NumElements = CAT->getZExtSize();
SmallVector<llvm::Constant *, 8> Array(NumElements, Element);
return llvm::ConstantArray::get(ATy, Array);
}
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGObjCMac.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2501,12 +2501,12 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,

if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
auto *CArray = cast<ConstantArrayType>(Array);
uint64_t ElCount = CArray->getSize().getZExtValue();
uint64_t ElCount = CArray->getZExtSize();
assert(CArray && "only array with known element size is supported");
FQT = CArray->getElementType();
while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
auto *CArray = cast<ConstantArrayType>(Array);
ElCount *= CArray->getSize().getZExtValue();
ElCount *= CArray->getZExtSize();
FQT = CArray->getElementType();
}
if (FQT->isRecordType() && ElCount) {
Expand Down Expand Up @@ -5326,7 +5326,7 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field,
}
// Unlike incomplete arrays, constant arrays can be nested.
while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
numElts *= arrayType->getSize().getZExtValue();
numElts *= arrayType->getZExtSize();
fieldType = arrayType->getElementType();
}

Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6796,7 +6796,7 @@ class MappableExprsHandler {
OASE->getBase()->IgnoreParenImpCasts())
.getCanonicalType();
if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr()))
return ATy->getSize().getSExtValue() != 1;
return ATy->getSExtSize() != 1;
// If we don't have a constant dimension length, we have to consider
// the current section as having any size, so it is not necessarily
// unitary. If it happen to be unity size, that's user fault.
Expand Down Expand Up @@ -7546,8 +7546,8 @@ class MappableExprsHandler {
// it.
if (DimSizes.size() < Components.size() - 1) {
if (CAT)
DimSizes.push_back(llvm::ConstantInt::get(
CGF.Int64Ty, CAT->getSize().getZExtValue()));
DimSizes.push_back(
llvm::ConstantInt::get(CGF.Int64Ty, CAT->getZExtSize()));
else if (VAT)
DimSizes.push_back(CGF.Builder.CreateIntCast(
CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty,
Expand Down
7 changes: 3 additions & 4 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2189,8 +2189,8 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
dyn_cast<llvm::ArrayType>(addr.getElementType());
while (llvmArrayType) {
assert(isa<ConstantArrayType>(arrayType));
assert(cast<ConstantArrayType>(arrayType)->getSize().getZExtValue()
== llvmArrayType->getNumElements());
assert(cast<ConstantArrayType>(arrayType)->getZExtSize() ==
llvmArrayType->getNumElements());

gepIndices.push_back(zero);
countFromCLAs *= llvmArrayType->getNumElements();
Expand All @@ -2208,8 +2208,7 @@ llvm::Value *CodeGenFunction::emitArrayLength(const ArrayType *origArrayType,
// as some other type (probably a packed struct). Compute the array
// size, and just emit the 'begin' expression as a bitcast.
while (arrayType) {
countFromCLAs *=
cast<ConstantArrayType>(arrayType)->getSize().getZExtValue();
countFromCLAs *= cast<ConstantArrayType>(arrayType)->getZExtSize();
eltType = arrayType->getElementType();
arrayType = getContext().getAsArrayType(eltType);
}
Expand Down
Loading