143 changes: 79 additions & 64 deletions bolt/lib/Profile/BoltAddressTranslation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

#include "bolt/Profile/BoltAddressTranslation.h"
#include "bolt/Core/BinaryFunction.h"
#include "llvm/Support/DataExtractor.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/LEB128.h"

#define DEBUG_TYPE "bolt-bat"

Expand Down Expand Up @@ -44,7 +45,7 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map,
// and this deleted block will both share the same output address (the same
// key), and we need to map back. We choose here to privilege the successor by
// allowing it to overwrite the previously inserted key in the map.
Map[BBOutputOffset] = BBInputOffset;
Map[BBOutputOffset] = BBInputOffset << 1;

const auto &IOAddressMap =
BB.getFunction()->getBinaryContext().getIOAddressMap();
Expand All @@ -61,8 +62,8 @@ void BoltAddressTranslation::writeEntriesForBB(MapTy &Map,

LLVM_DEBUG(dbgs() << " Key: " << Twine::utohexstr(OutputOffset) << " Val: "
<< Twine::utohexstr(InputOffset) << " (branch)\n");
Map.insert(
std::pair<uint32_t, uint32_t>(OutputOffset, InputOffset | BRANCHENTRY));
Map.insert(std::pair<uint32_t, uint32_t>(OutputOffset,
(InputOffset << 1) | BRANCHENTRY));
}
}

Expand Down Expand Up @@ -101,36 +102,51 @@ void BoltAddressTranslation::write(const BinaryContext &BC, raw_ostream &OS) {
}
}

const uint32_t NumFuncs = Maps.size();
OS.write(reinterpret_cast<const char *>(&NumFuncs), 4);
LLVM_DEBUG(dbgs() << "Writing " << NumFuncs << " functions for BAT.\n");
writeMaps</*Cold=*/false>(Maps, OS);
writeMaps</*Cold=*/true>(Maps, OS);

outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n";
}

template <bool Cold>
void BoltAddressTranslation::writeMaps(std::map<uint64_t, MapTy> &Maps,
raw_ostream &OS) {
const uint32_t NumFuncs =
llvm::count_if(llvm::make_first_range(Maps), [&](const uint64_t Address) {
return Cold == ColdPartSource.count(Address);
});
encodeULEB128(NumFuncs, OS);
LLVM_DEBUG(dbgs() << "Writing " << NumFuncs << (Cold ? " cold" : "")
<< " functions for BAT.\n");
size_t PrevIndex = 0;
// Output addresses are delta-encoded
uint64_t PrevAddress = 0;
for (auto &MapEntry : Maps) {
const uint64_t Address = MapEntry.first;
// Only process cold fragments in cold mode, and vice versa.
if (Cold != ColdPartSource.count(Address))
continue;
MapTy &Map = MapEntry.second;
const uint32_t NumEntries = Map.size();
LLVM_DEBUG(dbgs() << "Writing " << NumEntries << " entries for 0x"
<< Twine::utohexstr(Address) << ".\n");
OS.write(reinterpret_cast<const char *>(&Address), 8);
OS.write(reinterpret_cast<const char *>(&NumEntries), 4);
encodeULEB128(Address - PrevAddress, OS);
PrevAddress = Address;
if (Cold) {
size_t HotIndex =
std::distance(ColdPartSource.begin(), ColdPartSource.find(Address));
encodeULEB128(HotIndex - PrevIndex, OS);
PrevIndex = HotIndex;
}
encodeULEB128(NumEntries, OS);
uint64_t InOffset = 0, OutOffset = 0;
// Output and Input addresses and delta-encoded
for (std::pair<const uint32_t, uint32_t> &KeyVal : Map) {
OS.write(reinterpret_cast<const char *>(&KeyVal.first), 4);
OS.write(reinterpret_cast<const char *>(&KeyVal.second), 4);
encodeULEB128(KeyVal.first - OutOffset, OS);
encodeSLEB128(KeyVal.second - InOffset, OS);
std::tie(OutOffset, InOffset) = KeyVal;
}
}
const uint32_t NumColdEntries = ColdPartSource.size();
LLVM_DEBUG(dbgs() << "Writing " << NumColdEntries
<< " cold part mappings.\n");
OS.write(reinterpret_cast<const char *>(&NumColdEntries), 4);
for (std::pair<const uint64_t, uint64_t> &ColdEntry : ColdPartSource) {
OS.write(reinterpret_cast<const char *>(&ColdEntry.first), 8);
OS.write(reinterpret_cast<const char *>(&ColdEntry.second), 8);
LLVM_DEBUG(dbgs() << " " << Twine::utohexstr(ColdEntry.first) << " -> "
<< Twine::utohexstr(ColdEntry.second) << "\n");
}

outs() << "BOLT-INFO: Wrote " << Maps.size() << " BAT maps\n";
outs() << "BOLT-INFO: Wrote " << NumColdEntries
<< " BAT cold-to-hot entries\n";
}

