81 changes: 71 additions & 10 deletions bolt/lib/Profile/YAMLProfileReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ namespace opts {
extern cl::opt<unsigned> Verbosity;
extern cl::OptionCategory BoltOptCategory;
extern cl::opt<bool> InferStaleProfile;
extern cl::opt<bool> Lite;

static llvm::cl::opt<bool>
IgnoreHash("profile-ignore-hash",
cl::desc("ignore hash while reading function profile"),
cl::Hidden, cl::cat(BoltOptCategory));

llvm::cl::opt<bool>
MatchProfileWithFunctionHash("match-profile-with-function-hash",
cl::desc("Match profile with function hash"),
cl::Hidden, cl::cat(BoltOptCategory));

llvm::cl::opt<bool> ProfileUseDFS("profile-use-dfs",
cl::desc("use DFS order for YAML profile"),
cl::Hidden, cl::cat(BoltOptCategory));
Expand Down Expand Up @@ -329,6 +335,8 @@ Error YAMLProfileReader::preprocessProfile(BinaryContext &BC) {
}

bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) {
if (opts::MatchProfileWithFunctionHash)
return true;
for (StringRef Name : BF.getNames())
if (ProfileFunctionNames.contains(Name))
return true;
Expand Down Expand Up @@ -363,9 +371,24 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
return Profile.Hash == static_cast<uint64_t>(BF.getHash());
};

// We have to do 2 passes since LTO introduces an ambiguity in function
// names. The first pass assigns profiles that match 100% by name and
// by hash. The second pass allows name ambiguity for LTO private functions.
uint64_t MatchedWithExactName = 0;
uint64_t MatchedWithHash = 0;
uint64_t MatchedWithLTOCommonName = 0;

// Computes hash for binary functions.
if (opts::MatchProfileWithFunctionHash) {
for (auto &[_, BF] : BC.getBinaryFunctions()) {
BF.computeHash(YamlBP.Header.IsDFSOrder, YamlBP.Header.HashFunction);
}
} else if (!opts::IgnoreHash) {
for (BinaryFunction *BF : ProfileBFs) {
if (!BF)
continue;
BF->computeHash(YamlBP.Header.IsDFSOrder, YamlBP.Header.HashFunction);
}
}

// This first pass assigns profiles that match 100% by name and by hash.
for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs)) {
if (!BF)
continue;
Expand All @@ -374,15 +397,35 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
// the profile.
Function.setExecutionCount(BinaryFunction::COUNT_NO_PROFILE);

// Recompute hash once per function.
if (!opts::IgnoreHash)
Function.computeHash(YamlBP.Header.IsDFSOrder,
YamlBP.Header.HashFunction);

if (profileMatches(YamlBF, Function))
if (profileMatches(YamlBF, Function)) {
matchProfileToFunction(YamlBF, Function);
++MatchedWithExactName;
}
}

// Iterates through profiled functions to match the first binary function with
// the same exact hash. Serves to match identical, renamed functions.
// Collisions are possible where multiple functions share the same exact hash.
if (opts::MatchProfileWithFunctionHash) {
DenseMap<size_t, BinaryFunction *> StrictHashToBF;
StrictHashToBF.reserve(BC.getBinaryFunctions().size());

for (auto &[_, BF] : BC.getBinaryFunctions())
StrictHashToBF[BF.getHash()] = &BF;

for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) {
if (YamlBF.Used)
continue;
auto It = StrictHashToBF.find(YamlBF.Hash);
if (It != StrictHashToBF.end() && !ProfiledFunctions.count(It->second)) {
BinaryFunction *BF = It->second;
matchProfileToFunction(YamlBF, *BF);
++MatchedWithHash;
}
}
}

// This second pass allows name ambiguity for LTO private functions.
for (const auto &[CommonName, LTOProfiles] : LTOCommonNameMap) {
if (!LTOCommonNameFunctionMap.contains(CommonName))
continue;
Expand All @@ -396,6 +439,7 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
for (BinaryFunction *BF : Functions) {
if (!ProfiledFunctions.count(BF) && profileMatches(*YamlBF, *BF)) {
matchProfileToFunction(*YamlBF, *BF);
++MatchedWithLTOCommonName;
return true;
}
}
Expand All @@ -407,8 +451,10 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
// partially.
if (!ProfileMatched && LTOProfiles.size() == 1 && Functions.size() == 1 &&
!LTOProfiles.front()->Used &&
!ProfiledFunctions.count(*Functions.begin()))
!ProfiledFunctions.count(*Functions.begin())) {
matchProfileToFunction(*LTOProfiles.front(), **Functions.begin());
++MatchedWithLTOCommonName;
}
}

for (auto [YamlBF, BF] : llvm::zip_equal(YamlBP.Functions, ProfileBFs))
Expand All @@ -420,6 +466,15 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {
errs() << "BOLT-WARNING: profile ignored for function " << YamlBF.Name
<< '\n';

if (opts::Verbosity >= 1) {
outs() << "BOLT-INFO: matched " << MatchedWithExactName
<< " functions with identical names\n";
outs() << "BOLT-INFO: matched " << MatchedWithHash
<< " functions with hash\n";
outs() << "BOLT-INFO: matched " << MatchedWithLTOCommonName
<< " functions with matching LTO common names\n";
}

// Set for parseFunctionProfile().
NormalizeByInsnCount = usesEvent("cycles") || usesEvent("instructions");
NormalizeByCalls = usesEvent("branches");
Expand All @@ -439,6 +494,12 @@ Error YAMLProfileReader::readProfile(BinaryContext &BC) {

BC.setNumUnusedProfiledObjects(NumUnused);

if (opts::Lite && opts::MatchProfileWithFunctionHash) {
for (BinaryFunction *BF : BC.getAllBinaryFunctions())
if (!BF->hasProfile())
BF->setIgnored();
}

return Error::success();
}

Expand Down
7 changes: 4 additions & 3 deletions bolt/lib/Rewrite/DWARFRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/ObjectFile.h"
Expand Down Expand Up @@ -1351,7 +1351,7 @@ void DWARFRewriter::updateDWARFObjectAddressRanges(
}
}

