136 changes: 96 additions & 40 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3887,6 +3887,43 @@ void RewriteInstance::mapCodeSections(BOLTLinker::SectionMapper MapSection) {

void RewriteInstance::mapAllocatableSections(
BOLTLinker::SectionMapper MapSection) {

if (opts::UseOldText || opts::StrictMode) {
auto tryRewriteSection = [&](BinarySection &OldSection,
BinarySection &NewSection) {
if (OldSection.getSize() < NewSection.getOutputSize())
return;

BC->outs() << "BOLT-INFO: rewriting " << OldSection.getName()
<< " in-place\n";

NewSection.setOutputAddress(OldSection.getAddress());
NewSection.setOutputFileOffset(OldSection.getInputFileOffset());
MapSection(NewSection, OldSection.getAddress());

// Pad contents with zeros.
NewSection.addPadding(OldSection.getSize() - NewSection.getOutputSize());

// Prevent the original section name from appearing in the section header
// table.
OldSection.setAnonymous(true);
};

if (EHFrameSection) {
BinarySection *NewEHFrameSection =
getSection(getNewSecPrefix() + getEHFrameSectionName());
assert(NewEHFrameSection && "New contents expected for .eh_frame");
tryRewriteSection(*EHFrameSection, *NewEHFrameSection);
}
BinarySection *EHSection = getSection(".gcc_except_table");
BinarySection *NewEHSection =
getSection(getNewSecPrefix() + ".gcc_except_table");
if (EHSection) {
assert(NewEHSection && "New contents expected for .gcc_except_table");
tryRewriteSection(*EHSection, *NewEHSection);
}
}

// Allocate read-only sections first, then writable sections.
enum : uint8_t { ST_READONLY, ST_READWRITE };
for (uint8_t SType = ST_READONLY; SType <= ST_READWRITE; ++SType) {
Expand Down Expand Up @@ -4164,7 +4201,6 @@ void RewriteInstance::rewriteNoteSections() {
// New section size.
uint64_t Size = 0;
bool DataWritten = false;
uint8_t *SectionData = nullptr;
// Copy over section contents unless it's one of the sections we overwrite.
if (!willOverwriteSection(SectionName)) {
Size = Section.sh_size;
Expand Down Expand Up @@ -4196,12 +4232,7 @@ void RewriteInstance::rewriteNoteSections() {
if (BSec->getAllocAddress()) {
assert(!DataWritten && "Writing section twice.");
(void)DataWritten;
SectionData = BSec->getOutputData();

LLVM_DEBUG(dbgs() << "BOLT-DEBUG: " << (Size ? "appending" : "writing")
<< " contents to section " << SectionName << '\n');
OS.write(reinterpret_cast<char *>(SectionData), BSec->getOutputSize());
Size += BSec->getOutputSize();
Size += BSec->write(OS);
}

BSec->setOutputFileOffset(NextAvailableOffset);
Expand Down Expand Up @@ -4232,8 +4263,7 @@ void RewriteInstance::rewriteNoteSections() {
<< " of size " << Section.getOutputSize() << " at offset 0x"
<< Twine::utohexstr(Section.getOutputFileOffset()) << '\n');

OS.write(Section.getOutputContents().data(), Section.getOutputSize());
NextAvailableOffset += Section.getOutputSize();
NextAvailableOffset += Section.write(OS);
}
}

Expand Down Expand Up @@ -4347,6 +4377,10 @@ RewriteInstance::getOutputSections(ELFObjectFile<ELFT> *File,
BinarySection *BinSec = BC->getSectionForSectionRef(SecRef);
assert(BinSec && "Matching BinarySection should exist.");

// Exclude anonymous sections.
if (BinSec->isAnonymous())
continue;

addSection(Section, *BinSec);
}

Expand Down Expand Up @@ -5699,8 +5733,8 @@ void RewriteInstance::rewriteFile() {
<< Twine::utohexstr(Section.getAllocAddress()) << "\n of size "
<< Section.getOutputSize() << "\n at offset "
<< Section.getOutputFileOffset() << '\n';
OS.pwrite(reinterpret_cast<const char *>(Section.getOutputData()),
Section.getOutputSize(), Section.getOutputFileOffset());
OS.seek(Section.getOutputFileOffset());
Section.write(OS);
}

for (BinarySection &Section : BC->allocatableSections())
Expand Down Expand Up @@ -5791,42 +5825,64 @@ void RewriteInstance::writeEHFrameHeader() {
LLVM_DEBUG(dbgs() << "BOLT: writing a new " << getEHFrameHdrSectionName()
<< '\n');

NextAvailableAddress =
appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign);
// Try to overwrite the original .eh_frame_hdr if the size permits.
uint64_t EHFrameHdrOutputAddress = 0;
uint64_t EHFrameHdrFileOffset = 0;
std::vector<char> NewEHFrameHdr;
BinarySection *OldEHFrameHdrSection = getSection(getEHFrameHdrSectionName());
if (OldEHFrameHdrSection) {
NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
RelocatedEHFrame, NewEHFrame, OldEHFrameHdrSection->getAddress());
if (NewEHFrameHdr.size() <= OldEHFrameHdrSection->getSize()) {
BC->outs() << "BOLT-INFO: rewriting " << getEHFrameHdrSectionName()
<< " in-place\n";
EHFrameHdrOutputAddress = OldEHFrameHdrSection->getAddress();
EHFrameHdrFileOffset = OldEHFrameHdrSection->getInputFileOffset();
} else {
OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() +
getEHFrameHdrSectionName());
OldEHFrameHdrSection = nullptr;
}
}

const uint64_t EHFrameHdrOutputAddress = NextAvailableAddress;
const uint64_t EHFrameHdrFileOffset =
getFileOffsetForAddress(NextAvailableAddress);
// If there was not enough space, allocate more memory for .eh_frame_hdr.
if (!OldEHFrameHdrSection) {
NextAvailableAddress =
appendPadding(Out->os(), NextAvailableAddress, EHFrameHdrAlign);

std::vector<char> NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress);
EHFrameHdrOutputAddress = NextAvailableAddress;
EHFrameHdrFileOffset = getFileOffsetForAddress(NextAvailableAddress);

NewEHFrameHdr = CFIRdWrt->generateEHFrameHeader(
RelocatedEHFrame, NewEHFrame, EHFrameHdrOutputAddress);

NextAvailableAddress += NewEHFrameHdr.size();
if (!BC->BOLTReserved.empty() &&
(NextAvailableAddress > BC->BOLTReserved.end())) {
BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName()
<< " into reserved space\n";
exit(1);
}

// Create a new entry in the section header table.
const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
/*IsText=*/false,
/*IsAllocatable=*/true);
BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection(
getNewSecPrefix() + getEHFrameHdrSectionName(), ELF::SHT_PROGBITS,
Flags, nullptr, NewEHFrameHdr.size(), /*Alignment=*/1);
EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset);
EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress);
EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName());
}

Out->os().seek(EHFrameHdrFileOffset);
Out->os().write(NewEHFrameHdr.data(), NewEHFrameHdr.size());

const unsigned Flags = BinarySection::getFlags(/*IsReadOnly=*/true,
/*IsText=*/false,
/*IsAllocatable=*/true);
BinarySection *OldEHFrameHdrSection = getSection(getEHFrameHdrSectionName());
// Pad the contents if overwriting in-place.
if (OldEHFrameHdrSection)
OldEHFrameHdrSection->setOutputName(getOrgSecPrefix() +
getEHFrameHdrSectionName());

BinarySection &EHFrameHdrSec = BC->registerOrUpdateSection(
getNewSecPrefix() + getEHFrameHdrSectionName(), ELF::SHT_PROGBITS, Flags,
nullptr, NewEHFrameHdr.size(), /*Alignment=*/1);
EHFrameHdrSec.setOutputFileOffset(EHFrameHdrFileOffset);
EHFrameHdrSec.setOutputAddress(EHFrameHdrOutputAddress);
EHFrameHdrSec.setOutputName(getEHFrameHdrSectionName());

NextAvailableAddress += EHFrameHdrSec.getOutputSize();

if (!BC->BOLTReserved.empty() &&
(NextAvailableAddress > BC->BOLTReserved.end())) {
BC->errs() << "BOLT-ERROR: unable to fit " << getEHFrameHdrSectionName()
<< " into reserved space\n";
exit(1);
}
Out->os().write_zeros(OldEHFrameHdrSection->getSize() -
NewEHFrameHdr.size());

// Merge new .eh_frame with the relocated original so that gdb can locate all
// FDEs.
Expand Down
75 changes: 75 additions & 0 deletions bolt/test/X86/exceptions-compact.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## Check that llvm-bolt is able to overwrite LSDA in ULEB128 format in-place for
## all types of binaries.

# REQUIRES: system-linux

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o
# RUN: ld.lld --no-pie %t.o -o %t.exe -q
# RUN: ld.lld --pie %t.o -o %t.pie -q
# RUN: ld.lld --shared %t.o -o %t.so -q
# RUN: llvm-bolt %t.exe -o %t.bolt --strict \
# RUN: | FileCheck --check-prefix=CHECK-BOLT %s
# RUN: llvm-bolt %t.pie -o %t.pie.bolt --strict \
# RUN: | FileCheck --check-prefix=CHECK-BOLT %s
# RUN: llvm-bolt %t.so -o %t.so.bolt --strict \
# RUN: | FileCheck --check-prefix=CHECK-BOLT %s

# CHECK-BOLT: rewriting .gcc_except_table in-place

# RUN: llvm-readelf -WS %t.bolt | FileCheck --check-prefix=CHECK-ELF %s
# RUN: llvm-readelf -WS %t.pie.bolt | FileCheck --check-prefix=CHECK-ELF %s
# RUN: llvm-readelf -WS %t.so.bolt | FileCheck --check-prefix=CHECK-ELF %s

# CHECK-ELF-NOT: .bolt.org.gcc_except_table

.text
.global foo
.type foo, %function
foo:
.cfi_startproc
ret
.cfi_endproc
.size foo, .-foo

.globl _start
.type _start, %function
_start:
.Lfunc_begin0:
.cfi_startproc
.cfi_lsda 27, .Lexception0
call foo
.Ltmp0:
call foo
.Ltmp1:
ret

## Landing pads.
.LLP1:
ret
.LLP0:
ret

.cfi_endproc
.Lfunc_end0:
.size _start, .-_start

## EH table.
.section .gcc_except_table,"a",@progbits
.p2align 2
GCC_except_table0:
.Lexception0:
.byte 255 # @LPStart Encoding = omit
.byte 255 # @TType Encoding = omit
.byte 1 # Call site Encoding = uleb128
.uleb128 .Lcst_end0-.Lcst_begin0
.Lcst_begin0:
.uleb128 .Lfunc_begin0-.Lfunc_begin0 # >> Call Site 1 <<
.uleb128 .Ltmp0-.Lfunc_begin0 # Call between .Lfunc_begin0 and .Ltmp0
.uleb128 .LLP0-.Lfunc_begin0 # jumps to .LLP0
.byte 0 # On action: cleanup
.uleb128 .Ltmp0-.Lfunc_begin0 # >> Call Site 2 <<
.uleb128 .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1
.uleb128 .LLP1-.Lfunc_begin0 # jumps to .LLP1
.byte 0 # On action: cleanup
.Lcst_end0:

86 changes: 86 additions & 0 deletions bolt/test/X86/pie-eh-split-undo.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# REQUIRES: system-linux

# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-linux %s -o %t.o
# RUN: link_fdata %s %t.o %t.fdata
# RUN: llvm-strip --strip-unneeded %t.o
# RUN: ld.lld --pie %t.o -o %t.exe -q
# RUN: llvm-bolt %t.exe -o %t.out --data %t.fdata --split-functions --split-eh \
# RUN: --split-all-cold --print-after-lowering --print-only=_start 2>&1 \
# RUN: | FileCheck %s

## _start has two landing pads: one hot and one cold. Hence, BOLT will introduce
## a landing pad trampoline. However, the trampoline code will make the main
## split fragment larger than the whole function before split. Then BOLT will
## undo the splitting and remove the trampoline.

# CHECK: Binary Function "_start"
# CHECK: IsSplit :
# CHECK-SAME: 0

## Check that a landing pad trampoline was created, but contains no instructions
## and falls though to the real landing pad.

# CHECK: {{^[^[:space:]]+}} (0 instructions
# CHECK-NEXT: Landing Pad{{$}}
# CHECK: Exec Count
# CHECK-SAME: : 0
# CHECK: Successors:
# CHECK-SAME: [[LP:[^[:space:]]+]]
# CHECK-EMPTY:
# CHECK-NEXT: [[LP]]