std::error_code BoltAddressTranslation::parse(StringRef Buf) {
Expand All @@ -152,53 +168,52 @@ std::error_code BoltAddressTranslation::parse(StringRef Buf) {
if (Name.substr(0, 4) != "BOLT")
return make_error_code(llvm::errc::io_error);

if (Buf.size() - Offset < 4)
return make_error_code(llvm::errc::io_error);
Error Err(Error::success());
std::vector<uint64_t> HotFuncs;
parseMaps</*Cold=*/false>(HotFuncs, DE, Offset, Err);
parseMaps</*Cold=*/true>(HotFuncs, DE, Offset, Err);
outs() << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n";
return errorToErrorCode(std::move(Err));
}

const uint32_t NumFunctions = DE.getU32(&Offset);
LLVM_DEBUG(dbgs() << "Parsing " << NumFunctions << " functions\n");
template <bool Cold>
void BoltAddressTranslation::parseMaps(std::vector<uint64_t> &HotFuncs,
DataExtractor &DE, uint64_t &Offset,
Error &Err) {
const uint32_t NumFunctions = DE.getULEB128(&Offset, &Err);
LLVM_DEBUG(dbgs() << "Parsing " << NumFunctions << (Cold ? " cold" : "")
<< " functions\n");
size_t HotIndex = 0;
uint64_t PrevAddress = 0;
for (uint32_t I = 0; I < NumFunctions; ++I) {
if (Buf.size() - Offset < 12)
return make_error_code(llvm::errc::io_error);

const uint64_t Address = DE.getU64(&Offset);
const uint32_t NumEntries = DE.getU32(&Offset);
const uint64_t Address = PrevAddress + DE.getULEB128(&Offset, &Err);
PrevAddress = Address;
if (Cold) {
HotIndex += DE.getULEB128(&Offset, &Err);
ColdPartSource.emplace(Address, HotFuncs[HotIndex]);
} else {
HotFuncs.push_back(Address);
}
const uint32_t NumEntries = DE.getULEB128(&Offset, &Err);
MapTy Map;

LLVM_DEBUG(dbgs() << "Parsing " << NumEntries << " entries for 0x"
<< Twine::utohexstr(Address) << "\n");
if (Buf.size() - Offset < 8 * NumEntries)
return make_error_code(llvm::errc::io_error);
uint64_t InputOffset = 0, OutputOffset = 0;
for (uint32_t J = 0; J < NumEntries; ++J) {
const uint32_t OutputAddr = DE.getU32(&Offset);
const uint32_t InputAddr = DE.getU32(&Offset);
Map.insert(std::pair<uint32_t, uint32_t>(OutputAddr, InputAddr));
LLVM_DEBUG(dbgs() << Twine::utohexstr(OutputAddr) << " -> "
<< Twine::utohexstr(InputAddr) << "\n");
const uint64_t OutputDelta = DE.getULEB128(&Offset, &Err);
const int64_t InputDelta = DE.getSLEB128(&Offset, &Err);
OutputOffset += OutputDelta;
InputOffset += InputDelta;
Map.insert(std::pair<uint32_t, uint32_t>(OutputOffset, InputOffset));
LLVM_DEBUG(dbgs() << formatv("{0:x} -> {1:x} ({2}/{3}b -> {4}/{5}b)\n",
OutputOffset, InputOffset, OutputDelta,
encodeULEB128(OutputDelta, nulls()),
InputDelta,
encodeSLEB128(InputDelta, nulls())));
}
Maps.insert(std::pair<uint64_t, MapTy>(Address, Map));
}

if (Buf.size() - Offset < 4)
return make_error_code(llvm::errc::io_error);

const uint32_t NumColdEntries = DE.getU32(&Offset);
LLVM_DEBUG(dbgs() << "Parsing " << NumColdEntries << " cold part mappings\n");
for (uint32_t I = 0; I < NumColdEntries; ++I) {
if (Buf.size() - Offset < 16)
return make_error_code(llvm::errc::io_error);
const uint32_t ColdAddress = DE.getU64(&Offset);
const uint32_t HotAddress = DE.getU64(&Offset);
ColdPartSource.insert(
std::pair<uint64_t, uint64_t>(ColdAddress, HotAddress));
LLVM_DEBUG(dbgs() << Twine::utohexstr(ColdAddress) << " -> "
<< Twine::utohexstr(HotAddress) << "\n");
}
outs() << "BOLT-INFO: Parsed " << Maps.size() << " BAT entries\n";
outs() << "BOLT-INFO: Parsed " << NumColdEntries
<< " BAT cold-to-hot entries\n";

return std::error_code();
}

void BoltAddressTranslation::dump(raw_ostream &OS) {
Expand All @@ -209,7 +224,7 @@ void BoltAddressTranslation::dump(raw_ostream &OS) {
OS << "BB mappings:\n";
for (const auto &Entry : MapEntry.second) {
const bool IsBranch = Entry.second & BRANCHENTRY;
const uint32_t Val = Entry.second & ~BRANCHENTRY;
const uint32_t Val = Entry.second >> 1; // dropping BRANCHENTRY bit
OS << "0x" << Twine::utohexstr(Entry.first) << " -> "
<< "0x" << Twine::utohexstr(Val);
if (IsBranch)
Expand Down Expand Up @@ -244,7 +259,7 @@ uint64_t BoltAddressTranslation::translate(uint64_t FuncAddress,

--KeyVal;

const uint32_t Val = KeyVal->second & ~BRANCHENTRY;
const uint32_t Val = KeyVal->second >> 1; // dropping BRANCHENTRY bit
// Branch source addresses are translated to the first instruction of the
// source BB to avoid accounting for modifications BOLT may have made in the
// BB regarding deletion/addition of instructions.
Expand Down
1 change: 1 addition & 0 deletions bolt/lib/Rewrite/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set(LLVM_LINK_COMPONENTS
Object
Support
DWARFLinker
DWARFLinkerClassic
AsmPrinter
TargetParser
)
Expand Down
11 changes: 7 additions & 4 deletions bolt/lib/Rewrite/DWARFRewriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/DWARFLinker/DWARFStreamer.h"
#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
Expand Down Expand Up @@ -178,6 +178,9 @@ translateInputToOutputLocationList(const BinaryFunction &BF,
return MergedLL;
}

using namespace dwarf_linker;
using namespace dwarf_linker::classic;

namespace llvm {
namespace bolt {
/// Emits debug information into .debug_info or .debug_types section.
Expand Down Expand Up @@ -278,10 +281,10 @@ class DIEStreamer : public DwarfStreamer {

public:
DIEStreamer(DIEBuilder *DIEBldr, DWARFRewriter &Rewriter,
DWARFLinker::OutputFileType OutFileType,
DWARFLinkerBase::OutputFileType OutFileType,
raw_pwrite_stream &OutFile,
std::function<StringRef(StringRef Input)> Translator,
DWARFLinker::messageHandler Warning)
DWARFLinkerBase::MessageHandlerTy Warning)
: DwarfStreamer(OutFileType, OutFile, Translator, Warning),
DIEBldr(DIEBldr), Rewriter(Rewriter){};

Expand Down Expand Up @@ -457,7 +460,7 @@ createDIEStreamer(const Triple &TheTriple, raw_pwrite_stream &OutFile,
DWARFRewriter &Rewriter) {

std::unique_ptr<DIEStreamer> Streamer = std::make_unique<DIEStreamer>(
&DIEBldr, Rewriter, llvm::DWARFLinker::OutputFileType::Object, OutFile,
&DIEBldr, Rewriter, DWARFLinkerBase::OutputFileType::Object, OutFile,
[](StringRef Input) -> StringRef { return Input; },
[&](const Twine &Warning, StringRef Context, const DWARFDie *) {});
Error Err = Streamer->init(TheTriple, Swift5ReflectionSegmentName);
Expand Down
1 change: 1 addition & 0 deletions bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4112,6 +4112,7 @@ void RewriteInstance::encodeBATSection() {
copyByteArray(BoltInfo), BoltInfo.size(),
/*Alignment=*/1,
/*IsReadOnly=*/true, ELF::SHT_NOTE);
outs() << "BOLT-INFO: BAT section size (bytes): " << BoltInfo.size() << '\n';
}

template <typename ELFShdrTy>
Expand Down
2 changes: 1 addition & 1 deletion bolt/test/RISCV/relax.s
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

// CHECK: Binary Function "_start" after building cfg {
// CHECK: jal ra, near_f
// CHECK-NEXT: auipc ra, far_f@plt
// CHECK-NEXT: auipc ra, far_f
// CHECK-NEXT: jalr ra, 0xc(ra)
// CHECK-NEXT: j near_f

Expand Down
2 changes: 1 addition & 1 deletion bolt/test/X86/bolt-address-translation.test
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#
# CHECK: BOLT: 3 out of 7 functions were overwritten.
# CHECK: BOLT-INFO: Wrote 6 BAT maps
# CHECK: BOLT-INFO: Wrote 3 BAT cold-to-hot entries
# CHECK: BOLT-INFO: BAT section size (bytes): 404
#
# usqrt mappings (hot part). We match against any key (left side containing
# the bolted binary offsets) because BOLT may change where it puts instructions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
;;; clang-include-fixer.el --- Emacs integration of the clang include fixer -*- lexical-binding: t; -*-

;; Version: 0.1.0
;; Keywords: tools, c
;; Package-Requires: ((cl-lib "0.5") (json "1.2") (let-alist "1.0.4"))

Expand Down
9 changes: 3 additions & 6 deletions clang-tools-extra/clang-query/QueryParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@ namespace query {
// is found before End, return StringRef(). Begin is adjusted to exclude the
// lexed region.
StringRef QueryParser::lexWord() {
Line = Line.drop_while([](char c) {
// Don't trim newlines.
return StringRef(" \t\v\f\r").contains(c);
});
// Don't trim newlines.
Line = Line.ltrim(" \t\v\f\r");

if (Line.empty())
// Even though the Line is empty, it contains a pointer and
Expand Down Expand Up @@ -152,8 +150,7 @@ QueryRef QueryParser::parseSetTraversalKind(TraversalKind QuerySession::*Var) {

QueryRef QueryParser::endQuery(QueryRef Q) {
StringRef Extra = Line;
StringRef ExtraTrimmed = Extra.drop_while(
[](char c) { return StringRef(" \t\v\f\r").contains(c); });
StringRef ExtraTrimmed = Extra.ltrim(" \t\v\f\r");

if ((!ExtraTrimmed.empty() && ExtraTrimmed[0] == '\n') ||
(ExtraTrimmed.size() >= 2 && ExtraTrimmed[0] == '\r' &&
Expand Down
10 changes: 9 additions & 1 deletion clang-tools-extra/clang-tidy/misc/StaticAssertCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "StaticAssertCheck.h"
#include "../utils/Matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
Expand Down Expand Up @@ -45,13 +46,20 @@ void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
IsAlwaysFalse);
auto NonConstexprFunctionCall =
callExpr(hasDeclaration(functionDecl(unless(isConstexpr()))));
auto NonConstexprVariableReference =
declRefExpr(to(varDecl(unless(isConstexpr()))),
unless(hasAncestor(expr(matchers::hasUnevaluatedContext()))),
unless(hasAncestor(typeLoc())));

auto NonConstexprCode =
expr(anyOf(NonConstexprFunctionCall, NonConstexprVariableReference));
auto AssertCondition =
expr(
anyOf(expr(ignoringParenCasts(anyOf(
AssertExprRoot, unaryOperator(hasUnaryOperand(
ignoringParenCasts(AssertExprRoot)))))),
anything()),
unless(findAll(NonConstexprFunctionCall)))
unless(NonConstexprCode), unless(hasDescendant(NonConstexprCode)))
.bind("condition");
auto Condition =
anyOf(ignoringParenImpCasts(callExpr(
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ class UnusedUsingDeclsCheck : public ClangTidyCheck {
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
void onEndOfTranslationUnit() override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}

private:
void removeFromFoundDecls(const Decl *D);
Expand Down
12 changes: 6 additions & 6 deletions clang-tools-extra/clangd/AST.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ const TemplateTypeParmType *getFunctionPackType(const FunctionDecl *Callee) {
// Returns the template parameter pack type that this parameter was expanded
// from (if in the Args... or Args&... or Args&&... form), if this is the case,
// nullptr otherwise.
const TemplateTypeParmType *getUnderylingPackType(const ParmVarDecl *Param) {
const TemplateTypeParmType *getUnderlyingPackType(const ParmVarDecl *Param) {
const auto *PlainType = Param->getType().getTypePtr();
if (auto *RT = dyn_cast<ReferenceType>(PlainType))
PlainType = RT->getPointeeTypeAsWritten().getTypePtr();
Expand Down Expand Up @@ -793,8 +793,8 @@ class ForwardingCallVisitor
: public RecursiveASTVisitor<ForwardingCallVisitor> {
public:
ForwardingCallVisitor(ArrayRef<const ParmVarDecl *> Parameters)
: Parameters{Parameters}, PackType{getUnderylingPackType(
Parameters.front())} {}
: Parameters{Parameters},
PackType{getUnderlyingPackType(Parameters.front())} {}

bool VisitCallExpr(CallExpr *E) {
auto *Callee = getCalleeDeclOrUniqueOverload(E);
Expand Down Expand Up @@ -859,7 +859,7 @@ class ForwardingCallVisitor
if (const auto *TTPT = getFunctionPackType(Callee)) {
// In this case: Separate the parameters into head, pack and tail
auto IsExpandedPack = [&](const ParmVarDecl *P) {
return getUnderylingPackType(P) == TTPT;
return getUnderlyingPackType(P) == TTPT;
};
ForwardingInfo FI;
FI.Head = MatchingParams.take_until(IsExpandedPack);
Expand Down Expand Up @@ -964,7 +964,7 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) {
if (const auto *TTPT = getFunctionPackType(D)) {
// Split the parameters into head, pack and tail
auto IsExpandedPack = [TTPT](const ParmVarDecl *P) {
return getUnderylingPackType(P) == TTPT;
return getUnderlyingPackType(P) == TTPT;
};
ArrayRef<const ParmVarDecl *> Head = Parameters.take_until(IsExpandedPack);
ArrayRef<const ParmVarDecl *> Pack =
Expand Down Expand Up @@ -1016,7 +1016,7 @@ resolveForwardingParameters(const FunctionDecl *D, unsigned MaxDepth) {
}

bool isExpandedFromParameterPack(const ParmVarDecl *D) {
return getUnderylingPackType(D) != nullptr;
return getUnderlyingPackType(D) != nullptr;
}

} // namespace clangd
Expand Down
23 changes: 13 additions & 10 deletions clang-tools-extra/clangd/CompileCommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,26 +313,29 @@ void CommandMangler::operator()(tooling::CompileCommand &Command,

tooling::addTargetAndModeForProgramName(Cmd, Cmd.front());

// Check whether the flag exists, either as -flag or -flag=*
auto Has = [&](llvm::StringRef Flag) {
for (llvm::StringRef Arg : Cmd) {
if (Arg.consume_front(Flag) && (Arg.empty() || Arg[0] == '='))
return true;
}
return false;
// Check whether the flag exists in the command.
auto HasExact = [&](llvm::StringRef Flag) {
return llvm::any_of(Cmd, [&](llvm::StringRef Arg) { return Arg == Flag; });
};

// Check whether the flag appears in the command as a prefix.
auto HasPrefix = [&](llvm::StringRef Flag) {
return llvm::any_of(
Cmd, [&](llvm::StringRef Arg) { return Arg.starts_with(Flag); });
};

llvm::erase_if(Cmd, [](llvm::StringRef Elem) {
return Elem.starts_with("--save-temps") || Elem.starts_with("-save-temps");
});

std::vector<std::string> ToAppend;
if (ResourceDir && !Has("-resource-dir"))
if (ResourceDir && !HasExact("-resource-dir") && !HasPrefix("-resource-dir="))
ToAppend.push_back(("-resource-dir=" + *ResourceDir));

// Don't set `-isysroot` if it is already set or if `--sysroot` is set.
// `--sysroot` is a superset of the `-isysroot` argument.
if (Sysroot && !Has("-isysroot") && !Has("--sysroot")) {
if (Sysroot && !HasPrefix("-isysroot") && !HasExact("--sysroot") &&
!HasPrefix("--sysroot=")) {
ToAppend.push_back("-isysroot");
ToAppend.push_back(*Sysroot);
}
Expand All @@ -343,7 +346,7 @@ void CommandMangler::operator()(tooling::CompileCommand &Command,
}

if (!Cmd.empty()) {
bool FollowSymlink = !Has("-no-canonical-prefixes");
bool FollowSymlink = !HasExact("-no-canonical-prefixes");
Cmd.front() =
(FollowSymlink ? ResolvedDrivers : ResolvedDriversNoFollow)
.get(Cmd.front(), [&, this] {
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clangd/Selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1113,6 +1113,9 @@ const DeclContext &SelectionTree::Node::getDeclContext() const {
return *DC;
return *Current->getLexicalDeclContext();
}
if (const auto *LE = CurrentNode->ASTNode.get<LambdaExpr>())
if (CurrentNode != this)
return *LE->getCallOperator();
}
llvm_unreachable("A tree must always be rooted at TranslationUnitDecl.");
}
Expand Down
81 changes: 78 additions & 3 deletions clang-tools-extra/clangd/unittests/CompileCommandsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -370,9 +370,8 @@ TEST(ArgStripperTest, OrderDependent) {
}

TEST(PrintArgvTest, All) {
std::vector<llvm::StringRef> Args = {
"one", "two", "thr ee", "f\"o\"ur", "fi\\ve", "$"
};
std::vector<llvm::StringRef> Args = {"one", "two", "thr ee",
"f\"o\"ur", "fi\\ve", "$"};
const char *Expected = R"(one two "thr ee" "f\"o\"ur" "fi\\ve" $)";
EXPECT_EQ(Expected, printArgv(Args));
}
Expand Down Expand Up @@ -450,6 +449,82 @@ TEST(CommandMangler, PathsAsPositional) {
Mangler(Cmd, "a.cc");
EXPECT_THAT(Cmd.CommandLine, Contains("foo"));
}

TEST(CommandMangler, RespectsOriginalResourceDir) {
auto Mangler = CommandMangler::forTests();
Mangler.ResourceDir = testPath("fake/resources");

{
tooling::CompileCommand Cmd;
Cmd.CommandLine = {"clang++", "-resource-dir", testPath("true/resources"),
"foo.cc"};
Mangler(Cmd, "foo.cc");
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
HasSubstr("-resource-dir " + testPath("true/resources")));
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
Not(HasSubstr(testPath("fake/resources"))));
}

{
tooling::CompileCommand Cmd;
Cmd.CommandLine = {"clang++", "-resource-dir=" + testPath("true/resources"),
"foo.cc"};
Mangler(Cmd, "foo.cc");
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
HasSubstr("-resource-dir=" + testPath("true/resources")));
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
Not(HasSubstr(testPath("fake/resources"))));
}
}

TEST(CommandMangler, RespectsOriginalSysroot) {
auto Mangler = CommandMangler::forTests();
Mangler.Sysroot = testPath("fake/sysroot");

{
tooling::CompileCommand Cmd;
Cmd.CommandLine = {"clang++", "-isysroot", testPath("true/sysroot"),
"foo.cc"};
Mangler(Cmd, "foo.cc");
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
HasSubstr("-isysroot " + testPath("true/sysroot")));
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
Not(HasSubstr(testPath("fake/sysroot"))));
}

{
tooling::CompileCommand Cmd;
Cmd.CommandLine = {"clang++", "-isysroot" + testPath("true/sysroot"),
"foo.cc"};
Mangler(Cmd, "foo.cc");
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
HasSubstr("-isysroot" + testPath("true/sysroot")));
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
Not(HasSubstr(testPath("fake/sysroot"))));
}

{
tooling::CompileCommand Cmd;
Cmd.CommandLine = {"clang++", "--sysroot", testPath("true/sysroot"),
"foo.cc"};
Mangler(Cmd, "foo.cc");
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
HasSubstr("--sysroot " + testPath("true/sysroot")));
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
Not(HasSubstr(testPath("fake/sysroot"))));
}

{
tooling::CompileCommand Cmd;
Cmd.CommandLine = {"clang++", "--sysroot=" + testPath("true/sysroot"),
"foo.cc"};
Mangler(Cmd, "foo.cc");
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
HasSubstr("--sysroot=" + testPath("true/sysroot")));
EXPECT_THAT(llvm::join(Cmd.CommandLine, " "),
Not(HasSubstr(testPath("fake/sysroot"))));
}
}
} // namespace
} // namespace clangd
} // namespace clang
13 changes: 13 additions & 0 deletions clang-tools-extra/clangd/unittests/SelectionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,19 @@ TEST(SelectionTest, DeclContextIsLexical) {
}
}

TEST(SelectionTest, DeclContextLambda) {
llvm::Annotations Test(R"cpp(
void foo();
auto lambda = [] {
return $1^foo();
};
)cpp");
auto AST = TestTU::withCode(Test.code()).build();
auto ST = SelectionTree::createRight(AST.getASTContext(), AST.getTokens(),
Test.point("1"), Test.point("1"));
EXPECT_TRUE(ST.commonAncestor()->getDeclContext().isFunctionOrMethod());
}

} // namespace
} // namespace clangd
} // namespace clang
23 changes: 23 additions & 0 deletions clang-tools-extra/clangd/unittests/tweaks/AddUsingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,29 @@ namespace foo { void fun(); }
void foo::fun() {
ff();
})cpp"},
// Inside a lambda.
{
R"cpp(
namespace NS {
void unrelated();
void foo();
}
auto L = [] {
using NS::unrelated;
NS::f^oo();
};)cpp",
R"cpp(
namespace NS {
void unrelated();
void foo();
}
auto L = [] {
using NS::foo;using NS::unrelated;
foo();
};)cpp",
},
// If all other using are fully qualified, add ::
{R"cpp(
#include "test.hpp"
Expand Down
11 changes: 8 additions & 3 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ Improvements to clang-tidy

- Improved `--dump-config` to print check options in alphabetical order.

- Improved :program:`clang-tidy-diff.py` script.
- Improved :program:`clang-tidy-diff.py` script.
* Return exit code `1` if any :program:`clang-tidy` subprocess exits with
a non-zero code or if exporting fixes fails.

Expand Down Expand Up @@ -368,7 +368,8 @@ Changes in existing checks
<clang-tidy/checks/misc/const-correctness>` check to avoid false positive when
using pointer to member function. Additionally, the check no longer emits
a diagnostic when a variable that is not type-dependent is an operand of a
type-dependent binary operator.
type-dependent binary operator. Improved performance of the check through
optimizations.

- Improved :doc:`misc-include-cleaner
<clang-tidy/checks/misc/include-cleaner>` check by adding option
Expand All @@ -380,9 +381,13 @@ Changes in existing checks
<clang-tidy/checks/misc/redundant-expression>` check to ignore
false-positives in unevaluated context (e.g., ``decltype``).

- Improved :doc:`misc-static-assert
<clang-tidy/checks/misc/static-assert>` check to ignore false-positives when
referring to non-``constexpr`` variables in non-unevaluated context.

- Improved :doc:`misc-unused-using-decls
<clang-tidy/checks/misc/unused-using-decls>` check to avoid false positive when
using in elaborated type.
using in elaborated type and only check cpp files.

- Improved :doc:`modernize-avoid-bind
<clang-tidy/checks/modernize/avoid-bind>` check to
Expand Down
42 changes: 42 additions & 0 deletions clang-tools-extra/test/clang-tidy/checkers/misc/static-assert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,48 @@ void print(...);
#define my_macro() assert(0 == 1)
// CHECK-FIXES: #define my_macro() assert(0 == 1)

namespace PR24066 {

void referenceMember() {
struct {
int A;
int B;
} S;
assert(&S.B - &S.A == 1);
}

const int X = 1;
void referenceVariable() {
assert(X > 0);
}


constexpr int Y = 1;
void referenceConstexprVariable() {
assert(Y > 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
// CHECK-FIXES-CXX11: {{^ }}static_assert(Y > 0, "");
// CHECK-FIXES-CXX17: {{^ }}static_assert(Y > 0);
}

void useInSizeOf() {
char a = 0;
assert(sizeof(a) == 1U);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
// CHECK-FIXES-CXX11: {{^ }}static_assert(sizeof(a) == 1U, "");
// CHECK-FIXES-CXX17: {{^ }}static_assert(sizeof(a) == 1U);
}

void useInDecltype() {
char a = 0;
assert(static_cast<decltype(a)>(256) == 0);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: found assert() that could be replaced by static_assert() [misc-static-assert]
// CHECK-FIXES-CXX11: {{^ }}static_assert(static_cast<decltype(a)>(256) == 0, "");
// CHECK-FIXES-CXX17: {{^ }}static_assert(static_cast<decltype(a)>(256) == 0);
}

}

constexpr bool myfunc(int a, int b) { return a * b == 0; }

typedef __SIZE_TYPE__ size_t;
Expand Down
6 changes: 6 additions & 0 deletions clang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ set(C_INCLUDE_DIRS "" CACHE STRING
set(GCC_INSTALL_PREFIX "" CACHE PATH "Directory where gcc is installed." )
set(DEFAULT_SYSROOT "" CACHE STRING
"Default <path> to all compiler invocations for --sysroot=<path>." )
if(GCC_INSTALL_PREFIX)
message(WARNING "GCC_INSTALL_PREFIX is deprecated and will be removed. Use "
"configuration files (https://clang.llvm.org/docs/UsersManual.html#configuration-files)"
"to specify the default --gcc-install-dir= or --gcc-triple=. --gcc-toolchain= is discouraged. "
"See https://github.com/llvm/llvm-project/pull/77537 for detail.")
endif()

set(ENABLE_LINKER_BUILD_ID OFF CACHE BOOL "pass --build-id to ld")

Expand Down
16 changes: 16 additions & 0 deletions clang/cmake/caches/Fuchsia.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,25 @@ set(_FUCHSIA_BOOTSTRAP_PASSTHROUGH
CURL_ROOT
OpenSSL_ROOT
httplib_ROOT

# Deprecated
CursesAndPanel_ROOT

CURSES_INCLUDE_DIRS
CURSES_LIBRARIES
PANEL_LIBRARIES

# Deprecated
Terminfo_ROOT

Terminfo_LIBRARIES

# Deprecated
LibEdit_ROOT

LibEdit_INCLUDE_DIRS
LibEdit_LIBRARIES

FUCHSIA_ENABLE_LLDB
LLDB_ENABLE_CURSES
LLDB_ENABLE_LIBEDIT
Expand Down
13 changes: 12 additions & 1 deletion clang/cmake/caches/Release.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
# BOOTSTRAP_* options configure the second build.
# BOOTSTRAP_BOOTSTRAP_* options configure the third build.

# General Options
set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "")

set(CMAKE_BUILD_TYPE RELEASE CACHE STRING "")

# Stage 1 Bootstrap Setup
Expand Down Expand Up @@ -33,9 +36,17 @@ set(BOOTSTRAP_CLANG_BOOTSTRAP_TARGETS
check-clang CACHE STRING "")

# Stage 2 Options
set(BOOTSTRAP_LLVM_ENABLE_PROJECTS "clang" CACHE STRING "")
set(STAGE2_PROJECTS "clang")
if (LLVM_RELEASE_ENABLE_LTO)
list(APPEND STAGE2_PROJECTS "lld")
endif()
set(BOOTSTRAP_LLVM_ENABLE_PROJECTS ${STAGE2_PROJECTS} CACHE STRING "")
set(BOOTSTRAP_LLVM_TARGETS_TO_BUILD Native CACHE STRING "")

# Stage 3 Options
set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_PROJECTS "clang;lld;lldb;clang-tools-extra;bolt;polly;mlir;flang" CACHE STRING "")
set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LTO ${LLVM_RELEASE_ENABLE_LTO} CACHE STRING "")
if (LLVM_RELEASE_ENABLE_LTO)
set(BOOTSTRAP_BOOTSTRAP_LLVM_ENABLE_LLD ON CACHE BOOL "")
endif()
6 changes: 5 additions & 1 deletion clang/docs/ClangFormat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ An easy way to create the ``.clang-format`` file is:
Available style options are described in :doc:`ClangFormatStyleOptions`.

.clang-format-ignore
====================

You can create ``.clang-format-ignore`` files to make ``clang-format`` ignore
certain files. A ``.clang-format-ignore`` file consists of patterns of file path
names. It has the following format:
Expand All @@ -141,7 +144,8 @@ names. It has the following format:
* A non-comment line is a single pattern.
* The slash (``/``) is used as the directory separator.
* A pattern is relative to the directory of the ``.clang-format-ignore`` file
(or the root directory if the pattern starts with a slash).
(or the root directory if the pattern starts with a slash). Patterns
containing drive names (e.g. ``C:``) are not supported.
* Patterns follow the rules specified in `POSIX 2.13.1, 2.13.2, and Rule 1 of
2.13.3 <https://pubs.opengroup.org/onlinepubs/9699919799/utilities/
V3_chap02.html#tag_18_13>`_.
Expand Down
68 changes: 68 additions & 0 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down Expand Up @@ -517,6 +534,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down Expand Up @@ -642,6 +676,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down Expand Up @@ -768,6 +819,23 @@ the configuration (without a prefix: ``Auto``).
a &= 2;
bbb = 2;

* ``bool AlignFunctionPointers`` Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
aligned.

.. code-block:: c++

true:
unsigned i;
int &r;
int *p;
int (*f)();
false:
unsigned i;
int &r;
int *p;
int (*f)();
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
Expand Down
321 changes: 321 additions & 0 deletions clang/docs/HLSL/FunctionCalls.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
===================
HLSL Function Calls
===================

.. contents::
:local:

Introduction
============

This document describes the design and implementation of HLSL's function call
semantics in Clang. This includes details related to argument conversion and
parameter lifetimes.

This document does not seek to serve as official documentation for HLSL's
call semantics, but does provide an overview to assist a reader. The
authoritative documentation for HLSL's language semantics is the `draft language
specification <https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf>`_.

Argument Semantics
==================

In HLSL, all function arguments are passed by value in and out of functions.
HLSL has 3 keywords which denote the parameter semantics (``in``, ``out`` and
``inout``). In a function declaration a parameter may be annotated any of the
following ways:

#. <no parameter annotation> - denotes input
#. ``in`` - denotes input
#. ``out`` - denotes output
#. ``in out`` - denotes input and output
#. ``out in`` - denotes input and output
#. ``inout`` - denotes input and output

Parameters that are exclusively input behave like C/C++ parameters that are
passed by value.

For parameters that are output (or input and output), a temporary value is
created in the caller. The temporary value is then passed by-address. For
output-only parameters, the temporary is uninitialized when passed (if the
parameter is not explicitly initialized inside the function an undefined value
is stored back to the argument expression). For parameters that are both input
and output, the temporary is initialized from the lvalue argument expression
through implicit or explicit casting from the lvalue argument type to the
parameter type.

On return of the function, the values of any parameter temporaries are written
back to the argument expression through an inverted conversion sequence (if an
``out`` parameter was not initialized in the function, the uninitialized value
may be written back).

Parameters of constant-sized array type are also passed with value semantics.
This requires input parameters of arrays to construct temporaries and the
temporaries go through array-to-pointer decay when initializing parameters.

Implementations are allowed to avoid unnecessary temporaries, and HLSL's strict
no-alias rules can enable some trivial optimizations.

Array Temporaries
-----------------

Given the following example:

.. code-block:: c++

void fn(float a[4]) {
a[0] = a[1] + a[2] + a[3];
}

float4 main() : SV_Target {
float arr[4] = {1, 1, 1, 1};
fn(arr);
return float4(arr[0], arr[1], arr[2], arr[3]);
}

In C or C++, the array parameter decays to a pointer, so after the call to
``fn``, the value of ``arr[0]`` is ``3``. In HLSL, the array is passed by value,
so modifications inside ``fn`` do not propagate out.

.. note::

DXC may pass unsized arrays directly as decayed pointers, which is an
unfortunate behavior divergence.

Out Parameter Temporaries
-------------------------

.. code-block:: c++

void Init(inout int X, inout int Y) {
Y = 2;
X = 1;
}

void main() {
int V;
Init(V, V); // MSVC (or clang-cl) V == 2, Clang V == 1
}

In the above example the ``Init`` function's behavior depends on the C++
implementation. C++ does not define the order in which parameters are
initialized or destroyed. In MSVC and Clang's MSVC compatibility mode, arguments
are emitted right-to-left and destroyed left-to-right. This means that the
parameter initialization and destruction occurs in the order: {``Y``, ``X``,
``~X``, ``~Y``}. This causes the write-back of the value of ``Y`` to occur last,
so the resulting value of ``V`` is ``2``. In the Itanium C++ ABI, the parameter
ordering is reversed, so the initialization and destruction occurs in the order:
{``X``, ``Y``, ``~Y``, ``X``}. This causes the write-back of the value ``X`` to
occur last, resulting in the value of ``V`` being set to ``1``.

.. code-block:: c++

void Trunc(inout int3 V) { }


void main() {
float3 F = {1.5, 2.6, 3.3};
Trunc(F); // F == {1.0, 2.0, 3.0}
}

In the above example, the argument expression ``F`` undergoes element-wise
conversion from a float vector to an integer vector to create a temporary
``int3``. On expiration the temporary undergoes elementwise conversion back to
the floating point vector type ``float3``. This results in an implicit
element-wise conversion of the vector even if the value is unused in the
function (effectively truncating the floating point values).


.. code-block:: c++

void UB(out int X) {}

void main() {
int X = 7;
UB(X); // X is undefined!
}

In this example an initialized value is passed to an ``out`` parameter.
Parameters marked ``out`` are not initialized by the argument expression or
implicitly by the function. They must be explicitly initialized. In this case
the argument is not initialized in the function so the temporary is still
uninitialized when it is copied back to the argument expression. This is
undefined behavior in HLSL, and any use of the argument after the call is a use
of an undefined value which may be illegal in the target (DXIL programs with
used or potentially used ``undef`` or ``poison`` values fail validation).

Clang Implementation
====================

.. note::

The implementation described here is a proposal. It has not yet been fully
implemented, so the current state of Clang's sources may not reflect this
design. A prototype implementation was built on DXC which is Clang-3.7 based.
The prototype can be found
`here <https://github.com/microsoft/DirectXShaderCompiler/pull/5249>`_. A lot
of the changes in the prototype implementation are restoring Clang-3.7 code
that was previously modified to its original state.

The implementation in clang depends on two new AST nodes and minor extensions to
Clang's existing support for Objective-C write-back arguments. The goal of this
design is to capture the semantic details of HLSL function calls in the AST, and
minimize the amount of magic that needs to occur during IR generation.

The two new AST nodes are ``HLSLArrayTemporaryExpr`` and ``HLSLOutParamExpr``,
which respectively represent the temporaries used for passing arrays by value
and the temporaries created for function outputs.

Array Temporaries
-----------------

The ``HLSLArrayTemporaryExpr`` represents temporary values for input
constant-sized array arguments. This applies for all constant-sized array
arguments regardless of whether or not the parameter is constant-sized or
unsized.

.. code-block:: c++

void SizedArray(float a[4]);
void UnsizedArray(float a[]);

void main() {
float arr[4] = {1, 1, 1, 1};
SizedArray(arr);
UnsizedArray(arr);
}

In the example above, the following AST is generated for the call to
``SizedArray``:

.. code-block:: text
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(float [4])' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (float [4])' lvalue Function 'SizedArray' 'void (float [4])'
`-HLSLArrayTemporaryExpr 'float [4]'
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'
In the example above, the following AST is generated for the call to
``UnsizedArray``:

.. code-block:: text
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(float [])' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])'
`-HLSLArrayTemporaryExpr 'float [4]'
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'
In both of these cases the argument expression is of known array size so we can
initialize an appropriately sized temporary.

It is illegal in HLSL to convert an unsized array to a sized array:

.. code-block:: c++

void SizedArray(float a[4]);
void UnsizedArray(float a[]) {
SizedArray(a); // Cannot convert float[] to float[4]
}

When converting a sized array to an unsized array, an array temporary can also
be inserted. Given the following code:

.. code-block:: c++

void UnsizedArray(float a[]);
void SizedArray(float a[4]) {
UnsizedArray(a);
}

An expected AST should be something like:

.. code-block:: text
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(float [])' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (float [])' lvalue Function 'UnsizedArray' 'void (float [])'
`-HLSLArrayTemporaryExpr 'float [4]'
`-DeclRefExpr 'float [4]' lvalue Var 'arr' 'float [4]'
Out Parameter Temporaries
-------------------------

Output parameters are defined in HLSL as *casting expiring values* (cx-values),
which is a term made up for HLSL. A cx-value is a temporary value which may be
the result of a cast, and stores its value back to an lvalue when the value
expires.

To represent this concept in Clang we introduce a new ``HLSLOutParamExpr``. An
``HLSLOutParamExpr`` has two forms, one with a single sub-expression and one
with two sub-expressions.

The single sub-expression form is used when the argument expression and the
function parameter are the same type, so no cast is required. As in this
example:

.. code-block:: c++

void Init(inout int X) {
X = 1;
}

void main() {
int V;
Init(V);
}

The expected AST formulation for this code would be something like:

.. code-block:: text
CallExpr 'void'
|-ImplicitCastExpr 'void (*)(int &)' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (int &)' lvalue Function 'Init' 'void (int &)'
|-HLSLOutParamExpr 'int' lvalue inout
`-DeclRefExpr 'int' lvalue Var 'V' 'int'
The ``HLSLOutParamExpr`` captures that the value is ``inout`` vs ``out`` to
denote whether or not the temporary is initialized from the sub-expression. If
no casting is required the sub-expression denotes the lvalue expression that the
cx-value will be copied to when the value expires.

The two sub-expression form of the AST node is required when the argument type
is not the same as the parameter type. Given this example:

.. code-block:: c++

void Trunc(inout int3 V) { }


void main() {
float3 F = {1.5, 2.6, 3.3};
Trunc(F);
}

For this case the ``HLSLOutParamExpr`` will have sub-expressions to record both
casting expression sequences for the initialization and write back:

.. code-block:: text
-CallExpr 'void'
|-ImplicitCastExpr 'void (*)(int3 &)' <FunctionToPointerDecay>
| `-DeclRefExpr 'void (int3 &)' lvalue Function 'inc_i32' 'void (int3 &)'
`-HLSLOutParamExpr 'int3' lvalue inout
|-ImplicitCastExpr 'float3' <IntegralToFloating>
| `-ImplicitCastExpr 'int3' <LValueToRValue>
| `-OpaqueValueExpr 'int3' lvalue
`-ImplicitCastExpr 'int3' <FloatingToIntegral>
`-ImplicitCastExpr 'float3' <LValueToRValue>
`-DeclRefExpr 'float3' lvalue 'F' 'float3'
In this formation the write-back casts are captured as the first sub-expression
and they cast from an ``OpaqueValueExpr``. In IR generation we can use the
``OpaqueValueExpr`` as a placeholder for the ``HLSLOutParamExpr``'s temporary
value on function return.

In code generation this can be implemented with some targeted extensions to the
Objective-C write-back support. Specifically extending CGCall.cpp's
``EmitWriteback`` function to support casting expressions and emission of
aggregate lvalues.
1 change: 1 addition & 0 deletions clang/docs/HLSL/HLSLDocs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ HLSL Design and Implementation
HLSLIRReference
ResourceTypes
EntryFunctions
FunctionCalls
36 changes: 33 additions & 3 deletions clang/docs/InternalsManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -931,7 +931,7 @@ the option appears on the command line, the argument value is simply copied.
.. code-block:: text
def isysroot : JoinedOrSeparate<["-"], "isysroot">,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
MarshallingInfoString<HeaderSearchOpts<"Sysroot">, [{"/"}]>;
**List of Strings**
Expand Down Expand Up @@ -3364,7 +3364,7 @@ Multiple occurrences accumulate prefixes. For example,

Specifying Diagnostics
^^^^^^^^^^^^^^^^^^^^^^
Indicating that a line expects an error or a warning is simple. Put a comment
Indicating that a line expects an error or a warning is easy. Put a comment
on the line that has the diagnostic, use
``expected-{error,warning,remark,note}`` to tag if it's an expected error,
warning, remark, or note (respectively), and place the expected text between
Expand All @@ -3373,6 +3373,9 @@ enough to ensure that the correct diagnostic was emitted. (Note: full text
should be included in test cases unless there is a compelling reason to use
truncated text instead.)

For a full description of the matching behavior, including more complex
matching scenarios, see :ref:`matching <DiagnosticMatching>` below.

Here's an example of the most commonly used way to specify expected
diagnostics:

Expand Down Expand Up @@ -3458,8 +3461,33 @@ A range can also be specified by ``<n>-<m>``. For example:

In this example, the diagnostic may appear only once, if at all.

.. _DiagnosticMatching:

Matching Modes
~~~~~~~~~~~~~~

The default matching mode is simple string, which looks for the expected text
that appears between the first `{{` and `}}` pair of the comment. The string is
interpreted just as-is, with one exception: the sequence `\n` is converted to a
single newline character. This mode matches the emitted diagnostic when the
text appears as a substring at any position of the emitted message.

To enable matching against desired strings that contain `}}` or `{{`, the
string-mode parser accepts opening delimiters of more than two curly braces,
like `{{{`. It then looks for a closing delimiter of equal "width" (i.e `}}}`).
For example:

.. code-block:: c++

// expected-note {{{evaluates to '{{2, 3, 4}} == {0, 3, 4}'}}}

The intent is to allow the delimeter to be wider than the longest `{` or `}`
brace sequence in the content, so that if your expected text contains `{{{`
(three braces) it may be delimited with `{{{{` (four braces), and so on.

Regex matching mode may be selected by appending ``-re`` to the diagnostic type
and including regexes wrapped in double curly braces in the directive, such as:
and including regexes wrapped in double curly braces (`{{` and `}}`) in the
directive, such as:

.. code-block:: text
Expand All @@ -3471,6 +3499,8 @@ Examples matching error: "variable has incomplete type 'struct s'"

// expected-error {{variable has incomplete type 'struct s'}}
// expected-error {{variable has incomplete type}}
// expected-error {{{variable has incomplete type}}}
// expected-error {{{{variable has incomplete type}}}}

// expected-error-re {{variable has type 'struct {{.}}'}}
// expected-error-re {{variable has type 'struct {{.*}}'}}
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,7 @@ to ``float``; see below for more information on this emulation.
see below.

* ``_Float16`` is supported on the following targets:

* 32-bit ARM (natively on some architecture versions)
* 64-bit ARM (AArch64) (natively on ARMv8.2a and above)
* AMDGPU (natively)
Expand All @@ -837,6 +838,7 @@ to ``float``; see below for more information on this emulation.
* RISC-V (natively if Zfh or Zhinx is available)

* ``__bf16`` is supported on the following targets (currently never natively):

* 32-bit ARM
* 64-bit ARM (AArch64)
* RISC-V
Expand Down
85 changes: 78 additions & 7 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,35 @@ These changes are ones which we think may surprise users when upgrading to
Clang |release| because of the opportunity they pose for disruption to existing
code bases.

- Fix a bug in reversed argument for templated operators.
This breaks code in C++20 which was previously accepted in C++17.
Clang did not properly diagnose such casese in C++20 before this change. Eg:

.. code-block:: cpp
struct P {};
template<class S> bool operator==(const P&, const S&);
struct A : public P {};
struct B : public P {};
// This equality is now ambiguous in C++20.
bool ambiguous(A a, B b) { return a == b; }
template<class S> bool operator!=(const P&, const S&);
// Ok. Found a matching operator!=.
bool fine(A a, B b) { return a == b; }
To reduce such widespread breakages, as an extension, Clang accepts this code
with an existing warning ``-Wambiguous-reversed-operator`` warning.
Fixes `GH <https://github.com/llvm/llvm-project/issues/53954>`_.

- The CMake variable ``GCC_INSTALL_PREFIX`` (which sets the default
``--gcc-toolchain=``) is deprecated and will be removed. Specify
``--gcc-install-dir=`` or ``--gcc-triple=`` in a `configuration file
<https://clang.llvm.org/docs/UsersManual.html#configuration-files>` as a
replacement.
(`#77537 <https://github.com/llvm/llvm-project/pull/77537>`_)

C/C++ Language Potentially Breaking Changes
-------------------------------------------
Expand Down Expand Up @@ -68,6 +97,10 @@ C/C++ Language Potentially Breaking Changes
outlined in "The Equality Operator You Are Looking For" (`P2468 <http://wg21.link/p2468r2>`_).
Fixes (`#68901: <https://github.com/llvm/llvm-project/issues/68901>`_).

- Remove the hardcoded path to the imported modules for C++20 named modules. Now we
require all the dependent modules to specified from the command line.
See (`#62707: <https://github.com/llvm/llvm-project/issues/62707>`_).

C++ Specific Potentially Breaking Changes
-----------------------------------------
- The name mangling rules for function templates has been changed to take into
Expand Down Expand Up @@ -202,6 +235,11 @@ C Language Changes
- Enums will now be represented in TBAA metadata using their actual underlying
integer type. Previously they were treated as chars, which meant they could
alias with all other types.
- Clang now supports the C-only attribute ``counted_by``. When applied to a
struct's flexible array member, it points to the struct field that holds the
number of elements in the flexible array member. This information can improve
the results of the array bound sanitizer and the
``__builtin_dynamic_object_size`` builtin.

C23 Feature Support
^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -520,6 +558,8 @@ Improvements to Clang's diagnostics
- Clang now diagnoses narrowing conversions involving const references.
(`#63151: <https://github.com/llvm/llvm-project/issues/63151>`_).
- Clang now diagnoses unexpanded packs within the template argument lists of function template specializations.
- Clang now diagnoses attempts to bind a bitfield to an NTTP of a reference type as erroneous
converted constant expression and not as a reference to subobject.


Improvements to Clang's time-trace
Expand Down Expand Up @@ -610,7 +650,8 @@ Bug Fixes in This Version
of template classes. Fixes
(`#68543 <https://github.com/llvm/llvm-project/issues/68543>`_,
`#42496 <https://github.com/llvm/llvm-project/issues/42496>`_,
`#77071 <https://github.com/llvm/llvm-project/issues/77071>`_)
`#77071 <https://github.com/llvm/llvm-project/issues/77071>`_,
`#77411 <https://github.com/llvm/llvm-project/issues/77411>`_)
- Fixed an issue when a shift count larger than ``__INT64_MAX__``, in a right
shift operation, could result in missing warnings about
``shift count >= width of type`` or internal compiler error.
Expand Down Expand Up @@ -696,7 +737,22 @@ Bug Fixes in This Version
- Clang now accepts recursive non-dependent calls to functions with deduced
return type.
Fixes (`#71015 <https://github.com/llvm/llvm-project/issues/71015>`_)

- Fix assertion failure when initializing union containing struct with
flexible array member using empty initializer list.
Fixes (`#77085 <https://github.com/llvm/llvm-project/issues/77085>`_)
- Fix assertion crash due to failed scope restoring caused by too-early VarDecl
invalidation by invalid initializer Expr.
Fixes (`#30908 <https://github.com/llvm/llvm-project/issues/30908>`_)
- Clang now emits correct source location for code-coverage regions in `if constexpr`
and `if consteval` branches.
Fixes (`#54419 <https://github.com/llvm/llvm-project/issues/54419>`_)
- Fix assertion failure when declaring a template friend function with
a constrained parameter in a template class that declares a class method
or lambda at different depth.
Fixes (`#75426 <https://github.com/llvm/llvm-project/issues/75426>`_)
- Fix an issue where clang cannot find conversion function with template
parameter when instantiation of template class.
Fixes (`#77583 <https://github.com/llvm/llvm-project/issues/77583>`_)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -875,6 +931,9 @@ Bug Fixes to AST Handling
- Fixed a bug where RecursiveASTVisitor fails to visit the
initializer of a bitfield.
`Issue 64916 <https://github.com/llvm/llvm-project/issues/64916>`_
- Fixed a bug where range-loop-analysis checks for trivial copyability,
rather than trivial copy-constructibility
`Issue 47355 <https://github.com/llvm/llvm-project/issues/47355>`_
- Fixed a bug where Template Instantiation failed to handle Lambda Expressions
with certain types of Attributes.
(`#76521 <https://github.com/llvm/llvm-project/issues/76521>`_)
Expand Down Expand Up @@ -933,6 +992,14 @@ X86 Support
- Support ISA of ``AVX10.1``.
- ``-march=pantherlake`` and ``-march=clearwaterforest`` are now supported.
- Added ABI handling for ``__float128`` to match with GCC.
- Emit warnings for options to enable knl/knm specific ISAs: AVX512PF, AVX512ER
and PREFETCHWT1. From next version (LLVM 19), these ISAs' intrinsic supports
will be deprecated:
* intrinsic series of *_exp2a23_*
* intrinsic series of *_rsqrt28_*
* intrinsic series of *_rcp28_*
* intrinsic series of *_prefetch_i[3|6][2|4]gather_*
* intrinsic series of *_prefetch_i[3|6][2|4]scatter_*

Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -1065,6 +1132,7 @@ clang-format
- Add ``ObjCPropertyAttributeOrder`` which can be used to sort ObjC property
attributes (like ``nonatomic, strong, nullable``).
- Add ``.clang-format-ignore`` files.
- Add ``AlignFunctionPointers`` sub-option for ``AlignConsecutiveDeclarations``.

libclang
--------
Expand Down Expand Up @@ -1150,9 +1218,10 @@ Improvements
^^^^^^^^^^^^

- Improved the ``unix.StdCLibraryFunctions`` checker by modeling more
functions like ``send``, ``recv``, ``readlink``, ``fflush``, ``mkdtemp`` and
``errno`` behavior.
functions like ``send``, ``recv``, ``readlink``, ``fflush``, ``mkdtemp``,
``getcwd`` and ``errno`` behavior.
(`52ac71f92d38 <https://github.com/llvm/llvm-project/commit/52ac71f92d38f75df5cb88e9c090ac5fd5a71548>`_,
`#77040 <https://github.com/llvm/llvm-project/pull/77040>`_,
`#76671 <https://github.com/llvm/llvm-project/pull/76671>`_,
`#71373 <https://github.com/llvm/llvm-project/pull/71373>`_,
`#76557 <https://github.com/llvm/llvm-project/pull/76557>`_,
Expand Down Expand Up @@ -1181,16 +1250,18 @@ Improvements
(`c3a87ddad62a <https://github.com/llvm/llvm-project/commit/c3a87ddad62a6cc01acaccc76592bc6730c8ac3c>`_,
`0954dc3fb921 <https://github.com/llvm/llvm-project/commit/0954dc3fb9214b994623f5306473de075f8e3593>`_)

- Improved the ``alpha.unix.Stream`` checker by modeling more functions like,
``fflush``, ``fputs``, ``fgetc``, ``fputc``, ``fopen``, ``fdopen``, ``fgets``, ``tmpfile``.
- Improved the ``alpha.unix.Stream`` checker by modeling more functions
``fputs``, ``fputc``, ``fgets``, ``fgetc``, ``fdopen``, ``ungetc``, ``fflush``
and no not recognize alternative ``fopen`` and ``tmpfile`` implementations.
(`#76776 <https://github.com/llvm/llvm-project/pull/76776>`_,
`#74296 <https://github.com/llvm/llvm-project/pull/74296>`_,
`#73335 <https://github.com/llvm/llvm-project/pull/73335>`_,
`#72627 <https://github.com/llvm/llvm-project/pull/72627>`_,
`#71518 <https://github.com/llvm/llvm-project/pull/71518>`_,
`#72016 <https://github.com/llvm/llvm-project/pull/72016>`_,
`#70540 <https://github.com/llvm/llvm-project/pull/70540>`_,
`#73638 <https://github.com/llvm/llvm-project/pull/73638>`_)
`#73638 <https://github.com/llvm/llvm-project/pull/73638>`_,
`#77331 <https://github.com/llvm/llvm-project/pull/77331>`_)

- The ``alpha.security.taint.TaintPropagation`` checker no longer propagates
taint on ``strlen`` and ``strnlen`` calls, unless these are marked
Expand Down
11 changes: 5 additions & 6 deletions clang/docs/StandardCPlusPlusModules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Then we type:
.. code-block:: console
$ clang++ -std=c++20 Hello.cppm --precompile -o Hello.pcm
$ clang++ -std=c++20 use.cpp -fprebuilt-module-path=. Hello.pcm -o Hello.out
$ clang++ -std=c++20 use.cpp -fmodule-file=Hello=Hello.pcm Hello.pcm -o Hello.out
$ ./Hello.out
Hello World!
Expand Down Expand Up @@ -200,15 +200,15 @@ Then we are able to compile the example by the following command:
$ clang++ -std=c++20 interface_part.cppm --precompile -o M-interface_part.pcm
$ clang++ -std=c++20 impl_part.cppm --precompile -fprebuilt-module-path=. -o M-impl_part.pcm
$ clang++ -std=c++20 M.cppm --precompile -fprebuilt-module-path=. -o M.pcm
$ clang++ -std=c++20 Impl.cpp -fmodule-file=M=M.pcm -c -o Impl.o
$ clang++ -std=c++20 Impl.cpp -fprebuilt-module-path=. -c -o Impl.o
# Compiling the user
$ clang++ -std=c++20 User.cpp -fprebuilt-module-path=. -c -o User.o
# Compiling the module and linking it together
$ clang++ -std=c++20 M-interface_part.pcm -c -o M-interface_part.o
$ clang++ -std=c++20 M-impl_part.pcm -c -o M-impl_part.o
$ clang++ -std=c++20 M.pcm -c -o M.o
$ clang++ -std=c++20 M-interface_part.pcm -fprebuilt-module-path=. -c -o M-interface_part.o
$ clang++ -std=c++20 M-impl_part.pcm -fprebuilt-module-path=. -c -o M-impl_part.o
$ clang++ -std=c++20 M.pcm -fprebuilt-module-path=. -c -o M.o
$ clang++ User.o M-interface_part.o M-impl_part.o M.o Impl.o -o a.out
We explain the options in the following sections.
Expand All @@ -218,7 +218,6 @@ How to enable standard C++ modules

Currently, standard C++ modules are enabled automatically
if the language standard is ``-std=c++20`` or newer.
The ``-fmodules-ts`` option is deprecated and is planned to be removed.

How to produce a BMI
~~~~~~~~~~~~~~~~~~~~
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down Expand Up @@ -488,6 +489,15 @@ class alignas(8) Decl {
// Return true if this is a FileContext Decl.
bool isFileContextDecl() const;

/// Whether it resembles a flexible array member. This is a static member
/// because we want to be able to call it with a nullptr. That allows us to
/// perform non-Decl specific checks based on the object's type and strict
/// flex array level.
static bool isFlexibleArrayMemberLike(
ASTContext &Context, const Decl *D, QualType Ty,
LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel,
bool IgnoreTemplateOrMacroSubstitution);

ASTContext &getASTContext() const LLVM_READONLY;

/// Helper to get the language options from the ASTContext.
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,9 @@ class CXXRecordDecl : public RecordDecl {
/// (C++11 [class]p6).
bool isTriviallyCopyable() const;

/// Determine whether this class is considered trivially copyable per
bool isTriviallyCopyConstructible() const;

/// Determine whether this class is considered trivial.
///
/// C++11 [class]p6:
Expand Down
6 changes: 4 additions & 2 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1631,8 +1631,10 @@ class CompoundStmt final
SourceLocation RB);

// Build an empty compound statement with a location.
explicit CompoundStmt(SourceLocation Loc)
: Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) {
explicit CompoundStmt(SourceLocation Loc) : CompoundStmt(Loc, Loc) {}

CompoundStmt(SourceLocation Loc, SourceLocation EndLoc)
: Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(EndLoc) {
CompoundStmtBits.NumStmts = 0;
CompoundStmtBits.HasFPFeatures = 0;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/TextNodeDumper.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,8 @@ class TextNodeDumper
void VisitGotoStmt(const GotoStmt *Node);
void VisitCaseStmt(const CaseStmt *Node);
void VisitReturnStmt(const ReturnStmt *Node);
void VisitCoawaitExpr(const CoawaitExpr *Node);
void VisitCoreturnStmt(const CoreturnStmt *Node);
void VisitCompoundStmt(const CompoundStmt *Node);
void VisitConstantExpr(const ConstantExpr *Node);
void VisitCallExpr(const CallExpr *Node);
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,9 @@ class QualType {
/// Return true if this is a trivially copyable type (C++0x [basic.types]p9)
bool isTriviallyCopyableType(const ASTContext &Context) const;

/// Return true if this is a trivially copyable type
bool isTriviallyCopyConstructibleType(const ASTContext &Context) const;

/// Return true if this is a trivially relocatable type.
bool isTriviallyRelocatableType(const ASTContext &Context) const;

Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Analysis/CFG.h
Original file line number Diff line number Diff line change
Expand Up @@ -1215,7 +1215,9 @@ class CFG {
//===--------------------------------------------------------------------===//

class BuildOptions {
std::bitset<Stmt::lastStmtConstant> alwaysAddMask;
// Stmt::lastStmtConstant has the same value as the last Stmt kind,
// so make sure we add one to account for this!
std::bitset<Stmt::lastStmtConstant + 1> alwaysAddMask;

public:
using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>;
Expand Down
18 changes: 18 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4372,3 +4372,21 @@ def CodeAlign: StmtAttr {
static constexpr int MaximumAlignment = 4096;
}];
}

def CountedBy : InheritableAttr {
let Spellings = [Clang<"counted_by">];
let Subjects = SubjectList<[Field]>;
let Args = [IdentifierArgument<"CountedByField">];
let Documentation = [CountedByDocs];
let LangOpts = [COnly];
// FIXME: This is ugly. Let using a DeclArgument would be nice, but a Decl
// isn't yet available due to the fact that we're still parsing the
// structure. Maybe that code could be changed sometime in the future.
code AdditionalMembers = [{
private:
SourceRange CountedByFieldLoc;
public:
SourceRange getCountedByFieldLoc() const { return CountedByFieldLoc; }
void setCountedByFieldLoc(SourceRange Loc) { CountedByFieldLoc = Loc; }
}];
}
78 changes: 78 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -7749,3 +7749,81 @@ but do not pass them to the underlying coroutine or pass them by value.
.. _`CRT`: https://clang.llvm.org/docs/AttributeReference.html#coro-return-type
}];
}

def CountedByDocs : Documentation {
let Category = DocCatField;
let Content = [{
Clang supports the ``counted_by`` attribute on the flexible array member of a
structure in C. The argument for the attribute is the name of a field member
holding the count of elements in the flexible array. This information can be
used to improve the results of the array bound sanitizer and the
``__builtin_dynamic_object_size`` builtin. The ``count`` field member must be
within the same non-anonymous, enclosing struct as the flexible array member.

This example specifies that the flexible array member ``array`` has the number
of elements allocated for it in ``count``:

.. code-block:: c

struct bar;

struct foo {
size_t count;
char other;
struct bar *array[] __attribute__((counted_by(count)));
};

This establishes a relationship between ``array`` and ``count``. Specifically,
``array`` must have at least ``count`` number of elements available. It's the
user's responsibility to ensure that this relationship is maintained through
changes to the structure.

In the following example, the allocated array erroneously has fewer elements
than what's specified by ``p->count``. This would result in an out-of-bounds
access not being detected.

.. code-block:: c

#define SIZE_INCR 42

struct foo *p;

void foo_alloc(size_t count) {
p = malloc(MAX(sizeof(struct foo),
offsetof(struct foo, array[0]) + count * sizeof(struct bar *)));
p->count = count + SIZE_INCR;
}

The next example updates ``p->count``, but breaks the relationship requirement
that ``p->array`` must have at least ``p->count`` number of elements available:

.. code-block:: c

#define SIZE_INCR 42

struct foo *p;

void foo_alloc(size_t count) {
p = malloc(MAX(sizeof(struct foo),
offsetof(struct foo, array[0]) + count * sizeof(struct bar *)));
p->count = count;
}

void use_foo(int index, int val) {
p->count += SIZE_INCR + 1; /* 'count' is now larger than the number of elements of 'array'. */
p->array[index] = val; /* The sanitizer can't properly check this access. */
}

In this example, an update to ``p->count`` maintains the relationship
requirement:

.. code-block:: c

void use_foo(int index, int val) {
if (p->count == 0)
return;
--p->count;
p->array[index] = val;
}
}];
}
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticCommonKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,9 @@ def warn_invalid_feature_combination : Warning<
def warn_target_unrecognized_env : Warning<
"mismatch between architecture and environment in target triple '%0'; did you mean '%1'?">,
InGroup<InvalidCommandLineArgument>;
def warn_knl_knm_isa_support_removed : Warning<
"KNL, KNM related Intel Xeon Phi CPU's specific ISA's supports will be removed in LLVM 19.">,
InGroup<DiagGroup<"knl-knm-isa-support-removed">>;

// Source manager
def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ def warn_unsupported_branch_protection: Warning <
def err_sls_hardening_arm_not_supported : Error<
"-mharden-sls is only supported on armv7-a or later">;
def warn_drv_large_data_threshold_invalid_code_model: Warning<
"'%0' only applies to medium code model">,
"'%0' only applies to medium and large code models">,
InGroup<UnusedCommandLineArgument>;

def note_drv_command_failed_diag_msg : Note<
Expand Down Expand Up @@ -786,4 +786,7 @@ def warn_android_unversioned_fallback : Warning<
" directories will not be used in Clang 19. Provide a versioned directory"
" for the target version or lower instead.">,
InGroup<DiagGroup<"android-unversioned-fallback">>;

def err_drv_triple_version_invalid : Error<
"version '%0' in target triple '%1' is invalid">;
}
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticFrontendKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def err_verify_no_such_marker : Error<
def err_verify_missing_start : Error<
"cannot find start ('{{') of expected %0">;
def err_verify_missing_end : Error<
"cannot find end ('}}') of expected %0">;
"cannot find end ('%1') of expected %0">;
def err_verify_invalid_content : Error<
"invalid expected %0: %1">;
def err_verify_missing_regex : Error<
Expand Down
25 changes: 18 additions & 7 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2253,6 +2253,8 @@ def warn_cxx17_compat_aggregate_init_paren_list : Warning<
def err_reference_bind_to_bitfield : Error<
"%select{non-const|volatile}0 reference cannot bind to "
"bit-field%select{| %1}2">;
def err_reference_bind_to_bitfield_in_cce : Error<
"reference cannot bind to bit-field in converted constant expression">;
def err_reference_bind_to_vector_element : Error<
"%select{non-const|volatile}0 reference cannot bind to vector element">;
def err_reference_bind_to_matrix_element : Error<
Expand Down Expand Up @@ -6160,23 +6162,19 @@ def err_illegal_initializer_type : Error<"illegal initializer type %0">;
def ext_init_list_type_narrowing : ExtWarn<
"type %0 cannot be narrowed to %1 in initializer list">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
// *_narrowing_const_reference diagnostics have the same messages, but are
// controlled by -Wc++11-narrowing-const-reference for narrowing involving a
// const reference.
def ext_init_list_type_narrowing_const_reference : ExtWarn<
"type %0 cannot be narrowed to %1 in initializer list">,
ext_init_list_type_narrowing.Summary>,
InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
def ext_init_list_variable_narrowing : ExtWarn<
"non-constant-expression cannot be narrowed from type %0 to %1 in "
"initializer list">, InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def ext_init_list_variable_narrowing_const_reference : ExtWarn<
"non-constant-expression cannot be narrowed from type %0 to %1 in "
"initializer list">, InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
ext_init_list_variable_narrowing.Summary>, InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
def ext_init_list_constant_narrowing : ExtWarn<
"constant expression evaluates to %0 which cannot be narrowed to type %1">,
InGroup<CXX11Narrowing>, DefaultError, SFINAEFailure;
def ext_init_list_constant_narrowing_const_reference : ExtWarn<
"constant expression evaluates to %0 which cannot be narrowed to type %1">,
ext_init_list_constant_narrowing.Summary>,
InGroup<CXX11NarrowingConstReference>, DefaultError, SFINAEFailure;
def warn_init_list_type_narrowing : Warning<
"type %0 cannot be narrowed to %1 in initializer list in C++11">,
Expand Down Expand Up @@ -6443,6 +6441,19 @@ def warn_superclass_variable_sized_type_not_at_end : Warning<
"field %0 can overwrite instance variable %1 with variable sized type %2"
" in superclass %3">, InGroup<ObjCFlexibleArray>;

def err_flexible_array_count_not_in_same_struct : Error<
"'counted_by' field %0 isn't within the same struct as the flexible array">;
def err_counted_by_attr_not_on_flexible_array_member : Error<
"'counted_by' only applies to C99 flexible array members">;
def err_counted_by_attr_refers_to_flexible_array : Error<
"'counted_by' cannot refer to the flexible array %0">;
def err_counted_by_must_be_in_structure : Error<
"field %0 in 'counted_by' not inside structure">;
def err_flexible_array_counted_by_attr_field_not_integer : Error<
"field %0 in 'counted_by' must be a non-boolean integer type">;
def note_flexible_array_counted_by_attr_field : Note<
"field %0 declared here">;

let CategoryName = "ARC Semantic Issue" in {

// ARC-mode diagnostics.
Expand Down
6 changes: 2 additions & 4 deletions clang/include/clang/Basic/DiagnosticSerializationKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,8 @@ def warn_module_system_bit_conflict : Warning<
"as a non-system module; any difference in diagnostic options will be ignored">,
InGroup<ModuleConflict>;

def warn_reading_std_cxx_module_by_implicit_paths : Warning<
"it is deprecated to read module '%0' implicitly; it is going to be removed in clang 18; "
"consider to specify the dependencies explicitly">,
InGroup<DiagGroup<"read-modules-implicitly">>;
def err_failed_to_find_module_file : Error<
"failed to find module file for module '%0'">;
} // let CategoryName

let CategoryName = "AST Serialization Issue" in {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ ENUM_LANGOPT(SignReturnAddressKey, SignReturnAddressKeyKind, 1, SignReturnAddres
"Key used for return address signing")
LANGOPT(BranchTargetEnforcement, 1, 0, "Branch-target enforcement enabled")
LANGOPT(BranchProtectionPAuthLR, 1, 0, "Use PC as a diversifier using PAuthLR NOP instructions.")
LANGOPT(GuardedControlStack, 1, 0, "Guarded control stack enabled")

LANGOPT(SpeculativeLoadHardening, 1, 0, "Speculative load hardening enabled")

Expand Down
41 changes: 41 additions & 0 deletions clang/include/clang/Basic/OpenACCKinds.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,47 @@ enum class OpenACCClauseKind {
/// 'default' clause, allowed on parallel, serial, kernel (and compound)
/// constructs.
Default,
/// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
/// Executable Constructs, and Combined Constructs.
If,
/// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
Self,
/// 'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and
/// 'declare'.
Copy,
/// 'use_device' clause, allowed on 'host_data' construct.
UseDevice,
/// 'attach' clause, allowed on Compute and Combined constructs, plus 'data'
/// and 'enter data'.
Attach,
/// 'delete' clause, allowed on the 'exit data' construct.
Delete,
/// 'detach' clause, allowed on the 'exit data' construct.
Detach,
/// 'device' clause, allowed on the 'update' construct.
Device,
/// 'deviceptr' clause, allowed on Compute and Combined Constructs, plus
/// 'data' and 'declare'.
DevicePtr,
/// 'device_resident' clause, allowed on the 'declare' construct.
DeviceResident,
/// 'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop',
/// and 'serial loop' constructs.
FirstPrivate,
/// 'host' clause, allowed on 'update' construct.
Host,
/// 'link' clause, allowed on 'declare' construct.
Link,
/// 'no_create' clause, allowed on allowed on Compute and Combined constructs,
/// plus 'data'.
NoCreate,
/// 'present' clause, allowed on Compute and Combined constructs, plus 'data'
/// and 'declare'.
Present,
/// 'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel
/// loop', and 'serial loop' constructs.
Private,

/// Represents an invalid clause, for the purposes of parsing.
Invalid,
};
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -1373,6 +1373,7 @@ class TargetInfo : public TransferrableTargetInfo,
LangOptions::SignReturnAddressKeyKind::AKey;
bool BranchTargetEnforcement = false;
bool BranchProtectionPAuthLR = false;
bool GuardedControlStack = false;
};

/// Determine if the Architecture in this TargetInfo supports branch
Expand Down
38 changes: 19 additions & 19 deletions clang/include/clang/Basic/arm_sve.td
Original file line number Diff line number Diff line change
Expand Up @@ -454,11 +454,11 @@ let TargetGuard = "sve,bf16" in {

let TargetGuard = "sve2p1" in {
// Contiguous truncating store from quadword (single vector).
def SVST1UWQ : MInst<"svst1uwq[_{d}]", "vPcd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1uwq">;
def SVST1UWQ_VNUM : MInst<"svst1uwq_vnum[_{d}]", "vPcld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1uwq">;
def SVST1UWQ : MInst<"svst1wq[_{d}]", "vPcd", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">;
def SVST1UWQ_VNUM : MInst<"svst1wq_vnum[_{d}]", "vPcld", "iUif", [IsStore], MemEltTyInt32, "aarch64_sve_st1wq">;

def SVST1UDQ : MInst<"svst1udq[_{d}]", "vPcd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1udq">;
def SVST1UDQ_VNUM : MInst<"svst1udq_vnum[_{d}]", "vPcld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1udq">;
def SVST1UDQ : MInst<"svst1dq[_{d}]", "vPcd", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">;
def SVST1UDQ_VNUM : MInst<"svst1dq_vnum[_{d}]", "vPcld", "lUld", [IsStore], MemEltTyInt64, "aarch64_sve_st1dq">;

// Store one vector (vector base + scalar offset)
def SVST1Q_SCATTER_U64BASE_OFFSET : MInst<"svst1q_scatter[_{2}base]_offset[_{d}]", "vPgld", "cUcsUsiUilUlfhdb", [IsScatterStore, IsByteIndexed], MemEltTyDefault, "aarch64_sve_st1q_scatter_scalar_offset">;
Expand Down Expand Up @@ -2040,12 +2040,12 @@ let TargetGuard = "sve2p1|sme2" in {
}

let TargetGuard = "sve2p1" in {
def SVDOT_X2_S : SInst<"svdot[_{d}_{2}_{3}]", "ddhh", "i", MergeNone, "aarch64_sve_sdot_x2", [], []>;
def SVDOT_X2_U : SInst<"svdot[_{d}_{2}_{3}]", "ddhh", "Ui", MergeNone, "aarch64_sve_udot_x2", [], []>;
def SVDOT_X2_F : SInst<"svdot[_{d}_{2}_{3}]", "ddhh", "f", MergeNone, "aarch64_sve_fdot_x2", [], []>;
def SVDOT_LANE_X2_S : SInst<"svdot_lane[_{d}_{2}_{3}]", "ddhhi", "i", MergeNone, "aarch64_sve_sdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_U : SInst<"svdot_lane[_{d}_{2}_{3}]", "ddhhi", "Ui", MergeNone, "aarch64_sve_udot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_F : SInst<"svdot_lane[_{d}_{2}_{3}]", "ddhhi", "f", MergeNone, "aarch64_sve_fdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_X2_S : SInst<"svdot[_{d}_{2}]", "ddhh", "i", MergeNone, "aarch64_sve_sdot_x2", [], []>;
def SVDOT_X2_U : SInst<"svdot[_{d}_{2}]", "ddhh", "Ui", MergeNone, "aarch64_sve_udot_x2", [], []>;
def SVDOT_X2_F : SInst<"svdot[_{d}_{2}]", "ddhh", "f", MergeNone, "aarch64_sve_fdot_x2", [], []>;
def SVDOT_LANE_X2_S : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "i", MergeNone, "aarch64_sve_sdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_U : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "Ui", MergeNone, "aarch64_sve_udot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
def SVDOT_LANE_X2_F : SInst<"svdot_lane[_{d}_{2}]", "ddhhi", "f", MergeNone, "aarch64_sve_fdot_lane_x2", [], [ImmCheck<3, ImmCheck0_3>]>;
}

let TargetGuard = "sve2p1|sme2" in {
Expand Down Expand Up @@ -2208,7 +2208,7 @@ let TargetGuard = "sve2p1" in {
def SVTBLQ : SInst<"svtblq[_{d}]", "ddu", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_tblq">;
def SVTBXQ : SInst<"svtbxq[_{d}]", "dddu", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_tbxq">;
// EXTQ
def EXTQ : SInst<"svextq_lane[_{d}]", "dddk", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_extq_lane", [], [ImmCheck<2, ImmCheck0_15>]>;
def EXTQ : SInst<"svextq[_{d}]", "dddk", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_extq", [], [ImmCheck<2, ImmCheck0_15>]>;
// PMOV
// Move to Pred
multiclass PMOV_TO_PRED<string name, string types, string intrinsic, list<FlagType> flags=[], ImmCheckType immCh > {
Expand Down Expand Up @@ -2238,15 +2238,15 @@ let TargetGuard = "sme2" in {
def SVCVT_F16_X2 : SInst<"svcvt_f16[_f32_x2]", "e2", "f", MergeNone, "aarch64_sve_fcvt_x2", [IsStreaming],[]>;
def SVCVT_BF16_X2 : SInst<"svcvt_bf16[_f32_x2]", "$2", "f", MergeNone, "aarch64_sve_bfcvt_x2", [IsOverloadNone, IsStreaming],[]>;

def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_fcvtu_x2", [IsStreaming], []>;
def SVCVT_U32_F32_X2 : SInst<"svcvt_u32[_{d}_x2]", "2.u2.d", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming], []>;
def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_fcvts_x2", [IsStreaming], []>;
def SVCVT_S32_F32_X2 : SInst<"svcvt_s32[_{d}_x2]", "2.x2.d", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming], []>;
def SVCVT_F32_U32_X2 : SInst<"svcvt_{d}[_u32_x2]", "2.d2.u", "f", MergeNone, "aarch64_sve_ucvtf_x2", [IsStreaming], []>;
def SVCVT_U32_F32_X2 : SInst<"svcvt_u32[_{d}_x2]", "2.u2.d", "f", MergeNone, "aarch64_sve_fcvtu_x2", [IsStreaming], []>;
def SVCVT_F32_S32_X2 : SInst<"svcvt_{d}[_s32_x2]", "2.d2.x", "f", MergeNone, "aarch64_sve_scvtf_x2", [IsStreaming], []>;
def SVCVT_S32_F32_X2 : SInst<"svcvt_s32[_{d}_x2]", "2.x2.d", "f", MergeNone, "aarch64_sve_fcvts_x2", [IsStreaming], []>;

def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_fcvtu_x4", [IsStreaming], []>;
def SVCVT_U32_F32_X4 : SInst<"svcvt_u32[_{d}_x4]", "4.u4.d", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming], []>;
def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_fcvts_x4", [IsStreaming], []>;
def SVCVT_S32_F32_X4 : SInst<"svcvt_s32[_{d}_x4]", "4.x4.d", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming], []>;
def SVCVT_F32_U32_X4 : SInst<"svcvt_{d}[_u32_x4]", "4.d4.u", "f", MergeNone, "aarch64_sve_ucvtf_x4", [IsStreaming], []>;
def SVCVT_U32_F32_X4 : SInst<"svcvt_u32[_{d}_x4]", "4.u4.d", "f", MergeNone, "aarch64_sve_fcvtu_x4", [IsStreaming], []>;
def SVCVT_F32_S32_X4 : SInst<"svcvt_{d}[_s32_x4]", "4.d4.x", "f", MergeNone, "aarch64_sve_scvtf_x4", [IsStreaming], []>;
def SVCVT_S32_F32_X4 : SInst<"svcvt_s32[_{d}_x4]", "4.x4.d", "f", MergeNone, "aarch64_sve_fcvts_x4", [IsStreaming], []>;
}

//
Expand Down
28 changes: 17 additions & 11 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -773,6 +773,8 @@ def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">,
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>,
HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. "
"Clang will use the GCC installation with the largest version">;
def gcc_triple_EQ : Joined<["--"], "gcc-triple=">,
HelpText<"Search for the GCC installation with the specified triple.">;
def CC : Flag<["-"], "CC">, Visibility<[ClangOption, CC1Option]>,
Group<Preprocessor_Group>,
HelpText<"Include comments from within macros in preprocessed output">,
Expand Down Expand Up @@ -4265,7 +4267,7 @@ def iquote : JoinedOrSeparate<["-"], "iquote">, Group<clang_i_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Add directory to QUOTE include search path">, MetaVarName<"<directory>">;
def isysroot : JoinedOrSeparate<["-"], "isysroot">, Group<clang_i_Group>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption]>,
HelpText<"Set the system root directory (usually /)">, MetaVarName<"<dir>">,
MarshallingInfoString<HeaderSearchOpts<"Sysroot">, [{"/"}]>;
def isystem : JoinedOrSeparate<["-"], "isystem">, Group<clang_i_Group>,
Expand Down Expand Up @@ -4390,8 +4392,8 @@ def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<TargetOpts<"CodeModel">, [{"default"}]>;
def mlarge_data_threshold_EQ : Joined<["-"], "mlarge-data-threshold=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "65535">;
Flags<[TargetSpecific]>, Visibility<[ClangOption, CC1Option]>,
MarshallingInfoInt<TargetOpts<"LargeDataThreshold">, "0">;
def mtls_size_EQ : Joined<["-"], "mtls-size=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Specify bit size of immediate TLS offsets (AArch64 ELF only): "
Expand Down Expand Up @@ -4583,11 +4585,13 @@ let Flags = [TargetSpecific] in {
def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
HelpText<"Enable use of experimental RISC-V extensions.">;
def mrvv_vector_bits_EQ : Joined<["-"], "mrvv-vector-bits=">, Group<m_Group>,
HelpText<"Specify the size in bits of an RVV vector register. Defaults to "
"the vector length agnostic value of \"scalable\". Accepts power of "
"2 values between 64 and 65536. Also accepts \"zvl\" "
"to use the value implied by -march/-mcpu. Value will be reflected "
"in __riscv_v_fixed_vlen preprocessor define (RISC-V only)">;
Visibility<[ClangOption, FlangOption]>,
HelpText<"Specify the size in bits of an RVV vector register">,
DocBrief<"Defaults to the vector length agnostic value of \"scalable\". "
"Accepts power of 2 values between 64 and 65536. Also accepts "
"\"zvl\" to use the value implied by -march/-mcpu. On Clang, value "
"will be reflected in __riscv_v_fixed_vlen preprocessor define "
"(RISC-V only)">;

def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_Group>,
HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64/LoongArch/RISC-V only)">;
Expand Down Expand Up @@ -5195,12 +5199,12 @@ def nohipwrapperinc : Flag<["-"], "nohipwrapperinc">, Group<IncludePath_Group>,
HelpText<"Do not include the default HIP wrapper headers and include paths">;
def : Flag<["-"], "nocudainc">, Alias<nogpuinc>;
def nogpulib : Flag<["-"], "nogpulib">, MarshallingInfoFlag<LangOpts<"NoGPULib">>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Do not link device library for CUDA/HIP device compilation">;
def : Flag<["-"], "nocudalib">, Alias<nogpulib>;
def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option]>,
def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Link the LLVM C Library for GPUs">;
def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option]>;
def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>;
def nodefaultlibs : Flag<["-"], "nodefaultlibs">;
def nodriverkitlib : Flag<["-"], "nodriverkitlib">;
def nofixprebinding : Flag<["-"], "nofixprebinding">;
Expand Down Expand Up @@ -7013,6 +7017,8 @@ def mbranch_target_enforce : Flag<["-"], "mbranch-target-enforce">,
MarshallingInfoFlag<LangOpts<"BranchTargetEnforcement">>;
def mbranch_protection_pauth_lr : Flag<["-"], "mbranch-protection-pauth-lr">,
MarshallingInfoFlag<LangOpts<"BranchProtectionPAuthLR">>;
def mguarded_control_stack : Flag<["-"], "mguarded-control-stack">,
MarshallingInfoFlag<LangOpts<"GuardedControlStack">>;
def fno_dllexport_inlines : Flag<["-"], "fno-dllexport-inlines">,
MarshallingInfoNegativeFlag<LangOpts<"DllExportInlines">>;
def cfguard_no_checks : Flag<["-"], "cfguard-no-checks">,
Expand Down
7 changes: 6 additions & 1 deletion clang/include/clang/Format/.clang-format
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
BasedOnStyle: clang-format
BasedOnStyle: LLVM
InsertBraces: true
InsertNewlineAtEOF: true
LineEnding: LF
RemoveBracesLLVM: true
RemoveParentheses: ReturnStatement
21 changes: 20 additions & 1 deletion clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,22 @@ struct FormatStyle {
/// bbb = 2;
/// \endcode
bool AlignCompound;
/// Only for ``AlignConsecutiveDeclarations``. Whether function pointers are
/// aligned.
/// \code
/// true:
/// unsigned i;
/// int &r;
/// int *p;
/// int (*f)();
///
/// false:
/// unsigned i;
/// int &r;
/// int *p;
/// int (*f)();
/// \endcode
bool AlignFunctionPointers;
/// Only for ``AlignConsecutiveAssignments``. Whether short assignment
/// operators are left-padded to the same length as long ones in order to
/// put all assignment operators to the right of the left hand side.
Expand All @@ -247,7 +263,9 @@ struct FormatStyle {
bool operator==(const AlignConsecutiveStyle &R) const {
return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
AcrossComments == R.AcrossComments &&
AlignCompound == R.AlignCompound && PadOperators == R.PadOperators;
AlignCompound == R.AlignCompound &&
AlignFunctionPointers == R.AlignFunctionPointers &&
PadOperators == R.PadOperators;
}
bool operator!=(const AlignConsecutiveStyle &R) const {
return !(*this == R);
Expand Down Expand Up @@ -3037,6 +3055,7 @@ struct FormatStyle {
bool isProto() const {
return Language == LK_Proto || Language == LK_TextProto;
}
bool isTableGen() const { return Language == LK_TableGen; }

/// Language, this format style is targeted at.
/// \version 3.5
Expand Down
35 changes: 33 additions & 2 deletions clang/include/clang/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_PARSE_PARSER_H
#define LLVM_CLANG_PARSE_PARSER_H

#include "clang/Basic/OpenACCKinds.h"
#include "clang/Basic/OperatorPrecedence.h"
#include "clang/Lex/CodeCompletionHandler.h"
#include "clang/Lex/Preprocessor.h"
Expand Down Expand Up @@ -234,6 +235,26 @@ class Parser : public CodeCompletionHandler {
/// Parsing OpenACC directive mode.
bool OpenACCDirectiveParsing = false;

/// Currently parsing a situation where an OpenACC array section could be
/// legal, such as a 'var-list'.
bool AllowOpenACCArraySections = false;

/// RAII object to set reset OpenACC parsing a context where Array Sections
/// are allowed.
class OpenACCArraySectionRAII {
Parser &P;

public:
OpenACCArraySectionRAII(Parser &P) : P(P) {
assert(!P.AllowOpenACCArraySections);
P.AllowOpenACCArraySections = true;
}
~OpenACCArraySectionRAII() {
assert(P.AllowOpenACCArraySections);
P.AllowOpenACCArraySections = false;
}
};

/// When true, we are directly inside an Objective-C message
/// send expression.
///
Expand Down Expand Up @@ -3546,8 +3567,18 @@ class Parser : public CodeCompletionHandler {
ExprResult ParseOpenACCIDExpression();
/// Parses the variable list for the `cache` construct.
void ParseOpenACCCacheVarList();
/// Parses a single variable in a variable list for the 'cache' construct.
bool ParseOpenACCCacheVar();
/// Parses a single variable in a variable list for OpenACC.
bool ParseOpenACCVar();
/// Parses the variable list for the variety of clauses that take a var-list,
/// including the optional Special Token listed for some,based on clause type.
bool ParseOpenACCClauseVarList(OpenACCClauseKind Kind);
/// Parses any parameters for an OpenACC Clause, including required/optional
/// parens.
bool ParseOpenACCClauseParams(OpenACCClauseKind Kind);
/// Parses a single clause in a clause-list for OpenACC.
bool ParseOpenACCClause();
/// Parses the clause-list for an OpenACC directive.
void ParseOpenACCClauseList();
bool ParseOpenACCWaitArgument();

private:
Expand Down
12 changes: 9 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -4799,6 +4799,8 @@ class Sema final {
bool CheckAlwaysInlineAttr(const Stmt *OrigSt, const Stmt *CurSt,
const AttributeCommonInfo &A);

bool CheckCountedByAttr(Scope *Scope, const FieldDecl *FD);

/// Adjust the calling convention of a method to be the ABI default if it
/// wasn't specified explicitly. This handles method types formed from
/// function type typedefs and typename template arguments.
Expand Down Expand Up @@ -5642,6 +5644,7 @@ class Sema final {
CorrectionCandidateCallback &CCC,
TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr,
ArrayRef<Expr *> Args = std::nullopt,
DeclContext *LookupCtx = nullptr,
TypoExpr **Out = nullptr);

DeclResult LookupIvarInObjCMethod(LookupResult &Lookup, Scope *S,
Expand Down Expand Up @@ -11346,9 +11349,12 @@ class Sema final {
/// rigorous semantic checking in the new mapped directives.
bool mapLoopConstruct(llvm::SmallVector<OMPClause *> &ClausesWithoutBind,
ArrayRef<OMPClause *> Clauses,
OpenMPBindClauseKind BindKind,
OpenMPBindClauseKind &BindKind,
OpenMPDirectiveKind &Kind,
OpenMPDirectiveKind &PrevMappedDirective);
OpenMPDirectiveKind &PrevMappedDirective,
SourceLocation StartLoc, SourceLocation EndLoc,
const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion);

public:
/// The declarator \p D defines a function in the scope \p S which is nested
Expand Down Expand Up @@ -12969,7 +12975,7 @@ class Sema final {
QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS,
SourceLocation QuestionLoc);

bool DiagnoseConditionalForNull(Expr *LHSExpr, Expr *RHSExpr,
bool DiagnoseConditionalForNull(const Expr *LHSExpr, const Expr *RHSExpr,
SourceLocation QuestionLoc);

void DiagnoseAlwaysNonNullPointer(Expr *E,
Expand Down
12 changes: 8 additions & 4 deletions clang/include/clang/Sema/TypoCorrection.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class CorrectionCandidateCallback {
public:
static const unsigned InvalidDistance = TypoCorrection::InvalidDistance;

explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr,
explicit CorrectionCandidateCallback(const IdentifierInfo *Typo = nullptr,
NestedNameSpecifier *TypoNNS = nullptr)
: Typo(Typo), TypoNNS(TypoNNS) {}

Expand Down Expand Up @@ -319,7 +319,7 @@ class CorrectionCandidateCallback {
/// this method.
virtual std::unique_ptr<CorrectionCandidateCallback> clone() = 0;

void setTypoName(IdentifierInfo *II) { Typo = II; }
void setTypoName(const IdentifierInfo *II) { Typo = II; }
void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; }

// Flags for context-dependent keywords. WantFunctionLikeCasts is only
Expand All @@ -345,13 +345,13 @@ class CorrectionCandidateCallback {
candidate.getCorrectionSpecifier() == TypoNNS;
}

IdentifierInfo *Typo;
const IdentifierInfo *Typo;
NestedNameSpecifier *TypoNNS;
};

class DefaultFilterCCC final : public CorrectionCandidateCallback {
public:
explicit DefaultFilterCCC(IdentifierInfo *Typo = nullptr,
explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr,
NestedNameSpecifier *TypoNNS = nullptr)
: CorrectionCandidateCallback(Typo, TypoNNS) {}

Expand All @@ -365,6 +365,10 @@ class DefaultFilterCCC final : public CorrectionCandidateCallback {
template <class C>
class DeclFilterCCC final : public CorrectionCandidateCallback {
public:
explicit DeclFilterCCC(const IdentifierInfo *Typo = nullptr,
NestedNameSpecifier *TypoNNS = nullptr)
: CorrectionCandidateCallback(Typo, TypoNNS) {}

bool ValidateCandidate(const TypoCorrection &candidate) override {
return candidate.getCorrectionDeclAs<C>();
}
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,13 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping);
InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator);
}
// Placeholder type for OpenACC array sections.
if (LangOpts.OpenACC) {
// FIXME: Once we implement OpenACC array sections in Sema, this will either
// be combined with the OpenMP type, or given its own type. In the meantime,
// just use the OpenMP type so that parsing can work.
InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
}
if (LangOpts.MatrixTypes)
InitBuiltinType(IncompleteMatrixIdxTy, BuiltinType::IncompleteMatrixIdx);

Expand Down
71 changes: 48 additions & 23 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2034,23 +2034,25 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
return ToDCOrErr.takeError();
}

DeclContext *ToDC = *ToDCOrErr;
// Remove all declarations, which may be in wrong order in the
// lexical DeclContext and then add them in the proper order.
for (auto *D : FromDC->decls()) {
if (!MightNeedReordering(D))
continue;
if (const auto *FromRD = dyn_cast<RecordDecl>(FromDC)) {
DeclContext *ToDC = *ToDCOrErr;
// Remove all declarations, which may be in wrong order in the
// lexical DeclContext and then add them in the proper order.
for (auto *D : FromRD->decls()) {
if (!MightNeedReordering(D))
continue;

assert(D && "DC contains a null decl");
if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) {
// Remove only the decls which we successfully imported.
assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD));
// Remove the decl from its wrong place in the linked list.
ToDC->removeDecl(ToD);
// Add the decl to the end of the linked list.
// This time it will be at the proper place because the enclosing for
// loop iterates in the original (good) order of the decls.
ToDC->addDeclInternal(ToD);
assert(D && "DC contains a null decl");
if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) {
// Remove only the decls which we successfully imported.
assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD));
// Remove the decl from its wrong place in the linked list.
ToDC->removeDecl(ToD);
// Add the decl to the end of the linked list.
// This time it will be at the proper place because the enclosing for
// loop iterates in the original (good) order of the decls.
ToDC->addDeclInternal(ToD);
}
}
}

Expand Down Expand Up @@ -5927,15 +5929,22 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (ToD)
return ToD;

bool IsFriendTemplate = D->getFriendObjectKind() != Decl::FOK_None;
bool IsDependentContext = DC != LexicalDC ? LexicalDC->isDependentContext()
: DC->isDependentContext();
bool DependentFriend = IsFriendTemplate && IsDependentContext;
// Should check if a declaration is friend in a dependent context.
// Such templates are not linked together in a declaration chain.
// The ASTImporter strategy is to map existing forward declarations to
// imported ones only if strictly necessary, otherwise import these as new
// forward declarations. In case of the "dependent friend" declarations, new
// declarations are created, but not linked in a declaration chain.
auto IsDependentFriend = [](ClassTemplateDecl *TD) {
return TD->getFriendObjectKind() != Decl::FOK_None &&
TD->getLexicalDeclContext()->isDependentContext();
};
bool DependentFriend = IsDependentFriend(D);

ClassTemplateDecl *FoundByLookup = nullptr;

// We may already have a template of the same name; try to find and match it.
if (!DependentFriend && !DC->isFunctionOrMethod()) {
if (!DC->isFunctionOrMethod()) {
SmallVector<NamedDecl *, 4> ConflictingDecls;
auto FoundDecls = Importer.findDeclsInToCtx(DC, Name);
for (auto *FoundDecl : FoundDecls) {
Expand All @@ -5951,10 +5960,13 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) {

// FIXME: sufficient conditon for 'IgnoreTemplateParmDepth'?
bool IgnoreTemplateParmDepth =
FoundTemplate->getFriendObjectKind() != Decl::FOK_None &&
!D->specializations().empty();
(FoundTemplate->getFriendObjectKind() != Decl::FOK_None) !=
(D->getFriendObjectKind() != Decl::FOK_None);
if (IsStructuralMatch(D, FoundTemplate, /*Complain=*/true,
IgnoreTemplateParmDepth)) {
if (DependentFriend || IsDependentFriend(FoundTemplate))
continue;

ClassTemplateDecl *TemplateWithDef =
getTemplateDefinition(FoundTemplate);
if (D->isThisDeclarationADefinition() && TemplateWithDef)
Expand Down Expand Up @@ -9028,6 +9040,10 @@ class AttrImporter {
public:
AttrImporter(ASTImporter &I) : Importer(I), NImporter(I) {}

// Useful for accessing the imported attribute.
template <typename T> T *castAttrAs() { return cast<T>(ToAttr); }
template <typename T> const T *castAttrAs() const { return cast<T>(ToAttr); }

// Create an "importer" for an attribute parameter.
// Result of the 'value()' of that object is to be passed to the function
// 'importAttr', in the order that is expected by the attribute class.
Expand Down Expand Up @@ -9241,6 +9257,15 @@ Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
From->args_size());
break;
}
case attr::CountedBy: {
AI.cloneAttr(FromAttr);
const auto *CBA = cast<CountedByAttr>(FromAttr);
Expected<SourceRange> SR = Import(CBA->getCountedByFieldLoc()).get();
if (!SR)
return SR.takeError();
AI.castAttrAs<CountedByAttr>()->setCountedByFieldLoc(SR.get());
break;
}

default: {
// The default branch works for attributes that have no arguments to import.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2835,7 +2835,7 @@ CharUnits VarDecl::getFlexibleArrayInitChars(const ASTContext &Ctx) const {
if (!Ty || !Ty->getDecl()->hasFlexibleArrayMember())
return CharUnits::Zero();
auto *List = dyn_cast<InitListExpr>(getInit()->IgnoreParens());
if (!List)
if (!List || List->getNumInits() == 0)
return CharUnits::Zero();
const Expr *FlexibleInit = List->getInit(List->getNumInits() - 1);
auto InitTy = Ctx.getAsConstantArrayType(FlexibleInit->getType());
Expand Down
Loading