void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
void DWARFRewriter::updateLineTableOffsets(const MCAssembler &Asm) {
ErrorOr<BinarySection &> DbgInfoSection =
BC.getUniqueSectionByName(".debug_info");
ErrorOr<BinarySection &> TypeInfoSection =
Expand Down Expand Up @@ -1392,7 +1392,8 @@ void DWARFRewriter::updateLineTableOffsets(const MCAsmLayout &Layout) {
if (!StmtOffset)
continue;

const uint64_t LineTableOffset = Layout.getSymbolOffset(*Label);
const uint64_t LineTableOffset =
Asm.getSymbolOffset(*Label);
DebugLineOffsetMap[*StmtOffset] = LineTableOffset;
assert(DbgInfoSection && ".debug_info section must exist");
LineTablePatchMap[CU.get()] = LineTableOffset;
Expand Down
32 changes: 3 additions & 29 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCObjectStreamer.h"
#include "llvm/MC/MCStreamer.h"
Expand Down Expand Up @@ -76,12 +75,12 @@ extern cl::opt<bool> X86AlignBranchWithin32BBoundaries;

namespace opts {

extern cl::opt<MacroFusionType> AlignMacroOpFusion;
extern cl::list<std::string> HotTextMoveSections;
extern cl::opt<bool> Hugify;
extern cl::opt<bool> Instrument;
extern cl::opt<JumpTableSupportLevel> JumpTables;
extern cl::opt<bool> KeepNops;
extern cl::opt<bool> Lite;
extern cl::list<std::string> ReorderData;
extern cl::opt<bolt::ReorderFunctions::ReorderType> ReorderFunctions;
extern cl::opt<bool> TerminalTrap;
Expand Down Expand Up @@ -140,9 +139,6 @@ KeepTmp("keep-tmp",
cl::Hidden,
cl::cat(BoltCategory));

cl::opt<bool> Lite("lite", cl::desc("skip processing of cold functions"),
cl::cat(BoltCategory));

static cl::opt<unsigned>
LiteThresholdPct("lite-threshold-pct",
cl::desc("threshold (in percent) for selecting functions to process in lite "
Expand Down Expand Up @@ -1972,12 +1968,6 @@ void RewriteInstance::adjustCommandLineOptions() {
if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
RtLibrary->adjustCommandLineOptions(*BC);

if (opts::AlignMacroOpFusion != MFT_NONE && !BC->isX86()) {
BC->outs()
<< "BOLT-INFO: disabling -align-macro-fusion on non-x86 platform\n";
opts::AlignMacroOpFusion = MFT_NONE;
}

if (BC->isX86() && BC->MAB->allowAutoPadding()) {
if (!BC->HasRelocations) {
BC->errs()
Expand All @@ -1988,13 +1978,6 @@ void RewriteInstance::adjustCommandLineOptions() {
BC->outs()
<< "BOLT-WARNING: using mitigation for Intel JCC erratum, layout "
"may take several minutes\n";
opts::AlignMacroOpFusion = MFT_NONE;
}

if (opts::AlignMacroOpFusion != MFT_NONE && !BC->HasRelocations) {
BC->outs() << "BOLT-INFO: disabling -align-macro-fusion in non-relocation "
"mode\n";
opts::AlignMacroOpFusion = MFT_NONE;
}

if (opts::SplitEH && !BC->HasRelocations) {
Expand All @@ -2016,14 +1999,6 @@ void RewriteInstance::adjustCommandLineOptions() {
opts::StrictMode = true;
}

if (BC->isX86() && BC->HasRelocations &&
opts::AlignMacroOpFusion == MFT_HOT && !ProfileReader) {
BC->outs()
<< "BOLT-INFO: enabling -align-macro-fusion=all since no profile "
"was specified\n";
opts::AlignMacroOpFusion = MFT_ALL;
}

if (!BC->HasRelocations &&
opts::ReorderFunctions != ReorderFunctions::RT_NONE) {
BC->errs() << "BOLT-ERROR: function reordering only works when "
Expand Down Expand Up @@ -3510,9 +3485,8 @@ void RewriteInstance::emitAndLink() {
updateOutputValues(*Linker);

if (opts::UpdateDebugSections) {
MCAsmLayout FinalLayout(
static_cast<MCObjectStreamer *>(Streamer.get())->getAssembler());
DebugInfoRewriter->updateLineTableOffsets(FinalLayout);
DebugInfoRewriter->updateLineTableOffsets(
static_cast<MCObjectStreamer &>(*Streamer).getAssembler());
}

if (RuntimeLibrary *RtLibrary = BC->getRuntimeLibrary())
Expand Down
4 changes: 0 additions & 4 deletions bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,6 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
*AArch64ExprB.getSubExpr(), Comp);
}

bool isMacroOpFusionPair(ArrayRef<MCInst> Insts) const override {
return false;
}

bool shortenInstruction(MCInst &, const MCSubtargetInfo &) const override {
return false;
}
Expand Down
34 changes: 0 additions & 34 deletions bolt/lib/Target/X86/X86MCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -661,40 +661,6 @@ class X86MCPlusBuilder : public MCPlusBuilder {
return (Desc.TSFlags & X86II::EncodingMask) == X86II::EVEX;
}

bool isMacroOpFusionPair(ArrayRef<MCInst> Insts) const override {
const auto *I = Insts.begin();
while (I != Insts.end() && isPrefix(*I))
++I;
if (I == Insts.end())
return false;

const MCInst &FirstInst = *I;
++I;
while (I != Insts.end() && isPrefix(*I))
++I;
if (I == Insts.end())
return false;
const MCInst &SecondInst = *I;

if (!isConditionalBranch(SecondInst))
return false;
// Cannot fuse if the first instruction uses RIP-relative memory.
if (hasPCRelOperand(FirstInst))
return false;

const X86::FirstMacroFusionInstKind CmpKind =
X86::classifyFirstOpcodeInMacroFusion(FirstInst.getOpcode());
if (CmpKind == X86::FirstMacroFusionInstKind::Invalid)
return false;

X86::CondCode CC = static_cast<X86::CondCode>(getCondCode(SecondInst));
X86::SecondMacroFusionInstKind BranchKind =
X86::classifySecondCondCodeInMacroFusion(CC);
if (BranchKind == X86::SecondMacroFusionInstKind::Invalid)
return false;
return X86::isMacroFused(CmpKind, BranchKind);
}

std::optional<X86MemOperand>
evaluateX86MemoryOperand(const MCInst &Inst) const override {
int MemOpNo = getMemoryOperandNo(Inst);
Expand Down
3 changes: 3 additions & 0 deletions bolt/lib/Utils/CommandLineOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ cl::opt<bool>
cl::desc("instrument code to generate accurate profile data"),
cl::cat(BoltOptCategory));

cl::opt<bool> Lite("lite", cl::desc("skip processing of cold functions"),
cl::cat(BoltCategory));

cl::opt<std::string>
OutputFilename("o",
cl::desc("<output file>"),
Expand Down
63 changes: 63 additions & 0 deletions bolt/test/X86/hashing-based-function-matching.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
## Tests function matching in YAMLProfileReader by function hash.

# REQUIRES: system-linux
# RUN: split-file %s %t
# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %t/main.s -o %t.o
# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -nostdlib
# RUN: llvm-bolt %t.exe -o %t.out --data %t/yaml -v=2 \
# RUN: --print-cfg --match-profile-with-function-hash --profile-ignore-hash=0 2>&1 | FileCheck %s

# CHECK: BOLT-INFO: matched 1 functions with hash

#--- main.s
.globl main
.type main, @function
main:
.cfi_startproc
.LBB00:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
testq %rax, %rax
js .LBB03
.LBB01:
jne .LBB04
.LBB02:
nop
.LBB03:
xorl %eax, %eax
addq $16, %rsp
popq %rbp
retq
.LBB04:
xorl %eax, %eax
addq $16, %rsp
popq %rbp
retq
## For relocations against .text
.reloc 0, R_X86_64_NONE
.cfi_endproc
.size main, .-main

#--- yaml
---
header:
profile-version: 1
binary-name: 'hashing-based-function-matching.s.tmp.exe'
binary-build-id: '<unknown>'
profile-flags: [ lbr ]
profile-origin: branch profile reader
profile-events: ''
dfs-order: false
hash-func: xxh3
functions:
- name: main2
fid: 0
hash: 0x6E7F15254DE2478
exec: 1
nblocks: 6
blocks:
- bid: 1
insns: 1
succ: [ { bid: 3, cnt: 1} ]
...
1 change: 1 addition & 0 deletions bolt/test/X86/reader-stale-yaml-std.test
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# UNSUPPORTED: true
## This script checks that YamlProfileReader in llvm-bolt is reading data
## correctly and stale data is corrected by profile inference.

Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/clang-doc/HTMLGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,9 +993,9 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
});
});
};
OS << "var JsonIndex = `\n";
OS << "async function LoadIndex() {\nreturn";
IndexToJSON(CDCtx.Idx);
OS << "`;\n";
OS << ";\n}";
return llvm::Error::success();
}

Expand Down
8 changes: 4 additions & 4 deletions clang-tools-extra/clang-doc/assets/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ function createIndex(Index) {

// Runs after DOM loads
document.addEventListener("DOMContentLoaded", function() {
// JsonIndex is a variable from another file that contains the index
// in JSON format
var Index = JSON.parse(JsonIndex);
createIndex(Index);
// LoadIndex is an asynchronous function that will be generated clang-doc.
// It ensures that the function call will not block as soon the page loads,
// since the index object are often huge and can contain thousands of lines.
LoadIndex().then((Index) => { createIndex(Index); });
});
21 changes: 12 additions & 9 deletions clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
} else if (const auto *E =
Result.Nodes.getNodeAs<Expr>("sizeof-integer-call")) {
diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
"that results in an integer")
"of integer type")
<< E->getSourceRange();
} else if (const auto *E = Result.Nodes.getNodeAs<Expr>("sizeof-this")) {
diag(E->getBeginLoc(),
Expand All @@ -314,7 +314,7 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
<< E->getSourceRange();
} else {
diag(E->getBeginLoc(), "suspicious usage of 'sizeof()' on an expression "
"that results in a pointer")
"of pointer type")
<< E->getSourceRange();
}
} else if (const auto *E = Result.Nodes.getNodeAs<BinaryOperator>(
Expand Down Expand Up @@ -348,25 +348,28 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) {
} else if (ElementSize > CharUnits::Zero() &&
DenominatorSize > CharUnits::Zero() &&
ElementSize != DenominatorSize) {
diag(E->getOperatorLoc(), "suspicious usage of 'sizeof(...)/sizeof(...)';"
" numerator is not a multiple of denominator")
// FIXME: Apparently there are no testcases that cover this branch!
diag(E->getOperatorLoc(),
"suspicious usage of 'sizeof(array)/sizeof(...)';"
" denominator differs from the size of array elements")
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
} else if (NumTy && DenomTy && NumTy == DenomTy) {
// FIXME: This message is wrong, it should not refer to sizeof "pointer"
// usage (and by the way, it would be to clarify all the messages).
diag(E->getOperatorLoc(),
"suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'")
"suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions "
"have the same type")
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
} else if (!WarnOnSizeOfPointer) {
// When 'WarnOnSizeOfPointer' is enabled, these messages become redundant:
if (PointedTy && DenomTy && PointedTy == DenomTy) {
diag(E->getOperatorLoc(),
"suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'")
"suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer "
"is divided by size of pointed type")
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
} else if (NumTy && DenomTy && NumTy->isPointerType() &&
DenomTy->isPointerType()) {
diag(E->getOperatorLoc(),
"suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'")
"suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions "
"have pointer types")
<< E->getLHS()->getSourceRange() << E->getRHS()->getSourceRange();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,30 @@
//===----------------------------------------------------------------------===//

#include "AvoidNonConstGlobalVariablesCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"

using namespace clang::ast_matchers;

namespace clang::tidy::cppcoreguidelines {

AvoidNonConstGlobalVariablesCheck::AvoidNonConstGlobalVariablesCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
AllowInternalLinkage(Options.get("AllowInternalLinkage", false)) {}

void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {
auto NamespaceMatcher = AllowInternalLinkage
? namespaceDecl(unless(isAnonymous()))
: namespaceDecl();
auto GlobalContext =
varDecl(hasGlobalStorage(),
hasDeclContext(anyOf(namespaceDecl(), translationUnitDecl())));
hasDeclContext(anyOf(NamespaceMatcher, translationUnitDecl())));

auto GlobalVariable = varDecl(
GlobalContext,
AllowInternalLinkage ? varDecl(unless(isStaticStorageClass()))
: varDecl(),
unless(anyOf(
isConstexpr(), hasType(isConstQualified()),
hasType(referenceType())))); // References can't be changed, only the
Expand All @@ -43,7 +52,6 @@ void AvoidNonConstGlobalVariablesCheck::registerMatchers(MatchFinder *Finder) {

void AvoidNonConstGlobalVariablesCheck::check(
const MatchFinder::MatchResult &Result) {

if (const auto *Variable =
Result.Nodes.getNodeAs<VarDecl>("non-const_variable")) {
diag(Variable->getLocation(), "variable %0 is non-const and globally "
Expand All @@ -63,4 +71,9 @@ void AvoidNonConstGlobalVariablesCheck::check(
}
}

void AvoidNonConstGlobalVariablesCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "AllowInternalLinkage", AllowInternalLinkage);
}

} // namespace clang::tidy::cppcoreguidelines
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,13 @@ namespace clang::tidy::cppcoreguidelines {
/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables.html
class AvoidNonConstGlobalVariablesCheck : public ClangTidyCheck {
public:
AvoidNonConstGlobalVariablesCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {}
AvoidNonConstGlobalVariablesCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;

private:
const bool AllowInternalLinkage;
};

} // namespace clang::tidy::cppcoreguidelines
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ formatIncremental(llvm::StringRef OriginalCode, unsigned OriginalCursor,
// Never *remove* lines in response to pressing enter! This annoys users.
if (InsertedText == "\n") {
Style.MaxEmptyLinesToKeep = 1000;
Style.KeepEmptyLinesAtTheStartOfBlocks = true;
Style.KeepEmptyLines.AtStartOfBlock = true;
}

// Compute the code we want to format:
Expand Down
13 changes: 9 additions & 4 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,10 @@ Changes in existing checks
false positives resulting from use of optionals in unevaluated context.

- Improved :doc:`bugprone-sizeof-expression
<clang-tidy/checks/bugprone/sizeof-expression>` check by eliminating some
false positives and adding a new (off-by-default) option
`WarnOnSizeOfPointer` that reports all ``sizeof(pointer)`` expressions
(except for a few that are idiomatic).
<clang-tidy/checks/bugprone/sizeof-expression>` check by clarifying the
diagnostics, eliminating some false positives and adding a new
(off-by-default) option `WarnOnSizeOfPointer` that reports all
``sizeof(pointer)`` expressions (except for a few that are idiomatic).

- Improved :doc:`bugprone-suspicious-include
<clang-tidy/checks/bugprone/suspicious-include>` check by replacing the local
Expand All @@ -269,6 +269,11 @@ Changes in existing checks
<clang-tidy/checks/bugprone/use-after-move>` check to also handle
calls to ``std::forward``.

- Improved :doc:`cppcoreguidelines-avoid-non-const-global-variables
<clang-tidy/checks/cppcoreguidelines/avoid-non-const-global-variables>` check
with a new option `AllowInternalLinkage` to disable the warning for variables
with internal linkage.

- Improved :doc:`cppcoreguidelines-macro-usage
<clang-tidy/checks/cppcoreguidelines/macro-usage>` check by ignoring macro with
hash preprocessing token.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,11 @@ The variables ``a``, ``c``, ``c_ptr1``, ``c_const_ptr`` and ``c_reference``
will all generate warnings since they are either a non-const globally accessible
variable, a pointer or a reference providing global access to non-const data
or both.

Options
-------

.. option:: AllowInternalLinkage

When set to `true`, static non-const variables and variables in anonymous
namespaces will not generate a warning. The default value is `false`.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
cppcoreguidelines-pro-type-member-init
======================================

The check flags user-defined constructor definitions that do not
The check flags user-provided constructor definitions that do not
initialize all fields that would be left in an undefined state by
default construction, e.g. builtins, pointers and record types without
user-provided default constructors containing at least one such
Expand Down
7 changes: 4 additions & 3 deletions clang-tools-extra/test/clang-doc/basic-project.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Rectangle.html -check-prefix=HTML-RECTANGLE
// RUN: FileCheck %s -input-file=%t/docs/GlobalNamespace/Circle.html -check-prefix=HTML-CIRCLE

// JSON-INDEX: var JsonIndex = `
// JSON-INDEX-NEXT: {
// JSON-INDEX: async function LoadIndex() {
// JSON-INDEX-NEXT: return{
// JSON-INDEX-NEXT: "USR": "{{([0-9A-F]{40})}}",
// JSON-INDEX-NEXT: "Name": "",
// JSON-INDEX-NEXT: "RefType": "default",
Expand Down Expand Up @@ -51,7 +51,8 @@
// JSON-INDEX-NEXT: ]
// JSON-INDEX-NEXT: }
// JSON-INDEX-NEXT: ]
// JSON-INDEX-NEXT: }`;
// JSON-INDEX-NEXT: };
// JSON-INDEX-NEXT: }

// HTML-SHAPE: <!DOCTYPE html>
// HTML-SHAPE-NEXT: <meta charset="utf-8"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,24 @@ int Test5() {

int sum = 0;
sum += sizeof(&S);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(__typeof(&S));
sum += sizeof(&TS);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(__typeof(&TS));
sum += sizeof(STRKWD MyStruct*);
sum += sizeof(__typeof(STRKWD MyStruct*));
sum += sizeof(TypedefStruct*);
sum += sizeof(__typeof(TypedefStruct*));
sum += sizeof(PTTS);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PMyStruct);
sum += sizeof(PS);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PS2);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&A10);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type