.text
.global foo
.type foo, %function
foo:
.cfi_startproc
ret
.cfi_endproc
.size foo, .-foo

.globl _start
.type _start, %function
_start:
# FDATA: 0 [unknown] 0 1 _start 0 1 100
.Lfunc_begin0:
.cfi_startproc
.cfi_lsda 27, .Lexception0
call foo
.Ltmp0:
call foo
.Ltmp1:
ret

## Cold landing pad.
.LLP1:
ret

## Hot landing pad.
LLP0:
# FDATA: 0 [unknown] 0 1 _start #LLP0# 1 100
ret

.cfi_endproc
.Lfunc_end0:
.size _start, .-_start

## EH table.
.section .gcc_except_table,"a",@progbits
.p2align 2
GCC_except_table0:
.Lexception0:
.byte 255 # @LPStart Encoding = omit
.byte 255 # @TType Encoding = omit
.byte 1 # Call site Encoding = uleb128
.uleb128 .Lcst_end0-.Lcst_begin0
.Lcst_begin0:
.uleb128 .Lfunc_begin0-.Lfunc_begin0 # >> Call Site 1 <<
.uleb128 .Ltmp0-.Lfunc_begin0 # Call between .Lfunc_begin0 and .Ltmp0
.uleb128 LLP0-.Lfunc_begin0 # jumps to LLP0
.byte 0 # On action: cleanup
.uleb128 .Ltmp0-.Lfunc_begin0 # >> Call Site 2 <<
.uleb128 .Ltmp1-.Ltmp0 # Call between .Ltmp0 and .Ltmp1
.uleb128 .LLP1-.Lfunc_begin0 # jumps to .LLP1
.byte 0 # On action: cleanup
.Lcst_end0:

12 changes: 12 additions & 0 deletions bolt/test/eh-frame-hdr.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Check that llvm-bolt overwrites .eh_frame_hdr in-place.

REQUIRES: system-linux

RUN: %clang %cflags %p/Inputs/hello.c -o %t -Wl,-q
RUN: llvm-bolt %t -o %t.bolt --use-old-text \
RUN: | FileCheck %s --check-prefix=CHECK-BOLT
RUN: llvm-readelf -WS %t.bolt | FileCheck %s

CHECK-BOLT: rewriting .eh_frame_hdr in-place

CHECK-NOT: .bolt.org.eh_frame_hdr
8 changes: 8 additions & 0 deletions bolt/test/eh-frame-overwrite.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Check that llvm-bolt can overwrite .eh_frame section in-place.

REQUIRES: system-linux

RUN: %clang %cflags %p/Inputs/hello.c -o %t -Wl,-q
RUN: llvm-bolt %t -o %t.bolt --strict | FileCheck %s

CHECK: rewriting .eh_frame in-place
2 changes: 1 addition & 1 deletion bolt/test/runtime/X86/Inputs/pie-exceptions-failed-split.s
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Assembly generated from building the followingC++ code with the following
# Assembly generated from building the following C++ code with the following
# command using trunk clang. Then, basic block at .LBB1_7 was moved before the
# landing pad.
#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,16 @@ RUN: llvm-bolt %t -o %t.bolt --data %t.fdata --reorder-blocks=ext-tsp \
RUN: --split-functions --split-eh --print-after-lowering \
RUN: --print-only=_Z10throw_testiPPc 2>&1 | FileCheck %s

## Hot code in the test case gets larger after splitting because of jump
## instruction relaxation. Check that BOLT reverts the split correctly.
## Check that a landing pad is split from its thrower and does not require a
## trampoline LP.
CHECK: Binary Function "_Z10throw_testiPPc"
CHECK: IsSplit :
CHECK-SAME: 0