#ifdef __cplusplus
MyStruct &rS = S;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,17 @@ int Test1(const char* ptr) {
sum += sizeof(sum, LEN);
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(..., ...)'
sum += sizeof(AsBool());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(AsInt());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(AsEnum());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(AsEnumClass());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(M{}.AsInt());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(M{}.AsEnum());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(sizeof(X));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
sum += sizeof(LEN + sizeof(X));
Expand All @@ -62,7 +62,7 @@ int Test1(const char* ptr) {
sum += sizeof(LEN + - + -sizeof(X));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
sum += sizeof(char) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(A) / sizeof(S);
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
sum += sizeof(char) / sizeof(int);
Expand All @@ -72,21 +72,21 @@ int Test1(const char* ptr) {
sum += sizeof(B[0]) / sizeof(A);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
sum += sizeof(ptr) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(ptr) / sizeof(ptr[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(ptr) / sizeof(char*);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(ptr) / sizeof(void*);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(ptr) / sizeof(const void volatile*);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(ptr) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(int) * sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
sum += sizeof(ptr) * sizeof(ptr[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
sum += sizeof(int) * (2 * sizeof(char));
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
Expand Down Expand Up @@ -127,54 +127,54 @@ int Test5() {

int sum = 0;
sum += sizeof(&S.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&kGlocalMyStruct.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&kGlocalMyStructPtr->arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(S.arr + 0);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(+ S.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof((int*)S.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type

sum += sizeof(S.ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(kGlocalMyStruct.ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(kGlocalMyStructPtr->ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type

sum += sizeof(&kGlocalMyStruct);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&S);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(MyStruct*);
sum += sizeof(PMyStruct);
sum += sizeof(PS);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PS2);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&A10);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PtrArray) / sizeof(PtrArray[1]);
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(A10) / sizeof(PtrArray[0]);
sum += sizeof(PC) / sizeof(PtrArray[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(ArrayC) / sizeof(PtrArray[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator

sum += sizeof(PChar);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PInt);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PPInt);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PPMyStruct);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type

return sum;
}
Expand All @@ -200,9 +200,9 @@ void GenericFunctionTest() {
// reported by the `sizeof(pointer)` checks, but this causes some false
// positives, so it would be good to create an exception for them.
some_generic_function(&IntPP, sizeof(IntP));
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:33: warning: suspicious usage of 'sizeof()' on an expression of pointer type
some_generic_function(&ClassPP, sizeof(ClassP));
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type
}

int ValidExpressions() {
Expand All @@ -222,7 +222,7 @@ int ValidExpressions() {
sum += sizeof(A[sizeof(A) / sizeof(int)]);
// Here the outer sizeof is reported, but the inner ones are accepted:
sum += sizeof(&A[sizeof(A) / sizeof(int)]);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(sizeof(0)); // Special case: sizeof size_t.
sum += sizeof(void*);
sum += sizeof(void const *);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ int Test5() {
sum += sizeof(A10) / sizeof(PtrArray[0]);
// No warning.
sum += sizeof(PC) / sizeof(PtrArray[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(ArrayC) / sizeof(PtrArray[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ bool TestTrait2() {
template <class T>
bool TestTrait3() {
return sizeof(ReturnOverload(0)) == sizeof(T{});
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
}

template <class T>
bool TestTrait4() {
return sizeof(ReturnTemplate(0)) == sizeof(T{});
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
}

bool TestTemplates() {
Expand All @@ -79,17 +79,17 @@ int Test1(const char* ptr) {
sum += sizeof(sum, LEN);
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(..., ...)'
sum += sizeof(AsBool());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(AsInt());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(AsEnum());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(AsEnumClass());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(M{}.AsInt());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(M{}.AsEnum());
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
sum += sizeof(sizeof(X));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
sum += sizeof(LEN + sizeof(X));
Expand All @@ -103,7 +103,7 @@ int Test1(const char* ptr) {
sum += sizeof(LEN + - + -sizeof(X));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
sum += sizeof(char) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(A) / sizeof(S);
// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
sum += sizeof(char) / sizeof(int);
Expand All @@ -113,17 +113,17 @@ int Test1(const char* ptr) {
sum += sizeof(B[0]) / sizeof(A);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
sum += sizeof(ptr) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type
sum += sizeof(ptr) / sizeof(ptr[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type
sum += sizeof(ptr) / sizeof(char*);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types
sum += sizeof(ptr) / sizeof(void*);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types
sum += sizeof(ptr) / sizeof(const void volatile*);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types
sum += sizeof(ptr) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type
sum += sizeof(int) * sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
sum += sizeof(ptr) * sizeof(ptr[0]);
Expand Down Expand Up @@ -156,11 +156,11 @@ int CE4 = sizeof sizeof(MyConstChar);
int Test2(MyConstChar* A) {
int sum = 0;
sum += sizeof(MyConstChar) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(MyConstChar) / sizeof(MyChar);
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(A[0]) / sizeof(char);
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
return sum;
}

Expand All @@ -169,7 +169,7 @@ int Foo() { int A[T]; return sizeof(T); }
// CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'
template <typename T>
int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); }
// CHECK-MESSAGES: :[[@LINE-1]]:41: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:41: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
int Test3() { return Foo<42>() + Bar<char>(); }

static const char* kABC = "abc";
Expand Down Expand Up @@ -211,43 +211,43 @@ int Test5() {

int sum = 0;
sum += sizeof(&S.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&kGlocalMyStruct.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&kGlocalMyStructPtr->arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(S.arr + 0);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(+ S.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof((int*)S.arr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type

sum += sizeof(S.ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(kGlocalMyStruct.ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(kGlocalMyStructPtr->ptr);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type

sum += sizeof(&kGlocalMyStruct);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&S);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(MyStruct*);
sum += sizeof(PMyStruct);
sum += sizeof(PS);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PS2);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(&A10);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(PtrArray) / sizeof(PtrArray[1]);
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type
sum += sizeof(A10) / sizeof(PtrArray[0]);
sum += sizeof(PC) / sizeof(PtrArray[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
// CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
sum += sizeof(ArrayC) / sizeof(PtrArray[0]);
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator

Expand Down Expand Up @@ -321,7 +321,7 @@ void GenericFunctionTest() {
// NOTE: `sizeof(IntP)` is only reported with `WarnOnSizeOfPointer=true`.
some_generic_function(&IntPP, sizeof(IntP));
some_generic_function(&ClassPP, sizeof(ClassP));
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type
}

int ValidExpressions() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// RUN: %check_clang_tidy %s cppcoreguidelines-avoid-non-const-global-variables %t
// RUN: %check_clang_tidy %s -check-suffixes=,DEFAULT cppcoreguidelines-avoid-non-const-global-variables %t
// RUN: %check_clang_tidy %s -check-suffixes=,INTERNAL-LINKAGE cppcoreguidelines-avoid-non-const-global-variables %t -- \
// RUN: -config="{CheckOptions: {cppcoreguidelines-avoid-non-const-global-variables.AllowInternalLinkage : 'true'}}"

int nonConstInt = 0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
Expand Down Expand Up @@ -38,9 +40,16 @@ int function() {

namespace {
int nonConstAnonymousNamespaceInt = 0;
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:5: warning: variable 'nonConstAnonymousNamespaceInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
} // namespace

static int nonConstStaticInt = 0;
// CHECK-MESSAGES-DEFAULT: :[[@LINE-1]]:12: warning: variable 'nonConstStaticInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:12: warning: variable 'nonConstStaticInt' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

static const int constStaticInt = 0;

class DummyClass {
public:
int nonConstPublicMemberVariable = 0;
Expand Down Expand Up @@ -126,7 +135,8 @@ const DummyEnum constNamespaceEnumInstance = DummyEnum::first;
namespace {
DummyEnum nonConstAnonymousNamespaceEnumInstance = DummyEnum::first;
}
// CHECK-MESSAGES: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-DEFAULT: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

// CHECKING FOR NON-CONST GLOBAL STRUCT ///////////////////////////////////////
struct DummyStruct {
Expand Down Expand Up @@ -169,7 +179,8 @@ const DummyStruct constNamespaceDummyStructInstance;
namespace {
DummyStruct nonConstAnonymousNamespaceStructInstance;
}
// CHECK-MESSAGES: :[[@LINE-2]]:13: warning: variable 'nonConstAnonymousNamespaceStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-DEFAULT: :[[@LINE-2]]:13: warning: variable 'nonConstAnonymousNamespaceStructInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-2]]:11: warning: variable 'nonConstAnonymousNamespaceEnumInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

// CHECKING FOR NON-CONST GLOBAL UNION ////////////////////////////////////////
union DummyUnion {
Expand Down Expand Up @@ -209,7 +220,8 @@ const DummyUnion constNamespaceDummyUnionInstance = {0x0};
namespace {
DummyUnion nonConstAnonymousNamespaceUnionInstance = {0x0};
}
// CHECK-MESSAGES: :[[@LINE-2]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-DEFAULT: :[[@LINE-2]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]
// CHECK-MESSAGES-INTERNAL-LINKAGE-NOT: :[[@LINE-3]]:12: warning: variable 'nonConstAnonymousNamespaceUnionInstance' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables]

// CHECKING FOR NON-CONST GLOBAL FUNCTION POINTER /////////////////////////////
int dummyFunction() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ struct PositiveUninitializedBaseOrdering : public NegativeAggregateType,
};

// We shouldn't need to initialize anything because PositiveUninitializedBase
// has a user-defined constructor.
// has a user-provided constructor.
struct NegativeUninitializedBase : public PositiveUninitializedBase {
NegativeUninitializedBase() {}
};
Expand Down
71 changes: 57 additions & 14 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4443,23 +4443,51 @@ the configuration (without a prefix: ``Auto``).
false:
import {VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying, VeryLongImportsAreAnnoying,} from "some/module.js"
.. _KeepEmptyLines:

**KeepEmptyLines** (``KeepEmptyLinesStyle``) :versionbadge:`clang-format 19` :ref:`¶ <KeepEmptyLines>`
Which empty lines are kept. See ``MaxEmptyLinesToKeep`` for how many
consecutive empty lines are kept.

Nested configuration flags:

Options regarding which empty lines are kept.

For example, the config below will remove empty lines at start of the
file, end of the file, and start of blocks.


.. code-block:: c++

KeepEmptyLines:
AtEndOfFile: false
AtStartOfBlock: false
AtStartOfFile: false

* ``bool AtEndOfFile`` Keep empty lines at end of file.

* ``bool AtStartOfBlock`` Keep empty lines at start of a block.

.. code-block:: c++

true: false:
if (foo) { vs. if (foo) {
bar();
bar(); }
}

* ``bool AtStartOfFile`` Keep empty lines at start of file.


.. _KeepEmptyLinesAtEOF:

**KeepEmptyLinesAtEOF** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ <KeepEmptyLinesAtEOF>`
Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
This option is deprecated. See ``AtEndOfFile`` of ``KeepEmptyLines``.

.. _KeepEmptyLinesAtTheStartOfBlocks:

**KeepEmptyLinesAtTheStartOfBlocks** (``Boolean``) :versionbadge:`clang-format 3.7` :ref:`¶ <KeepEmptyLinesAtTheStartOfBlocks>`
If true, the empty line at the start of blocks is kept.

.. code-block:: c++

true: false:
if (foo) { vs. if (foo) {
bar();
bar(); }
}
This option is deprecated. See ``AtStartOfBlock`` of ``KeepEmptyLines``.

.. _LambdaBodyIndentation:

Expand Down Expand Up @@ -6214,6 +6242,7 @@ the configuration (without a prefix: ``Auto``).
# Example of usage:
SpacesInParens: Custom
SpacesInParensOptions:
ExceptDoubleParentheses: false
InConditionalStatements: true
InEmptyParentheses: true
Expand All @@ -6226,9 +6255,22 @@ the configuration (without a prefix: ``Auto``).
# Should be declared this way:
SpacesInParens: Custom
SpacesInParensOptions:
ExceptDoubleParentheses: false
InConditionalStatements: true
Other: true

* ``bool ExceptDoubleParentheses`` Override any of the following options to prevent addition of space
when both opening and closing parentheses use multiple parentheses.

.. code-block:: c++

true:
__attribute__(( noreturn ))
__decltype__(( x ))
if (( a = b ))
false:
Uses the applicable option.

* ``bool InConditionalStatements`` Put a space in parentheses only inside conditional statements
(``for/if/while/switch...``).

Expand All @@ -6242,8 +6284,9 @@ the configuration (without a prefix: ``Auto``).

.. code-block:: c++

true: false:
x = ( int32 )y vs. x = (int32)y
true: false:
x = ( int32 )y vs. x = (int32)y
y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x);

* ``bool InEmptyParentheses`` Insert a space in empty parentheses, i.e. ``()``.

Expand All @@ -6261,8 +6304,8 @@ the configuration (without a prefix: ``Auto``).

.. code-block:: c++

true: false:
t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
true: false:
t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;


.. _SpacesInParentheses:
Expand Down
59 changes: 44 additions & 15 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,6 @@ C++ Specific Potentially Breaking Changes
To fix this, update libstdc++ to version 14.1.1 or greater.

- Clang now emits errors when Thread Safety Analysis trylock attributes are
applied to functions or methods with incompatible return values, such as
constructors, destructors, and void-returning functions. This only affects the
``TRY_ACQUIRE`` and ``TRY_ACQUIRE_SHARED`` attributes (and any synonyms).

ABI Changes in This Version
---------------------------
- Fixed Microsoft name mangling of implicitly defined variables used for thread
Expand Down Expand Up @@ -152,6 +147,22 @@ Clang Frontend Potentially Breaking Changes
- The ``hasTypeLoc`` AST matcher will no longer match a ``classTemplateSpecializationDecl``;
existing uses should switch to ``templateArgumentLoc`` or ``hasAnyTemplateArgumentLoc`` instead.

- The comment parser now matches comments to declarations even if there is a
preprocessor macro in between the comment and declaration. This change is
intended to improve Clang's support for parsing documentation comments and
to better conform to Doxygen's behavior.

This has the potential to cause ``-Wdocumentation`` warnings, especially in
cases where a function-like macro has a documentation comment and is followed
immediately by a normal function. The function-like macro's documentation
comments will be attributed to the subsequent function and may cause
``-Wdocumentation`` warnings such as mismatched parameter names, or invalid
return documentation comments.

In cases where the ``-Wdocumentation`` warnings are thrown, the suggested fix
is to document the declaration following the macro so that the warnings are
fixed.

Clang Python Bindings Potentially Breaking Changes
--------------------------------------------------
- Renamed ``CursorKind`` variant 272 from ``OMP_TEAMS_DISTRIBUTE_DIRECTIVE``
Expand Down Expand Up @@ -309,6 +320,12 @@ Resolutions to C++ Defect Reports
C Language Changes
------------------

C2y Feature Support
^^^^^^^^^^^^^^^^^^^
- Clang now enables C2y mode with ``-std=c2y``. This sets ``__STDC_VERSION__``
to ``202400L`` so that it's greater than the value for C23. The value of this
macro is subject to change in the future.

C23 Feature Support
^^^^^^^^^^^^^^^^^^^
- No longer diagnose use of binary literals as an extension in C23 mode. Fixes
Expand Down Expand Up @@ -392,6 +409,11 @@ Non-comprehensive list of changes in this release
- ``#pragma GCC diagnostic warning "-Wfoo"`` can now downgrade ``-Werror=foo``
errors and certain default-to-error ``-W`` diagnostics to warnings.

- Support importing C++20 modules in clang-repl.

- Added support for ``TypeLoc::dump()`` for easier debugging, and improved
textual and JSON dumping for various ``TypeLoc``-related nodes.

New Compiler Flags
------------------
- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
Expand Down Expand Up @@ -623,10 +645,19 @@ Improvements to Clang's diagnostics
- Clang no longer emits a "declared here" note for a builtin function that has no declaration in source.
Fixes #GH93369.

- Clang now has an improved error message for captures that refer to a class member.
Fixes #GH94764.

- Clang now diagnoses unsupported class declarations for ``std::initializer_list<E>`` when they are
used rather than when they are needed for constant evaluation or when code is generated for them.
The check is now stricter to prevent crashes for some unsupported declarations (Fixes #GH95495).

- Clang now diagnoses dangling cases where a pointer is assigned to a temporary
that will be destroyed at the end of the full expression.
Fixes #GH54492.

- Clang now shows implicit deduction guides when diagnosing overload resolution failure. #GH92393.

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

Expand Down Expand Up @@ -735,16 +766,14 @@ Bug Fixes in This Version

- Fixed `static_cast` to array of unknown bound. Fixes (#GH62863).

- Clang's Thread Safety Analysis now evaluates trylock success arguments of enum
types rather than silently defaulting to false. This fixes a class of false
negatives where the analysis failed to detect unchecked access to guarded
data.

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

- Fix crash when atomic builtins are called with pointer to zero-size struct (#GH90330)

- Clang now allows pointee types of atomic builtin arguments to be complete template types
that was not instantiated elsewhere.

Bug Fixes to Attribute Support
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -1112,6 +1141,11 @@ clang-format
- Adds ``AllowShortCaseExpressionOnASingleLine`` option.
- Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``.
- Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``.
- Adds ``KeepEmptyLines`` option to deprecate ``KeepEmptyLinesAtEOF``
and ``KeepEmptyLinesAtTheStartOfBlocks``.
- Add ``ExceptDoubleParentheses`` sub-option for ``SpacesInParensOptions``
to override addition of spaces between multiple, non-redundant parentheses
similar to the rules used for ``RemoveParentheses``.

libclang
--------
Expand Down Expand Up @@ -1140,11 +1174,6 @@ Crash and bug fixes
Improvements
^^^^^^^^^^^^

- Support importing C++20 modules in clang-repl.

- Added support for ``TypeLoc::dump()`` for easier debugging, and improved
textual and JSON dumping for various ``TypeLoc``-related nodes.

Moved checkers
^^^^^^^^^^^^^^

Expand Down
53 changes: 4 additions & 49 deletions clang/docs/ThreadSafetyAnalysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -420,17 +420,10 @@ TRY_ACQUIRE(<bool>, ...), TRY_ACQUIRE_SHARED(<bool>, ...)
*Previously:* ``EXCLUSIVE_TRYLOCK_FUNCTION``, ``SHARED_TRYLOCK_FUNCTION``

These are attributes on a function or method that tries to acquire the given
capability, and returns a boolean, integer, or pointer value indicating success
or failure.

The attribute's first argument defines whether a zero or non-zero return value
indicates success. Syntactically, it accepts ``NULL`` or ``nullptr``, ``bool``
and ``int`` literals, as well as enumerator values. *The analysis only cares
whether this success value is zero or non-zero.* This leads to some subtle
consequences, discussed in the next section.

The remaining arguments are interpreted in the same way as ``ACQUIRE``. See
:ref:`mutexheader`, below, for example uses.
capability, and returns a boolean value indicating success or failure.
The first argument must be ``true`` or ``false``, to specify which return value
indicates success, and the remaining arguments are interpreted in the same way
as ``ACQUIRE``. See :ref:`mutexheader`, below, for example uses.

Because the analysis doesn't support conditional locking, a capability is
treated as acquired after the first branch on the return value of a try-acquire
Expand All @@ -452,44 +445,6 @@ function.
}
}

Subtle Consequences of Non-Boolean Success Values
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The trylock attributes accept non-boolean expressions for the success value, but
the analysis only cares whether the value is zero or non-zero.

Suppose you define an enum with two non-zero enumerators: ``LockAcquired = 1``
and ``LockNotAcquired = 2``. If your trylock function returns ``LockAcquired``
on success and ``LockNotAcquired`` on failure, the analysis may fail to detect
access to guarded data without holding the mutex because they are both non-zero.

.. code-block:: c++

// *** Beware: this code demonstrates incorrect usage. ***

enum TrylockResult { LockAcquired = 1, LockNotAcquired = 2 };

class CAPABILITY("mutex") Mutex {
public:
TrylockResult TryLock() TRY_ACQUIRE(LockAcquired);
};

Mutex mu;
int a GUARDED_BY(mu);

void foo() {
if (mu.TryLock()) { // This branch satisfies the analysis, but permits
// unguarded access to `a`!
a = 0;
mu.Unlock();
}
}

It's also possible to return a pointer from the trylock function. Similarly, all
that matters is whether the success value is zero or non-zero. For instance, a
success value of `true` means the function returns a non-null pointer on
success.


ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...)
--------------------------------------------------------
Expand Down
10 changes: 7 additions & 3 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3458,9 +3458,9 @@ Differences between various standard modes

clang supports the -std option, which changes what language mode clang uses.
The supported modes for C are c89, gnu89, c94, c99, gnu99, c11, gnu11, c17,
gnu17, c23, gnu23, and various aliases for those modes. If no -std option is
specified, clang defaults to gnu17 mode. Many C99 and C11 features are
supported in earlier modes as a conforming extension, with a warning. Use
gnu17, c23, gnu23, c2y, gnu2y, and various aliases for those modes. If no -std
option is specified, clang defaults to gnu17 mode. Many C99 and C11 features
are supported in earlier modes as a conforming extension, with a warning. Use
``-pedantic-errors`` to request an error if a feature from a later standard
revision is used in an earlier mode.

Expand Down Expand Up @@ -3523,6 +3523,10 @@ Differences between ``*17`` and ``*23`` modes:
- ``[[]]`` attributes are supported by default in ``*23`` mode, and as an
extension in ``*17`` and earlier modes.

Differences between ``*23`` and ``*2y`` modes:

- ``__STDC_VERSION__`` is defined to ``202400L`` rather than ``202311L``.

GCC extensions not implemented yet
----------------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendPluginRegistry.h"
#include "clang/Sema/Sema.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Passes/OptimizationLevel.h"
#include "llvm/Passes/PassBuilder.h"
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/Redeclarable.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,10 +281,10 @@ class Redeclarable {
return tmp;
}

friend bool operator==(redecl_iterator x, redecl_iterator y) {
friend bool operator==(const redecl_iterator &x, const redecl_iterator &y) {
return x.Current == y.Current;
}
friend bool operator!=(redecl_iterator x, redecl_iterator y) {
friend bool operator!=(const redecl_iterator &x, const redecl_iterator &y) {
return x.Current != y.Current;
}
};
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/AST/TemplateName.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ class SubstTemplateTemplateParmPackStorage : public UncommonTemplateNameStorage,
///
/// Here, "apply" is treated as a template name within the typename
/// specifier in the typedef. "apply" is a nested template, and can
/// only be understood in the context of
/// only be understood in the context of a template instantiation,
/// hence is represented as a dependent template name.
class TemplateName {
// NameDecl is either a TemplateDecl or a UsingShadowDecl depending on the
// NameKind.
Expand Down
28 changes: 14 additions & 14 deletions clang/include/clang/Basic/Cuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const char *CudaVersionToString(CudaVersion V);
// Input is "Major.Minor"
CudaVersion CudaStringToVersion(const llvm::Twine &S);

enum class CudaArch {
enum class OffloadArch {
UNUSED,
UNKNOWN,
// TODO: Deprecate and remove GPU architectures older than sm_52.
Expand Down Expand Up @@ -133,8 +133,8 @@ enum class CudaArch {
// public one.
LAST,

CudaDefault = CudaArch::SM_52,
HIPDefault = CudaArch::GFX906,
CudaDefault = OffloadArch::SM_52,
HIPDefault = OffloadArch::GFX906,
};

enum class CUDAFunctionTarget {
Expand All @@ -145,26 +145,26 @@ enum class CUDAFunctionTarget {
InvalidTarget
};

static inline bool IsNVIDIAGpuArch(CudaArch A) {
return A >= CudaArch::SM_20 && A < CudaArch::GFX600;
static inline bool IsNVIDIAOffloadArch(OffloadArch A) {
return A >= OffloadArch::SM_20 && A < OffloadArch::GFX600;
}

static inline bool IsAMDGpuArch(CudaArch A) {
static inline bool IsAMDOffloadArch(OffloadArch A) {
// Generic processor model is for testing only.
return A >= CudaArch::GFX600 && A < CudaArch::Generic;
return A >= OffloadArch::GFX600 && A < OffloadArch::Generic;
}

const char *CudaArchToString(CudaArch A);
const char *CudaArchToVirtualArchString(CudaArch A);
const char *OffloadArchToString(OffloadArch A);
const char *OffloadArchToVirtualArchString(OffloadArch A);

// The input should have the form "sm_20".
CudaArch StringToCudaArch(llvm::StringRef S);
OffloadArch StringToOffloadArch(llvm::StringRef S);

/// Get the earliest CudaVersion that supports the given CudaArch.
CudaVersion MinVersionForCudaArch(CudaArch A);
/// Get the earliest CudaVersion that supports the given OffloadArch.
CudaVersion MinVersionForOffloadArch(OffloadArch A);

/// Get the latest CudaVersion that supports the given CudaArch.
CudaVersion MaxVersionForCudaArch(CudaArch A);
/// Get the latest CudaVersion that supports the given OffloadArch.
CudaVersion MaxVersionForOffloadArch(OffloadArch A);

// Various SDK-dependent features that affect CUDA compilation
enum class CudaFeature {
Expand Down
11 changes: 10 additions & 1 deletion clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ def CPre23CompatPedantic : DiagGroup<"pre-c23-compat-pedantic",
def : DiagGroup<"pre-c2x-compat", [CPre23Compat]>;
def : DiagGroup<"pre-c2x-compat-pedantic", [CPre23CompatPedantic]>;

def CPre2yCompat : DiagGroup<"pre-c2y-compat">;
def CPre2yCompatPedantic : DiagGroup<"pre-c2y-compat-pedantic",
[CPre2yCompat]>;

// Warnings for C++ code which is not compatible with previous C++ standards.
def CXXPre14Compat : DiagGroup<"pre-c++14-compat">;
def : DiagGroup<"c++98-c++11-compat", [CXXPre14Compat]>;
Expand Down Expand Up @@ -430,14 +434,16 @@ def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingAssignment: DiagGroup<"dangling-assignment">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
def DanglingGsl : DiagGroup<"dangling-gsl">;
def ReturnStackAddress : DiagGroup<"return-stack-address">;
// Name of this warning in GCC
def : DiagGroup<"return-local-addr", [ReturnStackAddress]>;
def Dangling : DiagGroup<"dangling", [DanglingField,
def Dangling : DiagGroup<"dangling", [DanglingAssignment,
DanglingField,
DanglingInitializerList,
DanglingGsl,
ReturnStackAddress]>;
Expand Down Expand Up @@ -1195,6 +1201,9 @@ def C23 : DiagGroup<"c23-extensions">;

def : DiagGroup<"c2x-extensions", [C23]>;

// A warning group for warnings about using C2y features as extensions.
def C2y : DiagGroup<"c2y-extensions">;

// Previously supported warning group which is no longer pertinent as binary
// literals are a C++14 and C23 extension now instead of a GNU extension.
def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
Expand Down
9 changes: 6 additions & 3 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,12 @@ def err_duplicate_default_assoc : Error<
"duplicate default generic association">;
def note_previous_default_assoc : Note<
"previous default generic association is here">;
def ext_generic_with_type_arg : Extension<
"passing a type argument as the first operand to '_Generic' is a Clang "
"extension">, InGroup<DiagGroup<"generic-type-extension">>;
def ext_c2y_generic_with_type_arg : Extension<
"passing a type argument as the first operand to '_Generic' is a C2y "
"extension">, InGroup<C2y>;
def warn_c2y_compat_generic_with_type_arg : Warning<
"passing a type argument as the first operand to '_Generic' is incompatible "
"with C standards before C2y">, InGroup<CPre2yCompat>, DefaultIgnore;

def ext_c99_feature : Extension<
"'%0' is a C99 extension">, InGroup<C99>;
Expand Down
48 changes: 28 additions & 20 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2419,6 +2419,7 @@ def err_selected_explicit_constructor : Error<
"chosen constructor is explicit in copy-initialization">;
def note_explicit_ctor_deduction_guide_here : Note<
"explicit %select{constructor|deduction guide}0 declared here">;
def note_implicit_deduction_guide : Note<"implicit deduction guide declared as '%0'">;

// C++11 auto
def warn_cxx98_compat_auto_type_specifier : Warning<
Expand Down Expand Up @@ -3282,23 +3283,11 @@ def warn_aligned_attr_underaligned : Warning<err_alignas_underaligned.Summary>,
def err_attribute_sizeless_type : Error<
"%0 attribute cannot be applied to sizeless type %1">;
def err_attribute_argument_n_type : Error<
"%0 attribute requires parameter %1 to be %select{"
"int or bool"
"|an integer constant"
"|a string"
"|an identifier"
"|a constant expression"
"|a builtin function"
"|nullptr or a bool, int, or enum literal}2">;
"%0 attribute requires parameter %1 to be %select{int or bool|an integer "
"constant|a string|an identifier|a constant expression|a builtin function}2">;
def err_attribute_argument_type : Error<
"%0 attribute requires %select{"
"int or bool"
"|an integer constant"
"|a string"
"|an identifier"
"|a constant expression"
"|a builtin function"
"|a pointer or a bool, int, or enum literal}1">;
"%0 attribute requires %select{int or bool|an integer "
"constant|a string|an identifier}1">;
def err_attribute_argument_out_of_range : Error<
"%0 attribute requires integer constant between %1 and %2 inclusive">;
def err_init_priority_object_attr : Error<
Expand Down Expand Up @@ -3558,6 +3547,12 @@ def warn_alignment_not_power_of_two : Warning<
InGroup<DiagGroup<"non-power-of-two-alignment">>;
def err_alignment_dependent_typedef_name : Error<
"requested alignment is dependent but declaration is not dependent">;
def ext_c2y_alignof_incomplete_array : Extension<
"'alignof' on an incomplete array type is a C2y extension">,
InGroup<C2y>;
def warn_c2y_compat_alignof_incomplete_array : Warning<
"'alignof' on an incomplete array type is incompatible with C standards "
"before C2y">, InGroup<CPre2yCompat>, DefaultIgnore;

def warn_alignment_builtin_useless : Warning<
"%select{aligning a value|the result of checking whether a value is aligned}0"
Expand Down Expand Up @@ -3750,8 +3745,7 @@ def warn_attribute_wrong_decl_type : Warning<
"|types and namespaces"
"|variables, functions and classes"
"|kernel functions"
"|non-K&R-style functions"
"|functions that return bool, integer, or a pointer type}2">,
"|non-K&R-style functions}2">,
InGroup<IgnoredAttributes>;
def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Summary>;
def warn_type_attribute_wrong_type : Warning<
Expand Down Expand Up @@ -7676,8 +7670,12 @@ def ext_gnu_ptr_func_arith : Extension<
InGroup<GNUPointerArith>;
def err_readonly_message_assignment : Error<
"assigning to 'readonly' return result of an Objective-C message not allowed">;
def ext_increment_complex : Extension<
"'%select{--|++}0' on an object of complex type is a Clang extension">;
def ext_c2y_increment_complex : Extension<
"'%select{--|++}0' on an object of complex type is a C2y extension">,
InGroup<C2y>;
def warn_c2y_compat_increment_complex : Warning<
"'%select{--|++}0' on an object of complex type is incompatible with C "
"standards before C2y">, InGroup<CPre2yCompat>, DefaultIgnore;
def ext_integer_complement_complex : Extension<
"ISO C does not support '~' for complex conjugation of %0">;
def err_nosetter_property_assignment : Error<
Expand Down Expand Up @@ -8204,6 +8202,8 @@ let CategoryName = "Lambda Issue" in {
"'&' must precede a capture when the capture default is '='">;
def err_capture_does_not_name_variable : Error<
"%0 in capture list does not name a variable">;
def err_capture_class_member_does_not_name_variable : Error<
"class member %0 cannot appear in capture list as it is not a variable">;
def err_capture_non_automatic_variable : Error<
"%0 cannot be captured because it does not have automatic storage "
"duration">;
Expand Down Expand Up @@ -10120,6 +10120,11 @@ def warn_new_dangling_initializer_list : Warning<
"the allocated initializer list}0 "
"will be destroyed at the end of the full-expression">,
InGroup<DanglingInitializerList>;
def warn_dangling_pointer_assignment : Warning<
"object backing the pointer %0 "
"will be destroyed at the end of the full-expression">,
InGroup<DanglingAssignment>;

def warn_unsupported_lifetime_extension : Warning<
"lifetime extension of "
"%select{temporary|backing array of initializer list}0 created "
Expand Down Expand Up @@ -12330,6 +12335,9 @@ def warn_hlsl_availability_unavailable :
Warning<err_unavailable.Summary>,
InGroup<HLSLAvailability>, DefaultError;

def err_hlsl_export_not_on_function : Error<
"export declaration can only be used on functions">;

// Layout randomization diagnostics.
def err_non_designated_init_used : Error<
"a randomized struct can only be initialized with a designated initializer">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ LANGOPT(C99 , 1, 0, "C99")
LANGOPT(C11 , 1, 0, "C11")
LANGOPT(C17 , 1, 0, "C17")
LANGOPT(C23 , 1, 0, "C23")
LANGOPT(C2y , 1, 0, "C2y")
LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode")
LANGOPT(Kernel , 1, 0, "Kernel mode")
LANGOPT(MicrosoftExt , 1, 0, "Microsoft C++ extensions")
Expand Down
28 changes: 16 additions & 12 deletions clang/include/clang/Basic/LangStandard.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,19 @@ enum LangFeatures {
C11 = (1 << 2),
C17 = (1 << 3),
C23 = (1 << 4),
CPlusPlus = (1 << 5),
CPlusPlus11 = (1 << 6),
CPlusPlus14 = (1 << 7),
CPlusPlus17 = (1 << 8),
CPlusPlus20 = (1 << 9),
CPlusPlus23 = (1 << 10),
CPlusPlus26 = (1 << 11),
Digraphs = (1 << 12),
GNUMode = (1 << 13),
HexFloat = (1 << 14),
OpenCL = (1 << 15),
HLSL = (1 << 16)
C2y = (1 << 5),
CPlusPlus = (1 << 6),
CPlusPlus11 = (1 << 7),
CPlusPlus14 = (1 << 8),
CPlusPlus17 = (1 << 9),
CPlusPlus20 = (1 << 10),
CPlusPlus23 = (1 << 11),
CPlusPlus26 = (1 << 12),
Digraphs = (1 << 13),
GNUMode = (1 << 14),
HexFloat = (1 << 15),
OpenCL = (1 << 16),
HLSL = (1 << 17)
};

/// LangStandard - Information about the properties of a particular language
Expand Down Expand Up @@ -106,6 +107,9 @@ struct LangStandard {
/// isC23 - Language is a superset of C23.
bool isC23() const { return Flags & C23; }

/// isC2y - Language is a superset of C2y.
bool isC2y() const { return Flags & C2y; }

/// isCPlusPlus - Language is a C++ variant.
bool isCPlusPlus() const { return Flags & CPlusPlus; }

Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/LangStandards.def
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ LANGSTANDARD_ALIAS_DEPR(gnu23, "gnu2x")
// FIXME: Add the alias for iso9899:202* once we know the year ISO publishes
// the document (expected to be 2024).

// C2y modes
LANGSTANDARD(c2y, "c2y",
C, "Working Draft for ISO C2y",
LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | HexFloat)
LANGSTANDARD(gnu2y, "gnu2y",
C, "Working Draft for ISO C2y with GNU extensions",
LineComment | C99 | C11 | C17 | C23 | C2y | Digraphs | GNUMode | HexFloat)


// C++ modes
LANGSTANDARD(cxx98, "c++98",
CXX, "ISO C++ 1998 with amendments",
Expand Down
14 changes: 14 additions & 0 deletions clang/include/clang/Basic/OpenMPKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,20 @@ bool needsTaskBasedThreadLimit(OpenMPDirectiveKind DKind);
/// is restricted only to memory order clauses of "OMPC_acquire",
/// "OMPC_relaxed" and "OMPC_seq_cst".
bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter);

/// Checks if the specified directive is considered as "executable". This
/// combines the OpenMP categories of "executable" and "subsidiary", plus
/// any other directives that should be treated as executable.
/// \param DKind Specified directive.
/// \return true - if the above condition is met for this directive
/// otherwise - false.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind);

/// Checks if the specified directive can capture variables.
/// \param DKind Specified directive.
/// \return true - if the above condition is met for this directive
/// otherwise - false.
bool isOpenMPCapturingDirective(OpenMPDirectiveKind DKind);
}

#endif
Expand Down
12 changes: 12 additions & 0 deletions clang/include/clang/Basic/arm_sme.td
Original file line number Diff line number Diff line change
Expand Up @@ -805,4 +805,16 @@ defm SVREADZ_ZA16 : ZAReadzSingle<"za16", "sUshb", "aarch64_sme_readz", [ImmChe
defm SVREADZ_ZA32 : ZAReadzSingle<"za32", "iUif", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_3>]>;
defm SVREADZ_ZA64 : ZAReadzSingle<"za64", "lUld", "aarch64_sme_readz", [ImmCheck<0, ImmCheck0_7>]>;
defm SVREADZ_ZA128 : ZAReadzSingle<"za128", "csilUcUiUsUlbhfd", "aarch64_sme_readz_q", [ImmCheck<0, ImmCheck0_15>]>;

multiclass ZAReadzArray<string vg_num>{
let SMETargetGuard = "sme2p1" in {
def NAME # _B : SInst<"svreadz_za8_{d}_vg1x" # vg_num, vg_num # "m", "cUc", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
def NAME # _H : SInst<"svreadz_za16_{d}_vg1x" # vg_num, vg_num # "m", "sUsbh", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
def NAME # _S : SInst<"svreadz_za32_{d}_vg1x" # vg_num, vg_num # "m", "iUif", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
def NAME # _D : SInst<"svreadz_za64_{d}_vg1x" # vg_num, vg_num # "m", "lUld", MergeNone, "aarch64_sme_readz_x" # vg_num, [IsStreaming, IsInOutZA]>;
}
}

defm SVREADZ_VG2 : ZAReadzArray<"2">;
defm SVREADZ_VG4 : ZAReadzArray<"4">;
} // let SVETargetGuard = InvalidMode
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/ToolChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ class ToolChain {
// Returns target specific standard library path if it exists.
std::optional<std::string> getStdlibPath() const;

// Returns target specific standard library include path if it exists.
std::optional<std::string> getStdlibIncludePath() const;

// Returns <ResourceDir>/lib/<OSName>/<arch> or <ResourceDir>/lib/<triple>.
// This is used by runtimes (such as OpenMP) to find arch-specific libraries.
virtual path_list getArchSpecificLibPaths() const;
Expand Down
91 changes: 67 additions & 24 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -3095,20 +3095,49 @@ struct FormatStyle {
bool JavaScriptWrapImports;
// clang-format on

/// Keep empty lines (up to ``MaxEmptyLinesToKeep``) at end of file.
/// \version 17
bool KeepEmptyLinesAtEOF;

/// If true, the empty line at the start of blocks is kept.
/// Options regarding which empty lines are kept.
///
/// For example, the config below will remove empty lines at start of the
/// file, end of the file, and start of blocks.
///
/// \code
/// true: false:
/// if (foo) { vs. if (foo) {
/// bar();
/// bar(); }
/// }
/// KeepEmptyLines:
/// AtEndOfFile: false
/// AtStartOfBlock: false
/// AtStartOfFile: false
/// \endcode
struct KeepEmptyLinesStyle {
/// Keep empty lines at end of file.
bool AtEndOfFile;
/// Keep empty lines at start of a block.
/// \code
/// true: false:
/// if (foo) { vs. if (foo) {
/// bar();
/// bar(); }
/// }
/// \endcode
bool AtStartOfBlock;
/// Keep empty lines at start of file.
bool AtStartOfFile;
bool operator==(const KeepEmptyLinesStyle &R) const {
return AtEndOfFile == R.AtEndOfFile &&
AtStartOfBlock == R.AtStartOfBlock &&
AtStartOfFile == R.AtStartOfFile;
}
};
/// Which empty lines are kept. See ``MaxEmptyLinesToKeep`` for how many
/// consecutive empty lines are kept.
/// \version 19
KeepEmptyLinesStyle KeepEmptyLines;

/// This option is deprecated. See ``AtEndOfFile`` of ``KeepEmptyLines``.
/// \version 17
// bool KeepEmptyLinesAtEOF;

/// This option is deprecated. See ``AtStartOfBlock`` of ``KeepEmptyLines``.
/// \version 3.7
bool KeepEmptyLinesAtTheStartOfBlocks;
// bool KeepEmptyLinesAtTheStartOfBlocks;

/// Indentation logic for lambda bodies.
enum LambdaBodyIndentationKind : int8_t {
Expand Down Expand Up @@ -4650,10 +4679,22 @@ struct FormatStyle {
/// # Should be declared this way:
/// SpacesInParens: Custom
/// SpacesInParensOptions:
/// ExceptDoubleParentheses: false
/// InConditionalStatements: true
/// Other: true
/// \endcode
struct SpacesInParensCustom {
/// Override any of the following options to prevent addition of space
/// when both opening and closing parentheses use multiple parentheses.
/// \code
/// true:
/// __attribute__(( noreturn ))
/// __decltype__(( x ))
/// if (( a = b ))
/// \endcode
/// false:
/// Uses the applicable option.
bool ExceptDoubleParentheses;
/// Put a space in parentheses only inside conditional statements
/// (``for/if/while/switch...``).
/// \code
Expand All @@ -4664,8 +4705,9 @@ struct FormatStyle {
bool InConditionalStatements;
/// Put a space in C style casts.
/// \code
/// true: false:
/// x = ( int32 )y vs. x = (int32)y
/// true: false:
/// x = ( int32 )y vs. x = (int32)y
/// y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x);
/// \endcode
bool InCStyleCasts;
/// Insert a space in empty parentheses, i.e. ``()``.
Expand All @@ -4681,23 +4723,26 @@ struct FormatStyle {
bool InEmptyParentheses;
/// Put a space in parentheses not covered by preceding options.
/// \code
/// true: false:
/// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
/// true: false:
/// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
/// \endcode
bool Other;

SpacesInParensCustom()
: InConditionalStatements(false), InCStyleCasts(false),
InEmptyParentheses(false), Other(false) {}
: ExceptDoubleParentheses(false), InConditionalStatements(false),
InCStyleCasts(false), InEmptyParentheses(false), Other(false) {}

SpacesInParensCustom(bool InConditionalStatements, bool InCStyleCasts,
SpacesInParensCustom(bool ExceptDoubleParentheses,
bool InConditionalStatements, bool InCStyleCasts,
bool InEmptyParentheses, bool Other)
: InConditionalStatements(InConditionalStatements),
: ExceptDoubleParentheses(ExceptDoubleParentheses),
InConditionalStatements(InConditionalStatements),
InCStyleCasts(InCStyleCasts), InEmptyParentheses(InEmptyParentheses),
Other(Other) {}

bool operator==(const SpacesInParensCustom &R) const {
return InConditionalStatements == R.InConditionalStatements &&
return ExceptDoubleParentheses == R.ExceptDoubleParentheses &&
InConditionalStatements == R.InConditionalStatements &&
InCStyleCasts == R.InCStyleCasts &&
InEmptyParentheses == R.InEmptyParentheses && Other == R.Other;
}
Expand All @@ -4715,6 +4760,7 @@ struct FormatStyle {
/// # Example of usage:
/// SpacesInParens: Custom
/// SpacesInParensOptions:
/// ExceptDoubleParentheses: false
/// InConditionalStatements: true
/// InEmptyParentheses: true
/// \endcode
Expand Down Expand Up @@ -5033,10 +5079,7 @@ struct FormatStyle {
JavaImportGroups == R.JavaImportGroups &&
JavaScriptQuotes == R.JavaScriptQuotes &&
JavaScriptWrapImports == R.JavaScriptWrapImports &&
KeepEmptyLinesAtEOF == R.KeepEmptyLinesAtEOF &&
KeepEmptyLinesAtTheStartOfBlocks ==
R.KeepEmptyLinesAtTheStartOfBlocks &&
Language == R.Language &&
KeepEmptyLines == R.KeepEmptyLines && Language == R.Language &&
LambdaBodyIndentation == R.LambdaBodyIndentation &&
LineEnding == R.LineEnding && MacroBlockBegin == R.MacroBlockBegin &&
MacroBlockEnd == R.MacroBlockEnd && Macros == R.Macros &&
Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Sema/ParsedAttr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,6 @@ enum AttributeArgumentNType {
AANT_ArgumentIdentifier,
AANT_ArgumentConstantExpr,
AANT_ArgumentBuiltinFunction,
AANT_ArgumentNullptrOrBoolIntOrEnumLiteral,
};

/// These constants match the enumerated choices of
Expand All @@ -1102,7 +1101,6 @@ enum AttributeDeclKind {
ExpectedFunctionVariableOrClass,
ExpectedKernelFunction,
ExpectedFunctionWithProtoType,
ExpectedFunctionReturningPointerBoolIntOrEnum,
};

inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
Expand Down
Loading