## Check that the landing pad trampoline was created, but contains no
## instructions and falls to the real landing pad.
CHECK: {{^[^[:space:]]+}} (0 instructions
CHECK-NEXT: Landing Pad{{$}}
CHECK: Exec Count
CHECK-SAME: : 0
CHECK: Successors:
CHECK-SAME: [[LP:[^[:space:]]+]]
CHECK-EMPTY:
CHECK-NEXT: [[LP]]
CHECK-DAG: Exec Count
CHECK-NOT: Exec Count
CHECK-DAG: callq __cxa_begin_catch
CHECK-SAME: 1
CHECK: callq {{.*}} # handler: [[LPAD:.*]];
CHECK-NOT: Landing Pad{{$}}
CHECK: HOT-COLD SPLIT POINT
CHECK: {{^}}[[LPAD]]
CHECK-NEXT: Landing Pad

## Verify the output still executes correctly when the exception path is being
## taken.
Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-include-fixer/IncludeFixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ bool IncludeFixerActionFactory::runInvocation(

// Create the compiler's actual diagnostics engine. We want to drop all
// diagnostics here.
Compiler.createDiagnostics(new clang::IgnoringDiagConsumer,
Compiler.createDiagnostics(Files->getVirtualFileSystem(),
new clang::IgnoringDiagConsumer,
/*ShouldOwnClient=*/true);
Compiler.createSourceManager(*Files);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace {

AST_MATCHER_P(FunctionDecl, isEnabled, llvm::StringSet<>,
FunctionsThatShouldNotThrow) {
return FunctionsThatShouldNotThrow.count(Node.getNameAsString()) > 0;
return FunctionsThatShouldNotThrow.contains(Node.getNameAsString());
}

AST_MATCHER(FunctionDecl, isExplicitThrow) {
Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clang-tidy/modernize/UseStdPrintCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ AST_MATCHER(StringLiteral, isOrdinary) { return Node.isOrdinary(); }
} // namespace

UseStdPrintCheck::UseStdPrintCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
: ClangTidyCheck(Name, Context), PP(nullptr),
StrictMode(Options.getLocalOrGlobal("StrictMode", false)),
PrintfLikeFunctions(utils::options::parseStringList(
Options.get("PrintfLikeFunctions", ""))),
Expand Down Expand Up @@ -131,6 +131,7 @@ void UseStdPrintCheck::check(const MatchFinder::MatchResult &Result) {
utils::FormatStringConverter::Configuration ConverterConfig;
ConverterConfig.StrictMode = StrictMode;
ConverterConfig.AllowTrailingNewlineRemoval = true;
assert(PP && "Preprocessor should be set by registerPPCallbacks");
utils::FormatStringConverter Converter(
Result.Context, Printf, FormatArgOffset, ConverterConfig, getLangOpts(),
*Result.SourceManager, *PP);
Expand Down
13 changes: 10 additions & 3 deletions clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ bool isQualificationConvertiblePointer(QualType From, QualType To,
} // namespace

static bool canThrow(const FunctionDecl *Func) {
// consteval specifies that every call to the function must produce a
// compile-time constant, which cannot evaluate a throw expression without
// producing a compilation error.
if (Func->isConsteval())
return false;

const auto *FunProto = Func->getType()->getAs<FunctionProtoType>();
if (!FunProto)
return true;
Expand Down Expand Up @@ -418,7 +424,7 @@ ExceptionAnalyzer::ExceptionInfo::filterIgnoredExceptions(
if (TD->getDeclName().isIdentifier()) {
if ((IgnoreBadAlloc &&
(TD->getName() == "bad_alloc" && TD->isInStdNamespace())) ||
(IgnoredTypes.count(TD->getName()) > 0))
(IgnoredTypes.contains(TD->getName())))
TypesToDelete.push_back(T);
}
}
Expand Down Expand Up @@ -449,7 +455,8 @@ void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() {
ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
const FunctionDecl *Func, const ExceptionInfo::Throwables &Caught,
llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
if (!Func || CallStack.count(Func) || (!CallStack.empty() && !canThrow(Func)))
if (!Func || CallStack.contains(Func) ||
(!CallStack.empty() && !canThrow(Func)))
return ExceptionInfo::createNonThrowing();

if (const Stmt *Body = Func->getBody()) {
Expand Down Expand Up @@ -507,7 +514,7 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
for (unsigned I = 0; I < Try->getNumHandlers(); ++I) {
const CXXCatchStmt *Catch = Try->getHandler(I);

// Everything is catched through 'catch(...)'.
// Everything is caught through 'catch(...)'.
if (!Catch->getExceptionDecl()) {
ExceptionInfo Rethrown = throwsException(
Catch->getHandlerBlock(), Uncaught.getExceptionTypes(), CallStack);
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ class ExceptionAnalyzer {
/// Recalculate the 'Behaviour' for example after filtering.
void reevaluateBehaviour();

/// Keep track if the entity related to this 'ExceptionInfo' can in princple
/// throw, if it's unknown or if it won't throw.
/// Keep track if the entity related to this 'ExceptionInfo' can in
/// principle throw, if it's unknown or if it won't throw.
State Behaviour;

/// Keep track if the entity contains any unknown elements to keep track
Expand Down
6 changes: 3 additions & 3 deletions clang-tools-extra/clangd/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D,
CIOpts.VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
CIOpts.CC1Args = CC1Args;
CIOpts.RecoverOnError = true;
CIOpts.Diags =
CompilerInstance::createDiagnostics(new DiagnosticOptions, &D, false);
CIOpts.Diags = CompilerInstance::createDiagnostics(
*CIOpts.VFS, new DiagnosticOptions, &D, false);
CIOpts.ProbePrecompiled = false;
std::unique_ptr<CompilerInvocation> CI = createInvocation(ArgStrs, CIOpts);
if (!CI)
Expand Down Expand Up @@ -148,7 +148,7 @@ prepareCompilerInstance(std::unique_ptr<clang::CompilerInvocation> CI,
auto Clang = std::make_unique<CompilerInstance>(
std::make_shared<PCHContainerOperations>());
Clang->setInvocation(std::move(CI));
Clang->createDiagnostics(&DiagsClient, false);
Clang->createDiagnostics(*VFS, &DiagsClient, false);

if (auto VFSWithRemapping = createVFSFromCompilerInvocation(
Clang->getInvocation(), Clang->getDiagnostics(), VFS))
Expand Down
13 changes: 9 additions & 4 deletions clang-tools-extra/clangd/InlayHints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -626,10 +626,15 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {

bool VisitLambdaExpr(LambdaExpr *E) {
FunctionDecl *D = E->getCallOperator();
if (!E->hasExplicitResultType())
addReturnTypeHint(D, E->hasExplicitParameters()
? D->getFunctionTypeLoc().getRParenLoc()
: E->getIntroducerRange().getEnd());
if (!E->hasExplicitResultType()) {
SourceLocation TypeHintLoc;
if (!E->hasExplicitParameters())
TypeHintLoc = E->getIntroducerRange().getEnd();
else if (auto FTL = D->getFunctionTypeLoc())
TypeHintLoc = FTL.getRParenLoc();
if (TypeHintLoc.isValid())
addReturnTypeHint(D, TypeHintLoc);
}
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clangd/ModulesBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath,

clang::clangd::IgnoreDiagnostics IgnoreDiags;
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
CompilerInstance::createDiagnostics(new DiagnosticOptions, &IgnoreDiags,
CompilerInstance::createDiagnostics(*VFS, new DiagnosticOptions,
&IgnoreDiags,
/*ShouldOwnClient=*/false);

LangOptions LangOpts;
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/clangd/Preamble.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,8 +613,9 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
for (const auto &L : ASTListeners)
L->sawDiagnostic(D, Diag);
});
auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
llvm::IntrusiveRefCntPtr<DiagnosticsEngine> PreambleDiagsEngine =
CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(),
CompilerInstance::createDiagnostics(*VFS, &CI.getDiagnosticOpts(),
&PreambleDiagnostics,
/*ShouldOwnClient=*/false);
const Config &Cfg = Config::current();
Expand Down Expand Up @@ -651,7 +652,6 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
for (const auto &L : ASTListeners)
L->beforeExecute(CI);
});
auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
llvm::SmallString<32> AbsFileName(FileName);
VFS->makeAbsolute(AbsFileName);
auto StatCache = std::make_shared<PreambleFileStatusCache>(AbsFileName);
Expand Down
29 changes: 29 additions & 0 deletions clang-tools-extra/clangd/Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,35 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor"))
R.CompletionFixes |= *EditsNearCursor;
}
if (auto *References = TextDocument->getObject("references")) {
if (auto ContainerSupport = References->getBoolean("container")) {
R.ReferenceContainer |= *ContainerSupport;
}
}
if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {
if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline")) {
R.DiagnosticFixes |= *CodeActions;
}
}
if (auto *InactiveRegions =
TextDocument->getObject("inactiveRegionsCapabilities")) {
if (auto InactiveRegionsSupport =
InactiveRegions->getBoolean("inactiveRegions")) {
R.InactiveRegions |= *InactiveRegionsSupport;
}
}
}
if (auto *Window = Experimental->getObject("window")) {
if (auto Implicit =
Window->getBoolean("implicitWorkDoneProgressCreate")) {
R.ImplicitProgressCreation |= *Implicit;
}
}
if (auto *OffsetEncoding = Experimental->get("offsetEncoding")) {
R.offsetEncoding.emplace();
if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
P.field("offsetEncoding")))
return false;
}
}

Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clangd/Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ struct ClientCapabilities {
std::optional<SymbolKindBitset> WorkspaceSymbolKinds;

/// Whether the client accepts diagnostics with codeActions attached inline.
/// This is a clangd extension.
/// textDocument.publishDiagnostics.codeActionsInline.
bool DiagnosticFixes = false;

Expand All @@ -475,6 +476,7 @@ struct ClientCapabilities {

/// Client supports displaying a container string for results of
/// textDocument/reference (clangd extension)
/// textDocument.references.container
bool ReferenceContainer = false;

/// Client supports hierarchical document symbols.
Expand Down Expand Up @@ -563,6 +565,7 @@ struct ClientCapabilities {

/// Whether the client supports the textDocument/inactiveRegions
/// notification. This is a clangd extension.
/// textDocument.inactiveRegionsCapabilities.inactiveRegions
bool InactiveRegions = false;
};
bool fromJSON(const llvm::json::Value &, ClientCapabilities &,
Expand Down
21 changes: 17 additions & 4 deletions clang-tools-extra/clangd/XRefs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>
Expand Down Expand Up @@ -2275,7 +2276,7 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
// Initially store the ranges in a map keyed by SymbolID of the caller.
// This allows us to group different calls with the same caller
// into the same CallHierarchyIncomingCall.
llvm::DenseMap<SymbolID, std::vector<Range>> CallsIn;
llvm::DenseMap<SymbolID, std::vector<Location>> CallsIn;
// We can populate the ranges based on a refs request only. As we do so, we
// also accumulate the container IDs into a lookup request.
LookupRequest ContainerLookup;
Expand All @@ -2285,7 +2286,7 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
elog("incomingCalls failed to convert location: {0}", Loc.takeError());
return;
}
CallsIn[R.Container].push_back(Loc->range);
CallsIn[R.Container].push_back(*Loc);

ContainerLookup.IDs.insert(R.Container);
});
Expand All @@ -2294,9 +2295,21 @@ incomingCalls(const CallHierarchyItem &Item, const SymbolIndex *Index) {
Index->lookup(ContainerLookup, [&](const Symbol &Caller) {
auto It = CallsIn.find(Caller.ID);
assert(It != CallsIn.end());
if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file()))
if (auto CHI = symbolToCallHierarchyItem(Caller, Item.uri.file())) {
std::vector<Range> FromRanges;
for (const Location &L : It->second) {
if (L.uri != CHI->uri) {
// Call location not in same file as caller.
// This can happen in some edge cases. There's not much we can do,
// since the protocol only allows returning ranges interpreted as
// being in the caller's file.
continue;
}
FromRanges.push_back(L.range);
}
Results.push_back(
CallHierarchyIncomingCall{std::move(*CHI), std::move(It->second)});
CallHierarchyIncomingCall{std::move(*CHI), std::move(FromRanges)});
}
});
// Sort results by name of container.
llvm::sort(Results, [](const CallHierarchyIncomingCall &A,
Expand Down
69 changes: 50 additions & 19 deletions clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,13 @@ findContextForNS(llvm::StringRef TargetNS, const DeclContext *CurContext) {
// afterwards it can be shared with define-inline code action.
llvm::Expected<std::string>
getFunctionSourceAfterReplacements(const FunctionDecl *FD,
const tooling::Replacements &Replacements) {
const tooling::Replacements &Replacements,
bool TargetFileIsHeader) {
const auto &SM = FD->getASTContext().getSourceManager();
auto OrigFuncRange = toHalfOpenFileRange(
SM, FD->getASTContext().getLangOpts(), FD->getSourceRange());
if (!OrigFuncRange)
return error("Couldn't get range for function.");
assert(!FD->getDescribedFunctionTemplate() &&
"Define out-of-line doesn't apply to function templates.");

// Get new begin and end positions for the qualified function definition.
unsigned FuncBegin = SM.getFileOffset(OrigFuncRange->getBegin());
Expand All @@ -129,24 +128,38 @@ getFunctionSourceAfterReplacements(const FunctionDecl *FD,
if (!QualifiedFunc)
return QualifiedFunc.takeError();

auto Source = QualifiedFunc->substr(FuncBegin, FuncEnd - FuncBegin + 1);
std::string TemplatePrefix;
auto AddToTemplatePrefixIfApplicable = [&](const Decl *D) {
const TemplateParameterList *Params = D->getDescribedTemplateParams();
if (!Params)
return;
for (Decl *P : *Params) {
if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(P))
TTP->removeDefaultArgument();
else if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P))
NTTP->removeDefaultArgument();
else if (auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(P))
TTPD->removeDefaultArgument();
}
std::string S;
llvm::raw_string_ostream Stream(S);
Params->print(Stream, FD->getASTContext());
if (!S.empty())
*S.rbegin() = '\n'; // Replace space with newline
TemplatePrefix.insert(0, S);
};
AddToTemplatePrefixIfApplicable(FD);
if (auto *MD = llvm::dyn_cast<CXXMethodDecl>(FD)) {
for (const CXXRecordDecl *Parent = MD->getParent(); Parent;
Parent =
llvm::dyn_cast_or_null<const CXXRecordDecl>(Parent->getParent())) {
if (const TemplateParameterList *Params =
Parent->getDescribedTemplateParams()) {
std::string S;
llvm::raw_string_ostream Stream(S);
Params->print(Stream, FD->getASTContext());
if (!S.empty())
*S.rbegin() = '\n'; // Replace space with newline
TemplatePrefix.insert(0, S);
}
AddToTemplatePrefixIfApplicable(Parent);
}
}

auto Source = QualifiedFunc->substr(FuncBegin, FuncEnd - FuncBegin + 1);
if (TargetFileIsHeader)
Source.insert(0, "inline ");
if (!TemplatePrefix.empty())
Source.insert(0, TemplatePrefix);
return Source;
Expand Down Expand Up @@ -202,7 +215,8 @@ deleteTokensWithKind(const syntax::TokenBuffer &TokBuf, tok::TokenKind Kind,
llvm::Expected<std::string>
getFunctionSourceCode(const FunctionDecl *FD, const DeclContext *TargetContext,
const syntax::TokenBuffer &TokBuf,
const HeuristicResolver *Resolver) {
const HeuristicResolver *Resolver,
bool TargetFileIsHeader) {
auto &AST = FD->getASTContext();
auto &SM = AST.getSourceManager();

Expand All @@ -225,6 +239,8 @@ getFunctionSourceCode(const FunctionDecl *FD, const DeclContext *TargetContext,
return;

for (const NamedDecl *ND : Ref.Targets) {
if (ND->getKind() == Decl::TemplateTypeParm)
return;
if (ND->getDeclContext() != Ref.Targets.front()->getDeclContext()) {
elog("Targets from multiple contexts: {0}, {1}",
printQualifiedName(*Ref.Targets.front()),
Expand Down Expand Up @@ -337,7 +353,8 @@ getFunctionSourceCode(const FunctionDecl *FD, const DeclContext *TargetContext,

if (Errors)
return std::move(Errors);
return getFunctionSourceAfterReplacements(FD, DeclarationCleanups);
return getFunctionSourceAfterReplacements(FD, DeclarationCleanups,
TargetFileIsHeader);
}

struct InsertionPoint {
Expand Down Expand Up @@ -419,15 +436,15 @@ class DefineOutline : public Tweak {
Source->isOutOfLine())
return false;

// Bail out if this is a function template or specialization, as their
// Bail out if this is a function template specialization, as their
// definitions need to be visible in all including translation units.
if (Source->getDescribedFunctionTemplate())
return false;
if (Source->getTemplateSpecializationInfo())
return false;

auto *MD = llvm::dyn_cast<CXXMethodDecl>(Source);
if (!MD) {
if (Source->getDescribedFunctionTemplate())
return false;
// Can't outline free-standing functions in the same file.
return !SameFile;
}
Expand All @@ -450,6 +467,19 @@ class DefineOutline : public Tweak {
}
}

// For function templates, the same limitations as for class templates
// apply.
if (const TemplateParameterList *Params =
MD->getDescribedTemplateParams()) {
// FIXME: Is this really needed? It inhibits application on
// e.g. std::enable_if.
for (NamedDecl *P : *Params) {
if (!P->getIdentifier())
return false;
}
SameFile = true;
}

// The refactoring is meaningless for unnamed classes and namespaces,
// unless we're outlining in the same file
for (const DeclContext *DC = MD->getParent(); DC; DC = DC->getParent()) {
Expand Down Expand Up @@ -485,7 +515,8 @@ class DefineOutline : public Tweak {

auto FuncDef = getFunctionSourceCode(
Source, InsertionPoint->EnclosingNamespace, Sel.AST->getTokens(),
Sel.AST->getHeuristicResolver());
Sel.AST->getHeuristicResolver(),
SameFile && isHeaderFile(Sel.AST->tuPath(), Sel.AST->getLangOpts()));
if (!FuncDef)
return FuncDef.takeError();

Expand Down
29 changes: 29 additions & 0 deletions clang-tools-extra/clangd/unittests/CallHierarchyTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,35 @@ TEST(CallHierarchy, HierarchyOnVar) {
fromRanges(Source.range("Callee")))));
}

TEST(CallHierarchy, CallInDifferentFileThanCaller) {
Annotations Header(R"cpp(
#define WALDO void caller() {
)cpp");
Annotations Source(R"cpp(
void call^ee();
WALDO
callee();
}
)cpp");
auto TU = TestTU::withCode(Source.code());
TU.HeaderCode = Header.code();
auto AST = TU.build();
auto Index = TU.index();

std::vector<CallHierarchyItem> Items =
prepareCallHierarchy(AST, Source.point(), testPath(TU.Filename));
ASSERT_THAT(Items, ElementsAre(withName("callee")));

auto Incoming = incomingCalls(Items[0], Index.get());

// The only call site is in the source file, which is a different file from
// the declaration of the function containing the call, which is in the
// header. The protocol does not allow us to represent such calls, so we drop
// them. (The call hierarchy item itself is kept.)
EXPECT_THAT(Incoming,
ElementsAre(AllOf(from(withName("caller")), fromRanges())));
}

} // namespace
} // namespace clangd
} // namespace clang
16 changes: 16 additions & 0 deletions clang-tools-extra/clangd/unittests/InlayHintTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1576,6 +1576,22 @@ TEST(TypeHints, Aliased) {
EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
}

TEST(TypeHints, CallingConvention) {
// Check that we don't crash for lambdas without a FunctionTypeLoc
// https://github.com/clangd/clangd/issues/2223
std::string Code = R"cpp(
void test() {
[]() __cdecl {};
}
)cpp";
TestTU TU = TestTU::withCode(Code);
TU.ExtraArgs.push_back("--target=x86_64-w64-mingw32");
TU.PredefineMacros = true; // for the __cdecl
auto AST = TU.build();

EXPECT_THAT(hintsOfKind(AST, InlayHintKind::Type), IsEmpty());
}

TEST(TypeHints, Decltype) {
assertTypeHints(R"cpp(
$a[[decltype(0)]] a;
Expand Down
49 changes: 43 additions & 6 deletions clang-tools-extra/clangd/unittests/tweaks/DefineOutlineTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,17 @@ TEST_F(DefineOutlineTest, TriggersOnFunctionDecl) {
template <typename> struct Foo { void fo^o(){} };
)cpp");

// Not available on function templates and specializations, as definition must
// be visible to all translation units.
// Not available on function template specializations and free function
// templates.
EXPECT_UNAVAILABLE(R"cpp(
template <typename> void fo^o() {};
template <> void fo^o<int>() {};
template <typename T> void fo^o() {}
template <> void fo^o<int>() {}
)cpp");

// Not available on member function templates with unnamed template
// parameters.
EXPECT_UNAVAILABLE(R"cpp(
struct Foo { template <typename> void ba^r() {} };
)cpp");

// Not available on methods of unnamed classes.
Expand Down Expand Up @@ -237,7 +243,7 @@ TEST_F(DefineOutlineTest, ApplyTest) {
Foo(T z) __attribute__((weak)) ;
int bar;
};template <typename T>
Foo<T>::Foo(T z) __attribute__((weak)) : bar(2){}
inline Foo<T>::Foo(T z) __attribute__((weak)) : bar(2){}
)cpp",
""},
// Virt specifiers.
Expand Down Expand Up @@ -390,7 +396,7 @@ Foo<T>::Foo(T z) __attribute__((weak)) : bar(2){}
};
};template <typename T, typename ...U>
template <class V, int A>
typename O1<T, U...>::template O2<V, A>::E O1<T, U...>::template O2<V, A>::I::foo(T, U..., V, E) { return E1; }
inline typename O1<T, U...>::template O2<V, A>::E O1<T, U...>::template O2<V, A>::I::foo(T, U..., V, E) { return E1; }
)cpp",
""},
// Destructors
Expand All @@ -399,6 +405,37 @@ typename O1<T, U...>::template O2<V, A>::E O1<T, U...>::template O2<V, A>::I::fo
"class A { ~A(); };",
"A::~A(){} ",
},

// Member template
{
R"cpp(
struct Foo {
template <typename T, bool B = true>
T ^bar() { return {}; }
};)cpp",
R"cpp(
struct Foo {
template <typename T, bool B = true>
T bar() ;
};template <typename T, bool B>
inline T Foo::bar() { return {}; }
)cpp",
""},

// Class template with member template
{
R"cpp(
template <typename T> struct Foo {
template <typename U> T ^bar(const T& t, const U& u) { return {}; }
};)cpp",
R"cpp(
template <typename T> struct Foo {
template <typename U> T bar(const T& t, const U& u) ;
};template <typename T>
template <typename U>
inline T Foo<T>::bar(const T& t, const U& u) { return {}; }
)cpp",
""},
};
for (const auto &Case : Cases) {
SCOPED_TRACE(Case.Test);
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ Changes in existing checks
<clang-tidy/checks/bugprone/dangling-handle>` check to treat `std::span` as a
handle class.

- Improved :doc:`bugprone-exception-escape
<clang-tidy/checks/bugprone/exception-escape>` by fixing false positives
when a consteval function with throw statements.

- Improved :doc:`bugprone-forwarding-reference-overload
<clang-tidy/checks/bugprone/forwarding-reference-overload>` check by fixing
a crash when determining if an ``enable_if[_t]`` was found.
Expand Down
19 changes: 10 additions & 9 deletions clang-tools-extra/include-cleaner/unittests/RecordTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,15 +609,6 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) {
)cpp";
Inputs.ExtraFiles["foo.h"] = "";

auto Clang = std::make_unique<CompilerInstance>(
std::make_shared<PCHContainerOperations>());
Clang->createDiagnostics();

Clang->setInvocation(std::make_unique<CompilerInvocation>());
ASSERT_TRUE(CompilerInvocation::CreateFromArgs(
Clang->getInvocation(), {Filename.data()}, Clang->getDiagnostics(),
"clang"));

// Create unnamed memory buffers for all the files.
auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
VFS->addFile(Filename, /*ModificationTime=*/0,
Expand All @@ -626,6 +617,16 @@ TEST_F(PragmaIncludeTest, ExportInUnnamedBuffer) {
VFS->addFile(Extra.getKey(), /*ModificationTime=*/0,
llvm::MemoryBuffer::getMemBufferCopy(Extra.getValue(),
/*BufferName=*/""));

auto Clang = std::make_unique<CompilerInstance>(
std::make_shared<PCHContainerOperations>());
Clang->createDiagnostics(*VFS);

Clang->setInvocation(std::make_unique<CompilerInvocation>());
ASSERT_TRUE(CompilerInvocation::CreateFromArgs(
Clang->getInvocation(), {Filename.data()}, Clang->getDiagnostics(),
"clang"));

auto *FM = Clang->createFileManager(VFS);
ASSERT_TRUE(Clang->ExecuteAction(*Inputs.MakeAction()));
EXPECT_THAT(
Expand Down
2 changes: 0 additions & 2 deletions clang-tools-extra/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ set(CLANG_TOOLS_TEST_DEPS
clang-resource-headers

clang-tidy
# Clang-tidy tests need clang for building modules.
clang
)

# Add lit test dependencies.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %check_clang_tidy -std=c++20 %s bugprone-exception-escape %t -- \
// RUN: -- -fexceptions -Wno-everything

namespace GH104457 {

consteval int consteval_fn(int a) {
if (a == 0)
throw 1;
return a;
}

int test() noexcept { return consteval_fn(1); }

} // namespace GH104457
6 changes: 5 additions & 1 deletion clang/cmake/caches/CrossWinToARMLinux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ if (NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
endif()

set(CMAKE_CROSSCOMPILING ON CACHE BOOL "")
set(CMAKE_CL_SHOWINCLUDES_PREFIX "Note: including file: " CACHE STRING "")
# Required if COMPILER_RT_DEFAULT_TARGET_ONLY is ON
set(CMAKE_C_COMPILER_TARGET "${TOOLCHAIN_TARGET_TRIPLE}" CACHE STRING "")
Expand Down Expand Up @@ -219,6 +218,11 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_CXX_ABI
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "")
# Merge libc++ and libc++abi libraries into the single libc++ library file.
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
# Forcely disable the libc++ benchmarks on Windows build hosts
# (current benchmark test configuration does not support the cross builds there).
if (WIN32)
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_INCLUDE_BENCHMARKS OFF CACHE BOOL "")
endif(WIN32)

# Avoid searching for the python3 interpreter during the runtimes configuration for the cross builds.
# It starts searching the python3 package using the target's sysroot path, that usually is not compatible with the build host.
Expand Down
6 changes: 2 additions & 4 deletions clang/cmake/caches/Fuchsia-stage2.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi;armv8.1m.
foreach(lang C;CXX;ASM)
# TODO: The preprocessor defines workaround various issues in libc and libc++ integration.
# These should be addressed and removed over time.
set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -mthumb -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dtimeval=struct timeval{int tv_sec; int tv_usec;}\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1")
set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "--target=${target} -mthumb -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1")
if(${target} STREQUAL "armv8m.main-none-eabi")
set(RUNTIMES_${target}_CMAKE_${lang}_local_flags "${RUNTIMES_${target}_CMAKE_${lang}_local_flags} -mfloat-abi=softfp -march=armv8m.main+fp+dsp -mcpu=cortex-m33" CACHE STRING "")
endif()
Expand All @@ -346,7 +346,6 @@ foreach(target armv6m-none-eabi;armv7m-none-eabi;armv8m.main-none-eabi;armv8.1m.
endforeach()
set(RUNTIMES_${target}_LLVM_LIBC_FULL_BUILD ON CACHE BOOL "")
set(RUNTIMES_${target}_LIBC_ENABLE_USE_BY_CLANG ON CACHE BOOL "")
set(RUNTIMES_${target}_LIBC_USE_NEW_HEADER_GEN OFF CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_ABI_VERSION 2 CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_CXX_ABI none CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
Expand Down Expand Up @@ -391,14 +390,13 @@ foreach(target riscv32-unknown-elf)
foreach(lang C;CXX;ASM)
# TODO: The preprocessor defines workaround various issues in libc and libc++ integration.
# These should be addressed and removed over time.
set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dtimeval=struct timeval{int tv_sec; int tv_usec;}\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1" CACHE STRING "")
set(RUNTIMES_${target}_CMAKE_${lang}_FLAGS "--target=${target} -march=rv32imafc -mabi=ilp32f -Wno-atomic-alignment \"-Dvfprintf(stream, format, vlist)=vprintf(format, vlist)\" \"-Dfprintf(stream, format, ...)=printf(format)\" \"-Dgettimeofday(tv, tz)\" -D_LIBCPP_PRINT=1" CACHE STRING "")
endforeach()
foreach(type SHARED;MODULE;EXE)
set(RUNTIMES_${target}_CMAKE_${type}_LINKER_FLAGS "-fuse-ld=lld" CACHE STRING "")
endforeach()
set(RUNTIMES_${target}_LLVM_LIBC_FULL_BUILD ON CACHE BOOL "")
set(RUNTIMES_${target}_LIBC_ENABLE_USE_BY_CLANG ON CACHE BOOL "")
set(RUNTIMES_${target}_LIBC_USE_NEW_HEADER_GEN OFF CACHE BOOL "")
set(RUNTIMES_${target}_LIBCXX_ABI_VERSION 2 CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_CXX_ABI none CACHE STRING "")
set(RUNTIMES_${target}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
Expand Down
4 changes: 4 additions & 0 deletions clang/docs/InternalsManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,10 @@ wording a diagnostic.
named in a diagnostic message. e.g., prefer wording like ``'this' pointer
cannot be null in well-defined C++ code`` over wording like ``this pointer
cannot be null in well-defined C++ code``.
* Prefer diagnostic wording without contractions whenever possible. The single
quote in a contraction can be visually distracting due to its use with
syntactic constructs and contractions can be harder to understand for non-
native English speakers.

The Format String
^^^^^^^^^^^^^^^^^
Expand Down
4 changes: 4 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,10 @@ at the end to the next power of 2.

These reductions support both fixed-sized and scalable vector types.

The integer reduction intrinsics, including ``__builtin_reduce_add``,
``__builtin_reduce_mul``, ``__builtin_reduce_and``, ``__builtin_reduce_or``,
and ``__builtin_reduce_xor``, can be called in a ``constexpr`` context.

Example:

.. code-block:: c++
Expand Down
44 changes: 43 additions & 1 deletion clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,11 @@ A **partial** list of flags RealtimeSanitizer respects:
* - ``halt_on_error``
- ``true``
- boolean
- Exit after first reported error. If false (continue after a detected error), deduplicates error stacks so errors appear only once.
- Exit after first reported error.
* - ``suppress_equal_stacks``
- ``true``
- boolean
- If true, suppress duplicate reports (i.e. only print each unique error once). Only particularly useful when ``halt_on_error=false``.
* - ``print_stats_on_exit``
- ``false``
- boolean
Expand Down Expand Up @@ -203,6 +207,44 @@ Some issues with flags can be debugged using the ``verbosity=$NUM`` flag:
misspelled_flag
...
Additional customization
------------------------

In addition to ``__rtsan_default_options`` outlined above, you can provide definitions of other functions that affect how RTSan operates.

To be notified on every error reported by RTsan, provide a definition of ``__sanitizer_report_error_summary``.

.. code-block:: c
extern "C" void __sanitizer_report_error_summary(const char *error_summary) {
fprintf(stderr, "%s %s\n", "In custom handler! ", error_summary);
/* do other custom things */
}
The error summary will be of the form:

.. code-block:: console
SUMMARY: RealtimeSanitizer: unsafe-library-call main.cpp:8 in process(std::__1::vector<int, std::__1::allocator<int>>&)
To register a callback which will be invoked before a RTSan kills the process:

.. code-block:: c
extern "C" void __sanitizer_set_death_callback(void (*callback)(void));
void custom_on_die_callback() {
fprintf(stderr, "In custom handler!")
/* do other custom things */
}
int main()
{
__sanitizer_set_death_callback(custom_on_die_callback);
...
}
Disabling and suppressing
-------------------------

Expand Down
50 changes: 50 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,17 @@ C++ Specific Potentially Breaking Changes
// Now diagnoses with an error.
void f(int& i [[clang::lifetimebound]]);

- Clang now rejects all field accesses on null pointers in constant expressions. The following code
used to work but will now be rejected:

.. code-block:: c++

struct S { int a; int b; };
constexpr const int *p = &((S*)nullptr)->b;

Previously, this code was erroneously accepted.


ABI Changes in This Version
---------------------------

Expand Down Expand Up @@ -356,6 +367,9 @@ Non-comprehensive list of changes in this release
issues with the sanitizer because the counter is automatically set.

- ``__builtin_reduce_add`` function can now be used in constant expressions.
- ``__builtin_reduce_mul`` function can now be used in constant expressions.
- ``__builtin_reduce_and`` function can now be used in constant expressions.
- ``__builtin_reduce_or`` and ``__builtin_reduce_xor`` functions can now be used in constant expressions.

New Compiler Flags
------------------
Expand Down Expand Up @@ -537,6 +551,38 @@ Improvements to Clang's diagnostics

- Improved diagnostic message for ``__builtin_bit_cast`` size mismatch (#GH115870).

- Clang now omits shadow warnings for enum constants in separate class scopes (#GH62588).

- When diagnosing an unused return value of a type declared ``[[nodiscard]]``, the type
itself is now included in the diagnostic.

- Clang will now prefer the ``[[nodiscard]]`` declaration on function declarations over ``[[nodiscard]]``
declaration on the return type of a function. Previously, when both have a ``[[nodiscard]]`` declaration attached,
the one on the return type would be preferred. This may affect the generated warning message:

.. code-block:: c++

struct [[nodiscard("Reason 1")]] S {};
[[nodiscard("Reason 2")]] S getS();
void use()
{
getS(); // Now diagnoses "Reason 2", previously diagnoses "Reason 1"
}

- Clang now diagnoses ``= delete("reason")`` extension warnings only in pedantic mode rather than on by default. (#GH109311).

- Clang now diagnoses missing return value in functions containing ``if consteval`` (#GH116485).

- Clang now correctly recognises code after a call to a ``[[noreturn]]`` constructor
as unreachable (#GH63009).

- Clang now omits shadowing warnings for parameter names in explicit object member functions (#GH95707).

- Improved error recovery for function call arguments with trailing commas (#GH100921).

- For an rvalue reference bound to a temporary struct with an integer member, Clang will detect constant integer overflow
in the initializer for the integer member (#GH46755).

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

Expand Down Expand Up @@ -666,6 +712,8 @@ Bug Fixes to C++ Support
- Name independent data members were not correctly initialized from default member initializers. (#GH114069)
- Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the
assumption if they also occur inside of a dependent lambda. (#GH114787)
- Clang now uses valid deduced type locations when diagnosing functions with trailing return type
missing placeholder return type. (#GH78694)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -712,6 +760,8 @@ Target Specific Changes
AMDGPU Support
^^^^^^^^^^^^^^

- Initial support for gfx950

- Added headers ``gpuintrin.h`` and ``amdgpuintrin.h`` that contains common
definitions for GPU builtin functions. This header can be included for OpenMP,
CUDA, HIP, OpenCL, and C/C++.
Expand Down
24 changes: 19 additions & 5 deletions clang/docs/ThreadSafetyAnalysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -933,11 +933,25 @@ implementation.
MutexLocker(Mutex *mu, defer_lock_t) EXCLUDES(mu) : mut(mu), locked(false) {}
// Same as constructors, but without tag types. (Requires C++17 copy elision.)
static MutexLocker Lock(Mutex *mu) ACQUIRE(mu);
static MutexLocker Adopt(Mutex *mu) REQUIRES(mu);
static MutexLocker ReaderLock(Mutex *mu) ACQUIRE_SHARED(mu);
static MutexLocker AdoptReaderLock(Mutex *mu) REQUIRES_SHARED(mu);
static MutexLocker DeferLock(Mutex *mu) EXCLUDES(mu);
static MutexLocker Lock(Mutex *mu) ACQUIRE(mu) {
return MutexLocker(mu);
}
static MutexLocker Adopt(Mutex *mu) REQUIRES(mu) {
return MutexLocker(mu, adopt_lock);
}
static MutexLocker ReaderLock(Mutex *mu) ACQUIRE_SHARED(mu) {
return MutexLocker(mu, shared_lock);
}
static MutexLocker AdoptReaderLock(Mutex *mu) REQUIRES_SHARED(mu) {
return MutexLocker(mu, adopt_lock, shared_lock);
}
static MutexLocker DeferLock(Mutex *mu) EXCLUDES(mu) {
return MutexLocker(mu, defer_lock);
}
// Release *this and all associated mutexes, if they are still held.
// There is no warning if the scope was already unlocked before.
Expand Down
8 changes: 5 additions & 3 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -3181,12 +3181,14 @@ class CallExpr : public Expr {
QualType getCallReturnType(const ASTContext &Ctx) const;

/// Returns the WarnUnusedResultAttr that is either declared on the called
/// function, or its return type declaration.
const Attr *getUnusedResultAttr(const ASTContext &Ctx) const;
/// function, or its return type declaration, together with a NamedDecl that
/// refers to the declaration the attribute is attached onto.
std::pair<const NamedDecl *, const Attr *>
getUnusedResultAttr(const ASTContext &Ctx) const;

/// Returns true if this call expression should warn on unused results.
bool hasUnusedResultAttr(const ASTContext &Ctx) const {
return getUnusedResultAttr(Ctx) != nullptr;
return getUnusedResultAttr(Ctx).second != nullptr;
}

SourceLocation getRParenLoc() const { return RParenLoc; }
Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4888,3 +4888,10 @@ def ClspvLibclcBuiltin: InheritableAttr {
let Documentation = [ClspvLibclcBuiltinDoc];
let SimpleHandler = 1;
}

def NoTrivialAutoVarInit: InheritableAttr {
let Spellings = [Declspec<"no_init_all">];
let Subjects = SubjectList<[Function, Tag]>;
let Documentation = [NoTrivialAutoVarInitDocs];
let SimpleHandler = 1;
}
71 changes: 62 additions & 9 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3921,17 +3921,42 @@ have their lifetimes extended.
def LifetimeCaptureByDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Similar to `lifetimebound`_, the ``lifetime_capture_by(X)`` attribute on a function
parameter or implicit object parameter indicates that that objects that are referred to
by that parameter may also be referred to by the capturing entity ``X``.
Similar to `lifetimebound`_, the ``lifetime_capture_by(X)`` attribute on a
function parameter or implicit object parameter indicates that the capturing
entity ``X`` may refer to the object referred by that parameter.

Below is a list of types of the parameters and what they're considered to refer to:

- A reference param (of non-view type) is considered to refer to its referenced object.
- A pointer param (of non-view type) is considered to refer to its pointee.
- View type param (type annotated with ``[[gsl::Pointer()]]``) is considered to refer
to its pointee (gsl owner). This holds true even if the view type appears as a reference
in the parameter. For example, both ``std::string_view`` and
``const std::string_view &`` are considered to refer to a ``std::string``.
- A ``std::initializer_list<T>`` is considered to refer to its underlying array.
- Aggregates (arrays and simple ``struct``\s) are considered to refer to all
objects that their transitive subobjects refer to.

Clang would diagnose when a temporary object is used as an argument to such an
annotated parameter.
In this case, the capturing entity ``X`` could capture a dangling reference to this
temporary object.

By default, a reference is considered to refer to its referenced object, a
pointer is considered to refer to its pointee, a ``std::initializer_list<T>``
is considered to refer to its underlying array, and aggregates (arrays and
simple ``struct``\s) are considered to refer to all objects that their
transitive subobjects refer to.
.. code-block:: c++

void addToSet(std::string_view a [[clang::lifetime_capture_by(s)]], std::set<std::string_view>& s) {
s.insert(a);
}
void use() {
std::set<std::string_view> s;
addToSet(std::string(), s); // Warning: object whose reference is captured by 's' will be destroyed at the end of the full-expression.
// ^^^^^^^^^^^^^
std::string local;
addToSet(local, s); // Ok.
}

The capturing entity ``X`` can be one of the following:

- Another (named) function parameter.

.. code-block:: c++
Expand All @@ -3951,7 +3976,7 @@ The capturing entity ``X`` can be one of the following:
std::set<std::string_view> s;
};

- 'global', 'unknown' (without quotes).
- `global`, `unknown`.

.. code-block:: c++

Expand Down Expand Up @@ -3983,6 +4008,22 @@ The attribute supports specifying more than one capturing entities:
s2.insert(a);
}

Limitation: The capturing entity ``X`` is not used by the analysis and is
used for documentation purposes only. This is because the analysis is
statement-local and only detects use of a temporary as an argument to the
annotated parameter.

.. code-block:: c++

void addToSet(std::string_view a [[clang::lifetime_capture_by(s)]], std::set<std::string_view>& s);
void use() {
std::set<std::string_view> s;
if (foo()) {
std::string str;
addToSet(str, s); // Not detected.
}
}

.. _`lifetimebound`: https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
}];
}
Expand Down Expand Up @@ -8719,6 +8760,18 @@ Attribute used by `clspv`_ (OpenCL-C to Vulkan SPIR-V compiler) to identify func
}];
}

def NoTrivialAutoVarInitDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
The ``__declspec(no_init_all)`` attribute disables the automatic initialization that the
`-ftrivial-auto-var-init`_ flag would have applied to locals in a marked function, or instances of
a marked type. Note that this attribute has no effect for locals that are automatically initialized
without the `-ftrivial-auto-var-init`_ flag.

.. _`-ftrivial-auto-var-init`: ClangCommandLineReference.html#cmdoption-clang-ftrivial-auto-var-init
}];
}

def DocCatNonBlockingNonAllocating : DocumentationCategory<"Performance Constraint Attributes"> {
let Content = [{
The ``nonblocking``, ``blocking``, ``nonallocating`` and ``allocating`` attributes can be attached
Expand Down
20 changes: 16 additions & 4 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -1486,19 +1486,19 @@ def ReduceMinimum : Builtin {

def ReduceXor : Builtin {
let Spellings = ["__builtin_reduce_xor"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}

def ReduceOr : Builtin {
let Spellings = ["__builtin_reduce_or"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}

def ReduceAnd : Builtin {
let Spellings = ["__builtin_reduce_and"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}

Expand All @@ -1510,7 +1510,7 @@ def ReduceAdd : Builtin {

def ReduceMul : Builtin {
let Spellings = ["__builtin_reduce_mul"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
let Prototype = "void(...)";
}

Expand Down Expand Up @@ -1995,6 +1995,12 @@ def AtomicThreadFence : Builtin {
let Prototype = "void(int)";
}

def ScopedAtomicThreadFence : Builtin {
let Spellings = ["__scoped_atomic_thread_fence"];
let Attributes = [NoThrow];
let Prototype = "void(int, int)";
}

def AtomicSignalFence : Builtin {
let Spellings = ["__atomic_signal_fence"];
let Attributes = [NoThrow];
Expand Down Expand Up @@ -4744,6 +4750,12 @@ def HLSLAny : LangBuiltin<"HLSL_LANG"> {
let Prototype = "bool(...)";
}

def HLSLWaveActiveAnyTrue : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_wave_active_any_true"];
let Attributes = [NoThrow, Const];
let Prototype = "bool(bool)";
}

def HLSLWaveActiveCountBits : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_wave_active_count_bits"];
let Attributes = [NoThrow, Const];
Expand Down
26 changes: 26 additions & 0 deletions clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,30 @@ TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f32, "iffiIb", "nc", "fp8-conversion-
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f32, "ifiiIi", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f32, "ifiiIi", "nc", "fp8-conversion-insts")

//===----------------------------------------------------------------------===//
// GFX950 only builtins.
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_mfma_scale_f32_16x16x128_f8f6f4, "V4fV8ZiV8ZiV4fIiIiIiiIii", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_scale_f32_32x32x64_f8f6f4, "V16fV8ZiV8ZiV16fIiIiIiiIii", "nc", "gfx950-insts")

TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_f16, "V4fV8hV8hV4fIiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_bf16, "V4fV8yV8yV4fIiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_f16, "V16fV8hV8hV16fIiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_bf16, "V16fV8yV8yV16fIiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_16x16x64_i8, "V4iV4iV4iV4iIiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_i32_32x32x32_i8, "V16iV4iV4iV16iIiIiIi", "nc", "gfx950-insts")

TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x64_f16, "V4fV8hV16hV4fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_f16, "V16fV8hV16hV16fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x64_bf16, "V4fV8yV16yV4fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_32x32x32_bf16, "V16fV8yV16yV16fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_i32_16x16x128_i8, "V4iV4iV8iV4iiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_i32_32x32x64_i8, "V16iV4iV8iV16iiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x128_bf8_bf8, "V4fV4iV8iV4fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x128_bf8_fp8, "V4fV4iV8iV4fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x128_fp8_bf8, "V4fV4iV8iV4fiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_smfmac_f32_16x16x128_fp8_fp8, "V4fV4iV8iV4fiIiIi", "nc", "gfx950-insts")

//===----------------------------------------------------------------------===//
// GFX12+ only builtins.
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -522,5 +546,7 @@ TARGET_BUILTIN(__builtin_amdgcn_swmmac_f32_16x16x32_fp8_bf8_w64, "V4fiV2iV4fs",
TARGET_BUILTIN(__builtin_amdgcn_swmmac_f32_16x16x32_bf8_fp8_w64, "V4fiV2iV4fs", "nc", "gfx12-insts,wavefrontsize64")
TARGET_BUILTIN(__builtin_amdgcn_swmmac_f32_16x16x32_bf8_bf8_w64, "V4fiV2iV4fs", "nc", "gfx12-insts,wavefrontsize64")

TARGET_BUILTIN(__builtin_amdgcn_prng_b32, "UiUi", "nc", "prng-inst")

#undef BUILTIN
#undef TARGET_BUILTIN
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/BuiltinsLoongArchLASX.def
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ TARGET_BUILTIN(__builtin_lasx_xvor_v, "V32UcV32UcV32Uc", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvxor_v, "V32UcV32UcV32Uc", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvnor_v, "V32UcV32UcV32Uc", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvandn_v, "V32UcV32UcV32Uc", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvorn_v, "V32ScV32ScV32Sc", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvorn_v, "V32UcV32UcV32Uc", "nc", "lasx")

TARGET_BUILTIN(__builtin_lasx_xvandi_b, "V32UcV32UcIUi", "nc", "lasx")
TARGET_BUILTIN(__builtin_lasx_xvori_b, "V32UcV32UcIUi", "nc", "lasx")
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/BuiltinsLoongArchLSX.def
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ TARGET_BUILTIN(__builtin_lsx_vor_v, "V16UcV16UcV16Uc", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vxor_v, "V16UcV16UcV16Uc", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vnor_v, "V16UcV16UcV16Uc", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vandn_v, "V16UcV16UcV16Uc", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vorn_v, "V16ScV16ScV16Sc", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vorn_v, "V16UcV16UcV16Uc", "nc", "lsx")

TARGET_BUILTIN(__builtin_lsx_vandi_b, "V16UcV16UcIUi", "nc", "lsx")
TARGET_BUILTIN(__builtin_lsx_vori_b, "V16UcV16UcIUi", "nc", "lsx")
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Cuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ enum class OffloadArch {
GFX940,
GFX941,
GFX942,
GFX950,
GFX10_1_GENERIC,
GFX1010,
GFX1011,
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -364,9 +364,9 @@ def err_target_unsupported_abi_with_fpu : Error<

def err_ppc_impossible_musttail: Error<
"'musttail' attribute for this call is impossible because %select{"
"long calls can not be tail called on PPC|"
"indirect calls can not be tail called on PPC|"
"external calls can not be tail called on PPC}0"
"long calls cannot be tail called on PPC|"
"indirect calls cannot be tail called on PPC|"
"external calls cannot be tail called on PPC}0"
>;
def err_aix_musttail_unsupported: Error<
"'musttail' attribute is not supported on AIX">;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ def err_test_module_file_extension_format : Error<
"'blockname:major:minor:hashed:user info'">;

def err_drv_module_output_with_multiple_arch : Error<
"option '-fmodule-output' can't be used with multiple arch options">;
"option '-fmodule-output' cannot be used with multiple arch options">;

def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
def DanglingAssignment: DiagGroup<"dangling-assignment">;
def DanglingAssignmentGsl : DiagGroup<"dangling-assignment-gsl">;
def DanglingCapture : DiagGroup<"dangling-capture">;
def DanglingElse: DiagGroup<"dangling-else">;
def DanglingField : DiagGroup<"dangling-field">;
def DanglingInitializerList : DiagGroup<"dangling-initializer-list">;
Expand All @@ -462,6 +463,7 @@ def ReturnStackAddress : DiagGroup<"return-stack-address">;
def : DiagGroup<"return-local-addr", [ReturnStackAddress]>;
def Dangling : DiagGroup<"dangling", [DanglingAssignment,
DanglingAssignmentGsl,
DanglingCapture,
DanglingField,
DanglingInitializerList,
DanglingGsl,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ def warn_cxx98_compat_defaulted_deleted_function : Warning<
"%select{defaulted|deleted}0 function definitions are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;

def ext_delete_with_message : ExtWarn<
def ext_delete_with_message : Extension<
"'= delete' with a message is a C++2c extension">, InGroup<CXX26>;
def warn_cxx23_delete_with_message : Warning<
"'= delete' with a message is incompatible with C++ standards before C++2c">,
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/DiagnosticRefactoringKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ let Component = "Refactoring" in {

let CategoryName = "Refactoring Invocation Issue" in {

def err_refactor_no_selection : Error<"refactoring action can't be initiated "
def err_refactor_no_selection : Error<"refactoring action cannot be initiated "
"without a selection">;
def err_refactor_selection_no_symbol : Error<"there is no symbol at the given "
"location">;
Expand All @@ -26,7 +26,7 @@ def err_refactor_code_outside_of_function : Error<"the selected code is not a "
def err_refactor_extract_simple_expression : Error<"the selected expression "
"is too simple to extract">;
def err_refactor_extract_prohibited_expression : Error<"the selected "
"expression can't be extracted">;
"expression cannot be extracted">;

}

Expand Down
42 changes: 23 additions & 19 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1151,7 +1151,7 @@ def err_pragma_attribute_matcher_subrule_contradicts_rule : Error<
def err_pragma_attribute_matcher_negated_subrule_contradicts_subrule : Error<
"negated attribute subject matcher sub-rule '%0' contradicts sub-rule '%1'">;
def err_pragma_attribute_invalid_matchers : Error<
"attribute %0 can't be applied to %1">;
"attribute %0 cannot be applied to %1">;
def err_pragma_attribute_stack_mismatch : Error<
"'#pragma clang attribute %select{%1.|}0pop' with no matching"
" '#pragma clang attribute %select{%1.|}0push'">;
Expand Down Expand Up @@ -6150,7 +6150,7 @@ def err_mismatched_owning_module : Error<
"declaration of %0 in %select{the global module|module %2}1 follows "
"declaration in %select{the global module|module %4}3">;
def err_multiple_decl_in_different_modules : Error<
"declaration %0 attached to named module '%1' can't be attached to "
"declaration %0 attached to named module '%1' cannot be attached to "
"other modules">;
def err_redefinition_different_type : Error<
"redefinition of %0 with a different type%diff{: $ vs $|}1,2">;
Expand Down Expand Up @@ -8560,7 +8560,7 @@ def err_typecheck_missing_return_type_incompatible : Error<
"literal|lambda expression}2 has unspecified explicit return type">;

def note_incomplete_class_and_qualified_id : Note<
"conformance of forward class %0 to protocol %1 can not be confirmed">;
"conformance of forward class %0 to protocol %1 cannot be confirmed">;
def warn_incompatible_qualified_id : Warning<
"%select{%diff{assigning to $ from incompatible type $|"
"assigning to type from incompatible type}0,1"
Expand Down Expand Up @@ -9300,11 +9300,11 @@ def warn_unused_container_subscript_expr : Warning<
def warn_unused_call : Warning<
"ignoring return value of function declared with %0 attribute">,
InGroup<UnusedValue>;
def warn_unused_constructor : Warning<
"ignoring temporary created by a constructor declared with %0 attribute">,
def warn_unused_return_type : Warning<
"ignoring %select{return value|temporary}0 of type %2 declared with %1 attribute%select{|: %4}3">,
InGroup<UnusedValue>;
def warn_unused_constructor_msg : Warning<
"ignoring temporary created by a constructor declared with %0 attribute: %1">,
def warn_unused_constructor : Warning<
"ignoring temporary created by a constructor declared with %0 attribute%select{|: %2}1">,
InGroup<UnusedValue>;
def warn_side_effects_unevaluated_context : Warning<
"expression with side effects has no effect in an unevaluated context">,
Expand All @@ -9313,10 +9313,7 @@ def warn_side_effects_typeid : Warning<
"expression with side effects will be evaluated despite being used as an "
"operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>;
def warn_unused_result : Warning<
"ignoring return value of function declared with %0 attribute">,
InGroup<UnusedResult>;
def warn_unused_result_msg : Warning<
"ignoring return value of function declared with %0 attribute: %1">,
"ignoring return value of function declared with %0 attribute%select{|: %2}1">,
InGroup<UnusedResult>;
def warn_unused_result_typedef_unsupported_spelling : Warning<
"'[[%select{nodiscard|gnu::warn_unused_result}0]]' attribute ignored when "
Expand Down Expand Up @@ -9414,7 +9411,7 @@ let CategoryName = "Inline Assembly Issue" in {
"asm constraint has an unexpected number of alternatives: %0 vs %1">;
def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">;
def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
def err_asm_unwind_and_goto : Error<"unwind clobber can't be used with asm goto">;
def err_asm_unwind_and_goto : Error<"unwind clobber cannot be used with asm goto">;
def err_asm_invalid_global_var_reg : Error<"register '%0' unsuitable for "
"global register variables on this target">;
def err_asm_register_size_mismatch : Error<"size of register '%0' does not "
Expand All @@ -9433,7 +9430,7 @@ let CategoryName = "Inline Assembly Issue" in {
def err_asm_input_duplicate_match : Error<
"more than one input constraint matches the same output '%0'">;
def err_store_value_to_reg : Error<
"impossible constraint in asm: can't store value into a register">;
"impossible constraint in asm: cannot store value into a register">;

def warn_asm_label_on_auto_decl : Warning<
"ignored asm label '%0' on automatic variable">;
Expand Down Expand Up @@ -10132,10 +10129,11 @@ def err_lifetimebound_ctor_dtor : Error<
"%select{constructor|destructor}0">;
def err_lifetimebound_parameter_void_return_type : Error<
"'lifetimebound' attribute cannot be applied to a parameter of a function "
"that returns void">;
"that returns void; did you mean 'lifetime_capture_by(X)'">;
def err_lifetimebound_implicit_object_parameter_void_return_type : Error<
"'lifetimebound' attribute cannot be applied to an implicit object "
"parameter of a function that returns void">;
"parameter of a function that returns void; "
"did you mean 'lifetime_capture_by(X)'">;

// CHECK: returning address/reference of stack memory
def warn_ret_stack_addr_ref : Warning<
Expand Down Expand Up @@ -10230,6 +10228,12 @@ def warn_dangling_pointer_assignment : Warning<
"object backing %select{|the pointer }0%1 "
"will be destroyed at the end of the full-expression">,
InGroup<DanglingAssignment>;
def warn_dangling_reference_captured : Warning<
"object whose reference is captured by '%0' will be destroyed at the end of "
"the full-expression">, InGroup<DanglingCapture>, DefaultIgnore;
def warn_dangling_reference_captured_by_unknown : Warning<
"object whose reference is captured will be destroyed at the end of "
"the full-expression">, InGroup<DanglingCapture>, DefaultIgnore;

// For non-floating point, expressions of the form x == x or x != x
// should result in a warning, since these always evaluate to a constant.
Expand Down Expand Up @@ -10960,7 +10964,7 @@ def err_opencl_builtin_pipe_invalid_access_modifier : Error<
def err_opencl_invalid_access_qualifier : Error<
"access qualifier can only be used for pipe and image type">;
def err_opencl_invalid_read_write : Error<
"access qualifier %0 can not be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 "
"access qualifier %0 cannot be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 "
"and without __opencl_c_read_write_images feature}2">;
def err_opencl_multiple_access_qualifiers : Error<
"multiple access qualifiers">;
Expand Down Expand Up @@ -11460,7 +11464,7 @@ def err_omp_wrong_linear_modifier : Error<
def err_omp_wrong_linear_modifier_non_reference : Error<
"variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">;
def err_omp_step_simple_modifier_exclusive : Error<
"step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier">;
"step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier">;
def err_omp_wrong_simdlen_safelen_values : Error<
"the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">;
def err_omp_wrong_if_directive_name_modifier : Error<
Expand Down Expand Up @@ -11534,7 +11538,7 @@ def err_omp_schedule_nonmonotonic_static : Error<
def err_omp_simple_clause_incompatible_with_ordered : Error<
"'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">;
def err_omp_ordered_simd : Error<
"'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">;
"'ordered' clause with a parameter cannot be specified in '#pragma omp %0' directive">;
def err_omp_variable_in_given_clause_and_dsa : Error<
"%0 variable cannot be in a %1 clause in '#pragma omp %2' directive">;
def err_omp_param_or_this_in_clause : Error<
Expand Down Expand Up @@ -12366,7 +12370,7 @@ def err_preserve_enum_value_not_const: Error<
"__builtin_preserve_enum_value argument %0 not a constant">;

def err_bit_cast_non_trivially_copyable : Error<
"__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">;
"'__builtin_bit_cast' %select{source|destination}0 type must be trivially copyable">;
def err_bit_cast_type_size_mismatch : Error<
"size of '__builtin_bit_cast' source type %0 does not match destination type %1 (%2 vs %3 bytes)">;

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFuncti
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
FEATURE(ptrauth_init_fini_address_discrimination, LangOpts.PointerAuthInitFiniAddressDiscrimination)
FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT)
EXTENSION(swiftcc,
PP.getTargetInfo().checkCallingConvention(CC_Swift) ==
clang::TargetInfo::CCCR_OK)
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1871,6 +1871,11 @@ class TargetInfo : public TransferrableTargetInfo,
void CheckFixedPointBits() const;
};

namespace targets {
std::unique_ptr<clang::TargetInfo>
AllocateTarget(const llvm::Triple &Triple, const clang::TargetOptions &Opts);
} // namespace targets

} // end namespace clang

#endif
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/arm_mve.td
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,8 @@ let params = T.Float in {
defm: compare<"ne", fcmp_ne>;
defm: compare<"gt", fcmp_gt>;
defm: compare<"ge", fcmp_ge>;
defm: compare<"lt", fcmp_lt>;
defm: compare<"le", fcmp_le>;
defm: compare<"lt", fcmp_ult>;
defm: compare<"le", fcmp_ule>;
}

let params = T.Signed in {
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/arm_mve_defs.td
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ def fcmp_eq: IRBuilder<"CreateFCmpOEQ">;
def fcmp_ne: IRBuilder<"CreateFCmpUNE">; // not O: it must return true on NaNs
def fcmp_gt: IRBuilder<"CreateFCmpOGT">;
def fcmp_ge: IRBuilder<"CreateFCmpOGE">;
def fcmp_lt: IRBuilder<"CreateFCmpOLT">;
def fcmp_le: IRBuilder<"CreateFCmpOLE">;
def fcmp_ult: IRBuilder<"CreateFCmpULT">;
def fcmp_ule: IRBuilder<"CreateFCmpULE">;
def splat: CGHelperFn<"ARMMVEVectorSplat">;
def select: IRBuilder<"CreateSelect">;
def fneg: IRBuilder<"CreateFNeg">;
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/arm_neon.td
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def OP_BFMLALT_LN

def OP_VCVT_F32_BF16
: Op<(bitcast "R",
(call "vshll_n", (bitcast "int16x4_t", $p0),
(call "vshll_n", (bitcast "uint16x4_t", $p0),
(literal "int32_t", "16")))>;
def OP_VCVT_F32_BF16_LO
: Op<(call "vcvt_f32_bf16", (call "vget_low", $p0))>;
Expand All @@ -275,8 +275,8 @@ def OP_VCVT_BF16_F32_HI_A32
(call "vget_low", $p0))>;

def OP_CVT_F32_BF16
: Op<(bitcast "R", (op "<<", (cast "int32_t", (bitcast "int16_t", $p0)),
(literal "int32_t", "16")))>;
: Op<(bitcast "R", (op "<<", (cast "uint32_t", (bitcast "uint16_t", $p0)),
(literal "uint32_t", "16")))>;

//===----------------------------------------------------------------------===//
// Auxiliary Instructions
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/arm_neon_incl.td
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ def OP_UNAVAILABLE : Operation {
// h: half-float
// d: double
// b: bfloat16
// m: mfloat8
//
// Typespec modifiers
// ------------------
Expand Down
11 changes: 6 additions & 5 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -1732,8 +1732,6 @@ defm gnu_inline_asm : BoolFOption<"gnu-inline-asm",
"Disable GNU style inline asm">,
PosFlag<SetTrue>>;

def fprofile_sample_use : Flag<["-"], "fprofile-sample-use">, Group<f_Group>,
Visibility<[ClangOption, CLOption]>;
def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group<f_Group>,
Visibility<[ClangOption, CLOption]>;
def fprofile_sample_use_EQ : Joined<["-"], "fprofile-sample-use=">,
Expand All @@ -1759,8 +1757,6 @@ def fsample_profile_use_profi : Flag<["-"], "fsample-profile-use-profi">,
basic block counts to branch probabilites to fix them by extended
and re-engineered classic MCMF (min-cost max-flow) approach.}]>;
def fno_profile_sample_accurate : Flag<["-"], "fno-profile-sample-accurate">, Group<f_Group>;
def fauto_profile : Flag<["-"], "fauto-profile">, Group<f_Group>,
Alias<fprofile_sample_use>;
def fno_auto_profile : Flag<["-"], "fno-auto-profile">, Group<f_Group>,
Alias<fno_profile_sample_use>;
def fauto_profile_EQ : Joined<["-"], "fauto-profile=">,
Expand Down Expand Up @@ -4356,6 +4352,7 @@ defm ptrauth_indirect_gotos : OptInCC1FFlag<"ptrauth-indirect-gotos",
defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">;
defm ptrauth_init_fini_address_discrimination : OptInCC1FFlag<"ptrauth-init-fini-address-discrimination",
"Enable address discrimination of function pointers in init/fini arrays">;
defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Expand Down Expand Up @@ -4408,7 +4405,7 @@ def fcoverage_prefix_map_EQ
HelpText<"remap file source paths <old> to <new> in coverage mapping. If there are multiple options, prefix replacement is applied in reverse order starting from the last one">;
def ffile_prefix_map_EQ
: Joined<["-"], "ffile-prefix-map=">, Group<f_Group>,
HelpText<"remap file source paths in debug info, predefined preprocessor "
HelpText<"remap file source paths in debug info, coverage mapping, predefined preprocessor "
"macros and __builtin_FILE(). Implies -ffile-reproducible.">;
def fmacro_prefix_map_EQ
: Joined<["-"], "fmacro-prefix-map=">, Group<f_Group>,
Expand Down Expand Up @@ -5416,6 +5413,10 @@ def mlam_bh : Flag<["-"], "mlam-bh">, Group<m_loongarch_Features_Group>,
HelpText<"Enable amswap[_db].{b/h} and amadd[_db].{b/h}">;
def mno_lam_bh : Flag<["-"], "mno-lam-bh">, Group<m_loongarch_Features_Group>,
HelpText<"Disable amswap[_db].{b/h} and amadd[_db].{b/h}">;
def mld_seq_sa : Flag<["-"], "mld-seq-sa">, Group<m_loongarch_Features_Group>,
HelpText<"Do not generate load-load barrier instructions (dbar 0x700)">;
def mno_ld_seq_sa : Flag<["-"], "mno-ld-seq-sa">, Group<m_loongarch_Features_Group>,
HelpText<"Generate load-load barrier instructions (dbar 0x700)">;
def mannotate_tablejump : Flag<["-"], "mannotate-tablejump">, Group<m_loongarch_Features_Group>,
HelpText<"Enable annotate table jump instruction to correlate it with the jump table.">;
def mno_annotate_tablejump : Flag<["-"], "mno-annotate-tablejump">, Group<m_loongarch_Features_Group>,
Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/Frontend/CompilerInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -675,13 +675,17 @@ class CompilerInstance : public ModuleLoader {
/// Note that this routine also replaces the diagnostic client,
/// allocating one if one is not provided.
///
/// \param VFS is used for any IO needed when creating DiagnosticsEngine. It
/// doesn't replace VFS in the CompilerInstance (if any).
///
/// \param Client If non-NULL, a diagnostic client that will be
/// attached to (and, then, owned by) the DiagnosticsEngine inside this AST
/// unit.
///
/// \param ShouldOwnClient If Client is non-NULL, specifies whether
/// the diagnostic object should take ownership of the client.
void createDiagnostics(DiagnosticConsumer *Client = nullptr,
void createDiagnostics(llvm::vfs::FileSystem &VFS,
DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true);

/// Create a DiagnosticsEngine object with a the TextDiagnosticPrinter.
Expand All @@ -702,10 +706,11 @@ class CompilerInstance : public ModuleLoader {
/// used by some diagnostics printers (for logging purposes only).
///
/// \return The new object on success, or null on failure.
static IntrusiveRefCntPtr<DiagnosticsEngine> createDiagnostics(
DiagnosticOptions *Opts, DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true, const CodeGenOptions *CodeGenOpts = nullptr,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS = nullptr);
static IntrusiveRefCntPtr<DiagnosticsEngine>
createDiagnostics(llvm::vfs::FileSystem &VFS, DiagnosticOptions *Opts,
DiagnosticConsumer *Client = nullptr,
bool ShouldOwnClient = true,
const CodeGenOptions *CodeGenOpts = nullptr);

/// Create the file manager and replace any existing one with it.
///
Expand Down
8 changes: 7 additions & 1 deletion clang/include/clang/Frontend/FrontendAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -185,7 +186,12 @@ class FrontendAction {
virtual bool usesPreprocessorOnly() const = 0;

/// For AST-based actions, the kind of translation unit we're handling.
virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
virtual TranslationUnitKind getTranslationUnitKind() {
// The ASTContext, if exists, knows the exact TUKind of the frondend.
if (Instance && Instance->hasASTContext())
return Instance->getASTContext().TUKind;
return TU_Complete;
}

/// Does this action support use with PCH?
virtual bool hasPCHSupport() const { return true; }
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ class Interpreter {

CodeGenerator *getCodeGen() const;
std::unique_ptr<llvm::Module> GenModule();
PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU);
PartialTranslationUnit &RegisterPTU(TranslationUnitDecl *TU,
std::unique_ptr<llvm::Module> M = {});

// A cache for the compiled destructors used to for de-allocation of managed
// clang::Values.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Interpreter/PartialTranslationUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ struct PartialTranslationUnit {

/// The llvm IR produced for the input.
std::unique_ptr<llvm::Module> TheModule;
bool operator==(const PartialTranslationUnit &other) {
return other.TUPart == TUPart && other.TheModule == TheModule;
}
};
} // namespace clang

Expand Down
14 changes: 0 additions & 14 deletions clang/include/clang/Parse/ParseDiagnostic.h

This file was deleted.

3 changes: 2 additions & 1 deletion clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1934,7 +1934,8 @@ class Parser : public CodeCompletionHandler {
llvm::function_ref<void()> ExpressionStarts =
llvm::function_ref<void()>(),
bool FailImmediatelyOnInvalidExpr = false,
bool EarlyTypoCorrection = false);
bool EarlyTypoCorrection = false,
bool *HasTrailingComma = nullptr);

/// ParseSimpleExpressionList - A simple comma-separated list of expressions,
/// used for misc language extensions.
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Parse/RAIIObjectsForParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#ifndef LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H
#define LLVM_CLANG_PARSE_RAIIOBJECTSFORPARSER_H

#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Basic/DiagnosticParse.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/ParsedTemplate.h"
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -2323,6 +2323,9 @@ class Sema final : public SemaBase {
bool BuiltinVectorMath(CallExpr *TheCall, QualType &Res, bool FPOnly = false);
bool BuiltinVectorToScalarMath(CallExpr *TheCall);

void checkLifetimeCaptureBy(FunctionDecl *FDecl, bool IsMemberFunction,
const Expr *ThisArg, ArrayRef<const Expr *> Args);

/// Handles the checks for format strings, non-POD arguments to vararg
/// functions, NULL arguments passed to non-NULL parameters, diagnose_if
/// attributes and AArch64 SME attributes.
Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
const unsigned VERSION_MAJOR = 33;
const unsigned VERSION_MAJOR = 34;

/// AST file minor version number supported by this version of
/// Clang.
Expand Down Expand Up @@ -350,9 +350,8 @@ enum ControlRecordTypes {
/// and information about the compiler used to build this AST file.
METADATA = 1,

/// Record code for the list of other AST files imported by
/// this AST file.
IMPORTS,
/// Record code for another AST file imported by this AST file.
IMPORT,

/// Record code for the original file that was used to
/// generate the AST file, including both its file ID and its
Expand Down
14 changes: 4 additions & 10 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -2389,23 +2389,17 @@ class ASTReader

// Read a string
static std::string ReadString(const RecordDataImpl &Record, unsigned &Idx);

// Skip a string
static void SkipString(const RecordData &Record, unsigned &Idx) {
Idx += Record[Idx] + 1;
}
static StringRef ReadStringBlob(const RecordDataImpl &Record, unsigned &Idx,
StringRef &Blob);

// Read a path
std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx);

// Read a path
std::string ReadPath(StringRef BaseDirectory, const RecordData &Record,
unsigned &Idx);

// Skip a path
static void SkipPath(const RecordData &Record, unsigned &Idx) {
SkipString(Record, Idx);
}
std::string ReadPathBlob(StringRef BaseDirectory, const RecordData &Record,
unsigned &Idx, StringRef &Blob);

/// Read a version tuple.
static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx);
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,13 +769,17 @@ class ASTWriter : public ASTDeserializationListener,

/// Add a string to the given record.
void AddString(StringRef Str, RecordDataImpl &Record);
void AddStringBlob(StringRef Str, RecordDataImpl &Record,
SmallVectorImpl<char> &Blob);

/// Convert a path from this build process into one that is appropriate
/// for emission in the module file.
bool PreparePathForOutput(SmallVectorImpl<char> &Path);

/// Add a path to the given record.
void AddPath(StringRef Path, RecordDataImpl &Record);
void AddPathBlob(StringRef Str, RecordDataImpl &Record,
SmallVectorImpl<char> &Blob);

/// Emit the current record with the given path as a blob.
void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
Expand Down
1 change: 0 additions & 1 deletion clang/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ module Clang_Diagnostics {
module Frontend { header "clang/Frontend/FrontendDiagnostic.h" export * }
module Lex { header "clang/Lex/LexDiagnostic.h" export * }
module Parse { header "clang/Parse/ParseDiagnostic.h" export * }
module Sema { header "clang/Sema/SemaDiagnostic.h" export * }
module Serialization { header "clang/Serialization/SerializationDiagnostic.h" export * }
module Refactoring { header "clang/Tooling/Refactoring/RefactoringDiagnostic.h" export * }
}
Expand Down
15 changes: 11 additions & 4 deletions clang/lib/AST/ByteCode/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1370,9 +1370,15 @@ bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func,
S.Current = NewFrame.get();

if (InterpretBuiltin(S, OpPC, Func, CE, BuiltinID)) {
NewFrame.release();
// Release ownership of NewFrame to prevent it from being deleted.
NewFrame.release(); // Frame was deleted already.
// Ensure that S.Current is correctly reset to the previous frame.
assert(S.Current == FrameBefore);
return true;
}

// Interpreting the function failed somehow. Reset to
// previous state.
S.Current = FrameBefore;
return false;
}
Expand Down Expand Up @@ -1475,11 +1481,12 @@ bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,

bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E) {
assert(E);
const auto &Loc = S.Current->getSource(OpPC);

if (S.getLangOpts().CPlusPlus26)
return true;

const auto &Loc = S.Current->getSource(OpPC);

if (const auto *NewExpr = dyn_cast<CXXNewExpr>(E)) {
const FunctionDecl *OperatorNew = NewExpr->getOperatorNew();

Expand Down Expand Up @@ -1588,7 +1595,7 @@ bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
}

// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", off)
#endif
bool Interpret(InterpState &S, APValue &Result) {
Expand Down Expand Up @@ -1616,7 +1623,7 @@ bool Interpret(InterpState &S, APValue &Result) {
}
}
// https://github.com/llvm/llvm-project/issues/102513
#if defined(_WIN32) && !defined(__clang__) && !defined(NDEBUG)
#if defined(_MSC_VER) && !defined(__clang__) && !defined(NDEBUG)
#pragma optimize("", on)
#endif

Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3084,6 +3084,9 @@ inline bool BitCastPtr(InterpState &S, CodePtr OpPC) {
const Pointer &FromPtr = S.Stk.pop<Pointer>();
Pointer &ToPtr = S.Stk.peek<Pointer>();

if (!CheckLoad(S, OpPC, FromPtr))
return false;

if (!DoBitCastPtr(S, OpPC, FromPtr, ToPtr))
return false;

Expand Down
7 changes: 3 additions & 4 deletions clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ static bool CheckBitcastType(InterpState &S, CodePtr OpPC, QualType T,
};
auto note = [&](int Construct, QualType NoteType, SourceRange NoteRange) {
S.Note(NoteRange.getBegin(), diag::note_constexpr_bit_cast_invalid_subtype)
<< NoteType << Construct << T << NoteRange;
<< NoteType << Construct << T.getUnqualifiedType() << NoteRange;
return false;
};

Expand Down Expand Up @@ -388,11 +388,10 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
QualType FromType = FromPtr.getType();
QualType ToType = ToPtr.getType();

if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false))
return false;

if (!CheckBitcastType(S, OpPC, ToType, /*IsToType=*/true))
return false;
if (!CheckBitcastType(S, OpPC, FromType, /*IsToType=*/false))
return false;

BitcastBuffer Buffer;
readPointerToBuffer(S.getContext(), FromPtr, Buffer,
Expand Down
18 changes: 10 additions & 8 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1615,22 +1615,24 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
return FnType->getReturnType();
}

const Attr *CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
std::pair<const NamedDecl *, const Attr *>
CallExpr::getUnusedResultAttr(const ASTContext &Ctx) const {
// If the callee is marked nodiscard, return that attribute
const Decl *D = getCalleeDecl();
if (const auto *A = D->getAttr<WarnUnusedResultAttr>())
return {nullptr, A};

// If the return type is a struct, union, or enum that is marked nodiscard,
// then return the return type attribute.
if (const TagDecl *TD = getCallReturnType(Ctx)->getAsTagDecl())
if (const auto *A = TD->getAttr<WarnUnusedResultAttr>())
return A;
return {TD, A};

for (const auto *TD = getCallReturnType(Ctx)->getAs<TypedefType>(); TD;
TD = TD->desugar()->getAs<TypedefType>())
if (const auto *A = TD->getDecl()->getAttr<WarnUnusedResultAttr>())
return A;

// Otherwise, see if the callee is marked nodiscard and return that attribute
// instead.
const Decl *D = getCalleeDecl();
return D ? D->getAttr<WarnUnusedResultAttr>() : nullptr;
return {TD->getDecl(), A};
return {nullptr, nullptr};
}

SourceLocation CallExpr::getBeginLoc() const {
Expand Down
44 changes: 37 additions & 7 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3261,8 +3261,8 @@ static bool HandleLValueDirectBase(EvalInfo &Info, const Expr *E, LValue &Obj,
RL = &Info.Ctx.getASTRecordLayout(Derived);
}

Obj.getLValueOffset() += RL->getBaseClassOffset(Base);
Obj.addDecl(Info, E, Base, /*Virtual*/ false);
Obj.getLValueOffset() += RL->getBaseClassOffset(Base);
return true;
}

Expand All @@ -3286,8 +3286,8 @@ static bool HandleLValueBase(EvalInfo &Info, const Expr *E, LValue &Obj,
// Find the virtual base class.
if (DerivedDecl->isInvalidDecl()) return false;
const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(DerivedDecl);
Obj.getLValueOffset() += Layout.getVBaseClassOffset(BaseDecl);
Obj.addDecl(Info, E, BaseDecl, /*Virtual*/ true);
Obj.getLValueOffset() += Layout.getVBaseClassOffset(BaseDecl);
return true;
}

Expand Down Expand Up @@ -3330,8 +3330,8 @@ static bool HandleLValueMember(EvalInfo &Info, const Expr *E, LValue &LVal,
}

unsigned I = FD->getFieldIndex();
LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)));
LVal.addDecl(Info, E, FD);
LVal.adjustOffset(Info.Ctx.toCharUnitsFromBits(RL->getFieldOffset(I)));
return true;
}

Expand Down Expand Up @@ -13527,18 +13527,48 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(DidOverflow, E);
}

case Builtin::BI__builtin_reduce_add: {
case Builtin::BI__builtin_reduce_add:
case Builtin::BI__builtin_reduce_mul:
case Builtin::BI__builtin_reduce_and:
case Builtin::BI__builtin_reduce_or:
case Builtin::BI__builtin_reduce_xor: {
APValue Source;
if (!EvaluateAsRValue(Info, E->getArg(0), Source))
return false;

unsigned SourceLen = Source.getVectorLength();
APSInt Reduced = Source.getVectorElt(0).getInt();
for (unsigned EltNum = 1; EltNum < SourceLen; ++EltNum) {
if (!CheckedIntArithmetic(
Info, E, Reduced, Source.getVectorElt(EltNum).getInt(),
Reduced.getBitWidth() + 1, std::plus<APSInt>(), Reduced))
switch (BuiltinOp) {
default:
return false;
case Builtin::BI__builtin_reduce_add: {
if (!CheckedIntArithmetic(
Info, E, Reduced, Source.getVectorElt(EltNum).getInt(),
Reduced.getBitWidth() + 1, std::plus<APSInt>(), Reduced))
return false;
break;
}
case Builtin::BI__builtin_reduce_mul: {
if (!CheckedIntArithmetic(
Info, E, Reduced, Source.getVectorElt(EltNum).getInt(),
Reduced.getBitWidth() * 2, std::multiplies<APSInt>(), Reduced))
return false;
break;
}
case Builtin::BI__builtin_reduce_and: {
Reduced &= Source.getVectorElt(EltNum).getInt();
break;
}
case Builtin::BI__builtin_reduce_or: {
Reduced |= Source.getVectorElt(EltNum).getInt();
break;
}
case Builtin::BI__builtin_reduce_xor: {
Reduced ^= Source.getVectorElt(EltNum).getInt();
break;
}
}
}

return Success(Reduced, E);
Expand Down
31 changes: 19 additions & 12 deletions clang/lib/Analysis/CFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,7 @@ class CFGBuilder {
void cleanupConstructionContext(Expr *E);

void autoCreateBlock() { if (!Block) Block = createBlock(); }

CFGBlock *createBlock(bool add_successor = true);
CFGBlock *createNoReturnBlock();

Expand Down Expand Up @@ -818,15 +819,21 @@ class CFGBuilder {
B->appendStmt(const_cast<Stmt*>(S), cfg->getBumpVectorContext());
}

void appendConstructor(CFGBlock *B, CXXConstructExpr *CE) {
void appendConstructor(CXXConstructExpr *CE) {
CXXConstructorDecl *C = CE->getConstructor();
if (C && C->isNoReturn())
Block = createNoReturnBlock();
else
autoCreateBlock();

if (const ConstructionContext *CC =
retrieveAndCleanupConstructionContext(CE)) {
B->appendConstructor(CE, CC, cfg->getBumpVectorContext());
Block->appendConstructor(CE, CC, cfg->getBumpVectorContext());
return;
}

// No valid construction context found. Fall back to statement.
B->appendStmt(CE, cfg->getBumpVectorContext());
Block->appendStmt(CE, cfg->getBumpVectorContext());
}

void appendCall(CFGBlock *B, CallExpr *CE) {
Expand Down Expand Up @@ -3177,11 +3184,14 @@ CFGBlock *CFGBuilder::VisitIfStmt(IfStmt *I) {
if (!I->isConsteval())
KnownVal = tryEvaluateBool(I->getCond());

// Add the successors. If we know that specific branches are
// Add the successors. If we know that specific branches are
// unreachable, inform addSuccessor() of that knowledge.
addSuccessor(Block, ThenBlock, /* IsReachable = */ !KnownVal.isFalse());
addSuccessor(Block, ElseBlock, /* IsReachable = */ !KnownVal.isTrue());

if (I->isConsteval())
return Block;

// Add the condition as the last statement in the new block. This may
// create new blocks as the condition may contain control-flow. Any newly
// created blocks will be pointed to be "Block".
Expand Down Expand Up @@ -4829,9 +4839,7 @@ CFGBlock *CFGBuilder::VisitCXXConstructExpr(CXXConstructExpr *C,
// construct these objects. Construction contexts we find here aren't for the
// constructor C, they're for its arguments only.
findConstructionContextsForArguments(C);

autoCreateBlock();
appendConstructor(Block, C);
appendConstructor(C);

return VisitChildren(C);
}
Expand Down Expand Up @@ -4889,16 +4897,15 @@ CFGBlock *CFGBuilder::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *E,
return Visit(E->getSubExpr(), asc);
}

CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *C,
CFGBlock *CFGBuilder::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E,
AddStmtChoice asc) {
// If the constructor takes objects as arguments by value, we need to properly
// construct these objects. Construction contexts we find here aren't for the
// constructor C, they're for its arguments only.
findConstructionContextsForArguments(C);
findConstructionContextsForArguments(E);
appendConstructor(E);

autoCreateBlock();
appendConstructor(Block, C);
return VisitChildren(C);
return VisitChildren(E);
}

CFGBlock *CFGBuilder::VisitImplicitCastExpr(ImplicitCastExpr *E,
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ static const OffloadArchToStringMap arch_names[] = {
GFX(940), // gfx940
GFX(941), // gfx941
GFX(942), // gfx942
GFX(950), // gfx950
{OffloadArch::GFX10_1_GENERIC, "gfx10-1-generic", "compute_amdgcn"},
GFX(1010), // gfx1010
GFX(1011), // gfx1011
Expand Down
Loading