8 changes: 5 additions & 3 deletions bolt/lib/Rewrite/JITLinkLinker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext {
jitlink::AsyncLookupResult AllResults;

for (const auto &Symbol : Symbols) {
std::string SymName = Symbol.first.str();
std::string SymName = (*Symbol.first).str();
LLVM_DEBUG(dbgs() << "BOLT: looking for " << SymName << "\n");

if (auto Address = Linker.lookupSymbol(SymName)) {
Expand Down Expand Up @@ -167,7 +167,9 @@ struct JITLinkLinker::Context : jitlink::JITLinkContext {
Error notifyResolved(jitlink::LinkGraph &G) override {
for (auto *Symbol : G.defined_symbols()) {
SymbolInfo Info{Symbol->getAddress().getValue(), Symbol->getSize()};
Linker.Symtab.insert({Symbol->getName().str(), Info});
auto Name =
Symbol->hasName() ? (*Symbol->getName()).str() : std::string();
Linker.Symtab.insert({std::move(Name), Info});
}

return Error::success();
Expand All @@ -189,7 +191,7 @@ JITLinkLinker::~JITLinkLinker() { cantFail(MM->deallocate(std::move(Allocs))); }

void JITLinkLinker::loadObject(MemoryBufferRef Obj,
SectionsMapper MapSections) {
auto LG = jitlink::createLinkGraphFromObject(Obj);
auto LG = jitlink::createLinkGraphFromObject(Obj, BC.getSymbolStringPool());
if (auto E = LG.takeError()) {
errs() << "BOLT-ERROR: JITLink failed: " << E << '\n';
exit(1);
Expand Down
3 changes: 2 additions & 1 deletion bolt/lib/Rewrite/MachORewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ MachORewriteInstance::MachORewriteInstance(object::MachOObjectFile *InputFile,
ErrorAsOutParameter EAO(&Err);
Relocation::Arch = InputFile->makeTriple().getArch();
auto BCOrErr = BinaryContext::createBinaryContext(
InputFile->makeTriple(), InputFile->getFileName(), nullptr,
InputFile->makeTriple(), std::make_shared<orc::SymbolStringPool>(),
InputFile->getFileName(), nullptr,
/* IsPIC */ true, DWARFContext::create(*InputFile),
{llvm::outs(), llvm::errs()});
if (Error E = BCOrErr.takeError()) {
Expand Down
3 changes: 2 additions & 1 deletion bolt/lib/Rewrite/RewriteInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,8 @@ RewriteInstance::RewriteInstance(ELFObjectFileBase *File, const int Argc,

Relocation::Arch = TheTriple.getArch();
auto BCOrErr = BinaryContext::createBinaryContext(
TheTriple, File->getFileName(), Features.get(), IsPIC,
TheTriple, std::make_shared<orc::SymbolStringPool>(), File->getFileName(),
Features.get(), IsPIC,
DWARFContext::create(*File, DWARFContext::ProcessDebugRelocations::Ignore,
nullptr, opts::DWPPathName,
WithColor::defaultErrorHandler,
Expand Down
496 changes: 496 additions & 0 deletions bolt/test/X86/dwarf5-debug-names-union.test

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions bolt/unittests/Core/BinaryContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ struct BinaryContextTester : public testing::TestWithParam<Triple::ArchType> {
void initializeBOLT() {
Relocation::Arch = ObjFile->makeTriple().getArch();
BC = cantFail(BinaryContext::createBinaryContext(
ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true,
ObjFile->makeTriple(), std::make_shared<orc::SymbolStringPool>(),
ObjFile->getFileName(), nullptr, true,
DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()}));
ASSERT_FALSE(!BC);
}
Expand Down Expand Up @@ -216,4 +217,4 @@ TEST_P(BinaryContextTester, BaseAddressSegmentsSmallerThanAlignment) {
BC->getBaseAddressForMapping(0xaaaaaaab1000, 0x1000);
ASSERT_TRUE(BaseAddress.has_value());
ASSERT_EQ(*BaseAddress, 0xaaaaaaaa0000ULL);
}
}
3 changes: 2 additions & 1 deletion bolt/unittests/Core/MCPlusBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ struct MCPlusBuilderTester : public testing::TestWithParam<Triple::ArchType> {
void initializeBolt() {
Relocation::Arch = ObjFile->makeTriple().getArch();
BC = cantFail(BinaryContext::createBinaryContext(
ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true,
ObjFile->makeTriple(), std::make_shared<orc::SymbolStringPool>(),
ObjFile->getFileName(), nullptr, true,
DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()}));
ASSERT_FALSE(!BC);
BC->initializeTarget(std::unique_ptr<MCPlusBuilder>(
Expand Down
3 changes: 2 additions & 1 deletion bolt/unittests/Core/MemoryMaps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ struct MemoryMapsTester : public testing::TestWithParam<Triple::ArchType> {
void initializeBOLT() {
Relocation::Arch = ObjFile->makeTriple().getArch();
BC = cantFail(BinaryContext::createBinaryContext(
ObjFile->makeTriple(), ObjFile->getFileName(), nullptr, true,
ObjFile->makeTriple(), std::make_shared<orc::SymbolStringPool>(),
ObjFile->getFileName(), nullptr, true,
DWARFContext::create(*ObjFile.get()), {llvm::outs(), llvm::errs()}));
ASSERT_FALSE(!BC);
}
Expand Down
24 changes: 12 additions & 12 deletions clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
#include "clang/Analysis/CallGraph.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/SmallVector.h"

using namespace clang::ast_matchers;
using clang::ast_matchers::internal::Matcher;
using clang::tidy::utils::hasPtrOrReferenceInFunc;

namespace clang {
namespace ast_matchers {
namespace tidy::bugprone {

namespace {
/// matches a Decl if it has a "no return" attribute of any kind
AST_MATCHER(Decl, declHasNoReturnAttr) {
return Node.hasAttr<NoReturnAttr>() || Node.hasAttr<CXX11NoReturnAttr>() ||
Expand All @@ -30,23 +32,21 @@ AST_MATCHER(Decl, declHasNoReturnAttr) {
AST_MATCHER(FunctionType, typeHasNoReturnAttr) {
return Node.getNoReturnAttr();
}
} // namespace ast_matchers
namespace tidy::bugprone {
} // namespace

static internal::Matcher<Stmt>
loopEndingStmt(internal::Matcher<Stmt> Internal) {
internal::Matcher<QualType> isNoReturnFunType =
static Matcher<Stmt> loopEndingStmt(Matcher<Stmt> Internal) {
Matcher<QualType> IsNoReturnFunType =
ignoringParens(functionType(typeHasNoReturnAttr()));
internal::Matcher<Decl> isNoReturnDecl =
anyOf(declHasNoReturnAttr(), functionDecl(hasType(isNoReturnFunType)),
varDecl(hasType(blockPointerType(pointee(isNoReturnFunType)))));
Matcher<Decl> IsNoReturnDecl =
anyOf(declHasNoReturnAttr(), functionDecl(hasType(IsNoReturnFunType)),
varDecl(hasType(blockPointerType(pointee(IsNoReturnFunType)))));

return stmt(anyOf(
mapAnyOf(breakStmt, returnStmt, gotoStmt, cxxThrowExpr).with(Internal),
callExpr(Internal,
callee(mapAnyOf(functionDecl, /* block callee */ varDecl)
.with(isNoReturnDecl))),
objcMessageExpr(Internal, callee(isNoReturnDecl))));
.with(IsNoReturnDecl))),
objcMessageExpr(Internal, callee(IsNoReturnDecl))));
}

/// Return whether `Var` was changed in `LoopStmt`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,20 @@ void ReturnConstRefFromParameterCheck::registerMatchers(MatchFinder *Finder) {
qualType(lValueReferenceType(pointee(
qualType(isConstQualified()))))
.bind("type"))),
hasDeclContext(functionDecl().bind("owner")),
hasDeclContext(functionDecl(
equalsBoundNode("func"),
hasReturnTypeLoc(loc(qualType(
hasCanonicalType(equalsBoundNode("type"))))))),
unless(hasLifetimeBoundAttr()))
.bind("param")))
.bind("dref"));
const auto Func =
functionDecl(equalsBoundNode("owner"),
hasReturnTypeLoc(loc(
qualType(hasCanonicalType(equalsBoundNode("type"))))))
.bind("func");

Finder->addMatcher(returnStmt(hasReturnValue(DRef), hasAncestor(Func)), this);
Finder->addMatcher(
returnStmt(hasReturnValue(ignoringParens(conditionalOperator(
eachOf(hasTrueExpression(DRef), hasFalseExpression(DRef)),
hasAncestor(Func))))),
returnStmt(
hasAncestor(functionDecl().bind("func")),
hasReturnValue(anyOf(
DRef, ignoringParens(conditionalOperator(eachOf(
hasTrueExpression(DRef), hasFalseExpression(DRef))))))),
this);
}

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

SourceManager SourceMgr(*Diags, FileMgr);

HeaderSearch HeaderInfo(HSOpts, SourceMgr, *Diags, LangOpts,
HeaderSearch HeaderInfo(std::move(HSOpts), SourceMgr, *Diags, LangOpts,
/*Target=*/nullptr);

TrivialModuleLoader ModuleLoader;
Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/clangd/unittests/XRefsTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,15 @@ TEST(LocateSymbol, All) {
void *Value;
void *getPointer() const { return Info::get^Pointer(Value); }
};
)cpp",
R"cpp(// Deducing this
struct S {
int bar(this S&);
};
void foo() {
S [[waldo]];
int x = wa^ldo.bar();
}
)cpp"};
for (const char *Test : Tests) {
Annotations T(Test);
Expand All @@ -1035,6 +1044,7 @@ TEST(LocateSymbol, All) {
TU.Code = std::string(T.code());

TU.ExtraArgs.push_back("-xobjective-c++");
TU.ExtraArgs.push_back("-std=c++23");

auto AST = TU.build();
auto Results = locateSymbolAt(AST, T.point());
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ Changes in existing checks
- Improved :doc:`bugprone-return-const-ref-from-parameter
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check to
diagnose potential dangling references when returning a ``const &`` parameter
by using the conditional operator ``cond ? var1 : var2`` and no longer giving
false positives for functions which contain lambda and ignore parameters
by using the conditional operator ``cond ? var1 : var2`` and fixing false
positives for functions which contain lambda and ignore parameters
with ``[[clang::lifetimebound]]`` attribute.

- Improved :doc:`bugprone-sizeof-expression
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,3 +203,26 @@ namespace use_lifetime_bound_attr {
int const &f(int const &a [[clang::lifetimebound]]) { return a; }
} // namespace use_lifetime_bound_attr
} // namespace gh117696


namespace lambda {
using T = const int &;
using K = const float &;
T inner_valid_lambda(T a) {
[&]() -> T { return a; };
return a;
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter
}
T inner_invalid_lambda(T a) {
[&](T a) -> T { return a; };
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: returning a constant reference parameter
return a;
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter
}
T inner_invalid_lambda2(T a) {
[&](K a) -> K { return a; };
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: returning a constant reference parameter
return a;
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: returning a constant reference parameter
}
} // namespace lambda
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing
// RUN: %check_clang_tidy %s misc-redundant-expression %t -- -- -fno-delayed-template-parsing -Wno-array-compare-cxx26

typedef __INT64_TYPE__ I64;

Expand Down
7 changes: 4 additions & 3 deletions clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,15 @@ A **partial** list of flags RealtimeSanitizer respects:
* - ``abort_on_error``
- OS dependent
- boolean
- If true, the tool calls abort() instead of _exit() after printing the error report. On some OSes (OSX, for exmple) this is beneficial because a better stack trace is emitted on crash.
- If true, the tool calls ``abort()`` instead of ``_exit()`` after printing the error report. On some OSes (MacOS, for exmple) this is beneficial because a better stack trace is emitted on crash.
* - ``symbolize``
- ``true``
- boolean
- If set, use the symbolizer to turn virtual addresses to file/line locations. If false, can greatly speed up the error reporting.
* - ``suppressions``
- ""
- ``""``
- path
- If set to a valid suppressions file, will suppress issue reporting. See details in "Disabling", below.
- If set to a valid suppressions file, will suppress issue reporting. See details in `Disabling and Suppressing`_.


Some issues with flags can be debugged using the ``verbosity=$NUM`` flag:
Expand Down Expand Up @@ -244,6 +244,7 @@ To register a callback which will be invoked before a RTSan kills the process:
...
}
.. _disabling-and-suppressing:

Disabling and suppressing
-------------------------
Expand Down
7 changes: 6 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,9 @@ New Compiler Flags
- The ``-Warray-compare`` warning has been added to warn about array comparison
on versions older than C++20.

- The ``-Warray-compare-cxx26`` warning has been added to warn about array comparison
starting from C++26, this warning is enabled as an error by default.

Deprecated Compiler Flags
-------------------------

Expand Down Expand Up @@ -677,6 +680,9 @@ Bug Fixes in This Version
- Fixed a crash when GNU statement expression contains invalid statement (#GH113468).
- Fixed a failed assertion when using ``__attribute__((noderef))`` on an
``_Atomic``-qualified type (#GH116124).
- No longer return ``false`` for ``noexcept`` expressions involving a
``delete`` which resolves to a destroying delete but the type of the object
being deleted has a potentially throwing destructor (#GH118660).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -793,7 +799,6 @@ Bug Fixes to C++ Support
- Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205)
- Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda
captures at the end of a full expression. (#GH115931)
- Clang no longer rejects deleting a pointer of incomplete enumeration type. (#GH99278)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
10 changes: 10 additions & 0 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,16 @@ In this way, the user may only need to specify a root configuration file with
-L <CFGDIR>/lib
-T <CFGDIR>/ldscripts/link.ld

Usually, config file options are placed before command-line options, regardless
of the actual operation to be performed. The exception is being made for the
options prefixed with the ``$`` character. These will be used only when linker
is being invoked, and added after all of the command-line specified linker
inputs. Here is some example of ``$``-prefixed options:

::
$-Wl,-Bstatic $-lm
$-Wl,-Bshared

Language and Target-Independent Features
========================================

Expand Down
25 changes: 25 additions & 0 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3438,6 +3438,31 @@ alpha.WebKit
.. _alpha-webkit-NoUncheckedPtrMemberChecker:
alpha.webkit.MemoryUnsafeCastChecker
""""""""""""""""""""""""""""""""""""""
Check for all casts from a base type to its derived type as these might be memory-unsafe.
Example:
.. code-block:: cpp
class Base { };
class Derived : public Base { };
void f(Base* base) {
Derived* derived = static_cast<Derived*>(base); // ERROR
}
For all cast operations (C-style casts, static_cast, reinterpret_cast, dynamic_cast), if the source type a `Base*` and the destination type is `Derived*`, where `Derived` inherits from `Base`, the static analyzer should signal an error.
This applies to:
- C structs, C++ structs and classes, and Objective-C classes and protocols.
- Pointers and references.
- Inside template instantiations and macro expansions that are visible to the compiler.
For types like this, instead of using built in casts, the programmer will use helper functions that internally perform the appropriate type check and disable static analysis.
alpha.webkit.NoUncheckedPtrMemberChecker
""""""""""""""""""""""""""""""""""""""""
Raw pointers and references to an object which supports CheckedPtr or CheckedRef can't be used as class members. Only CheckedPtr, CheckedRef, RefPtr, or Ref are allowed.
Expand Down
11 changes: 10 additions & 1 deletion clang/docs/tools/dump_format_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# A tool to parse the output of `clang-format --help` and update the
# documentation in ../ClangFormat.rst automatically.

import argparse
import os
import re
import subprocess
Expand All @@ -26,7 +27,7 @@ def indent(text, columns, indent_first_line=True):


def get_help_output():
args = ["clang-format", "--help"]
args = [binary, "--help"]
cmd = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = cmd.communicate()
out = out.decode(sys.stdout.encoding)
Expand Down Expand Up @@ -54,6 +55,14 @@ def validate(text, columns):
print("warning: line too long:\n", line, file=sys.stderr)


p = argparse.ArgumentParser()
p.add_argument("-d", "--directory", help="directory of clang-format")
opts = p.parse_args()

binary = "clang-format"
if opts.directory:
binary = opts.directory + "/" + binary

help_text = get_help_text()
validate(help_text, 100)

Expand Down
2 changes: 1 addition & 1 deletion clang/docs/tools/dump_format_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
PLURALS_FILE = os.path.join(os.path.dirname(__file__), "plurals.txt")

plurals: Set[str] = set()
with open(PLURALS_FILE, "a+") as f:
with open(PLURALS_FILE) as f:
f.seek(0)
plurals = set(f.read().splitlines())

Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Basic/Diagnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,8 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
ArgToStringFnTy ArgToStringFn;

/// Whether the diagnostic should be suppressed in FilePath.
llvm::unique_function<bool(diag::kind, StringRef /*FilePath*/) const>
llvm::unique_function<bool(diag::kind, SourceLocation /*DiagLoc*/,
const SourceManager &) const>
DiagSuppressionMapping;

public:
Expand Down Expand Up @@ -972,7 +973,7 @@ class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
/// These take presumed locations into account, and can still be overriden by
/// clang-diagnostics pragmas.
void setDiagSuppressionMapping(llvm::MemoryBuffer &Input);
bool isSuppressedViaMapping(diag::kind DiagId, StringRef FilePath) const;
bool isSuppressedViaMapping(diag::kind DiagId, SourceLocation DiagLoc) const;

/// Issue the message to the client.
///
Expand Down
15 changes: 10 additions & 5 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10274,6 +10274,11 @@ def warn_array_comparison : Warning<
"to compare array addresses, use unary '+' to decay operands to pointers">,
InGroup<DiagGroup<"array-compare">>;

def warn_array_comparison_cxx26 : Warning<
"comparison between two arrays is ill-formed in C++26; "
"to compare array addresses, use unary '+' to decay operands to pointers">,
InGroup<DiagGroup<"array-compare-cxx26">>, DefaultError;

def warn_stringcompare : Warning<
"result of comparison against %select{a string literal|@encode}0 is "
"unspecified (use an explicit string comparison function instead)">,
Expand Down Expand Up @@ -12762,12 +12767,12 @@ def err_acc_gang_dim_value
: Error<"argument to 'gang' clause dimension must be %select{a constant "
"expression|1, 2, or 3: evaluated to %1}0">;
def err_acc_num_arg_conflict
: Error<"'num' argument to '%0' clause not allowed on a '%1' "
"construct%select{| associated with a '%3' construct}2 that has a "
"'%4' clause">;
: Error<"'%0' argument to '%1' clause not allowed on a '%2' "
"construct%select{| associated with a '%4' construct}3 that has a "
"'%5' clause">;
def err_acc_num_arg_conflict_reverse
: Error<"'num_gangs' clause not allowed on a 'kernels loop' construct that "
"has a 'gang' clause with a 'num' argument">;
: Error<"'%0' clause not allowed on a 'kernels loop' construct that "
"has a '%1' clause with a%select{n| 'num'}2 argument">;
def err_acc_clause_in_clause_region
: Error<"loop with a '%0' clause may not exist in the region of a '%1' "
"clause%select{| on a '%3' construct}2">;
Expand Down
10 changes: 5 additions & 5 deletions clang/include/clang/Basic/arm_mve.td
Original file line number Diff line number Diff line change
Expand Up @@ -1270,13 +1270,13 @@ defm sqrshr: ScalarSaturatingShiftReg<s32, s64>;
def lsll: LongScalarShift<u64, (args s32:$sh), (IRInt<"lsll"> $lo, $hi, $sh)>;
def asrl: LongScalarShift<s64, (args s32:$sh), (IRInt<"asrl"> $lo, $hi, $sh)>;

multiclass vadcsbc {
multiclass vadcsbc<dag initial_carry_in> {
def q: Intrinsic<Vector, (args Vector:$a, Vector:$b, Ptr<uint>:$carry),
(seq (IRInt<NAME, [Vector]> $a, $b, (shl (load $carry), 29)):$pair,
(store (and 1, (lshr (xval $pair, 1), 29)), $carry),
(xval $pair, 0))>;
def iq: Intrinsic<Vector, (args Vector:$a, Vector:$b, Ptr<uint>:$carry),
(seq (IRInt<NAME, [Vector]> $a, $b, 0):$pair,
(seq (IRInt<NAME, [Vector]> $a, $b, initial_carry_in):$pair,
(store (and 1, (lshr (xval $pair, 1), 29)), $carry),
(xval $pair, 0))>;
def q_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b,
Expand All @@ -1288,13 +1288,13 @@ multiclass vadcsbc {
def iq_m: Intrinsic<Vector, (args Vector:$inactive, Vector:$a, Vector:$b,
Ptr<uint>:$carry, Predicate:$pred),
(seq (IRInt<NAME # "_predicated", [Vector, Predicate]> $inactive, $a, $b,
0, $pred):$pair,
initial_carry_in, $pred):$pair,
(store (and 1, (lshr (xval $pair, 1), 29)), $carry),
(xval $pair, 0))>;
}
let params = T.Int32 in {
defm vadc: vadcsbc;
defm vsbc: vadcsbc;
defm vadc: vadcsbc<(u32 0)>;
defm vsbc: vadcsbc<(shl 1, 29)>;
}

let params = T.Int in {
Expand Down
35 changes: 33 additions & 2 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_CLANG_CIR_DIALECT_IR_CIROPS

include "clang/CIR/Dialect/IR/CIRDialect.td"
include "clang/CIR/Dialect/IR/CIRTypes.td"

include "mlir/IR/BuiltinAttributeInterfaces.td"
include "mlir/IR/EnumAttr.td"
Expand Down Expand Up @@ -74,6 +75,35 @@ class LLVMLoweringInfo {
class CIR_Op<string mnemonic, list<Trait> traits = []> :
Op<CIR_Dialect, mnemonic, traits>, LLVMLoweringInfo;

//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//

// TODO(CIR): For starters, cir.global has only name and type. The other
// properties of a global variable will be added over time as more of ClangIR
// is upstreamed.

def GlobalOp : CIR_Op<"global"> {
let summary = "Declare or define a global variable";
let description = [{
The `cir.global` operation declares or defines a named global variable.

The backing memory for the variable is allocated statically and is
described by the type of the variable.
}];

let arguments = (ins SymbolNameAttr:$sym_name, TypeAttr:$sym_type);

let assemblyFormat = [{ $sym_name `:` $sym_type attr-dict }];

let skipDefaultBuilders = 1;

let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name,
"mlir::Type":$sym_type)>];

let hasVerifier = 1;
}

//===----------------------------------------------------------------------===//
// FuncOp
//===----------------------------------------------------------------------===//
Expand All @@ -85,14 +115,15 @@ class CIR_Op<string mnemonic, list<Trait> traits = []> :
def FuncOp : CIR_Op<"func"> {
let summary = "Declare or define a function";
let description = [{
... lots of text to be added later ...
The `cir.func` operation defines a function, similar to the `mlir::FuncOp`
built-in.
}];

let arguments = (ins SymbolNameAttr:$sym_name);

let skipDefaultBuilders = 1;

let builders = [OpBuilder<(ins "llvm::StringRef":$name)>];
let builders = [OpBuilder<(ins "llvm::StringRef":$sym_name)>];

let hasCustomAssemblyFormat = 1;
let hasVerifier = 1;
Expand Down
27 changes: 27 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the types in the CIR dialect.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_DIALECT_CIR_IR_CIRTYPES_H_
#define MLIR_DIALECT_CIR_IR_CIRTYPES_H_

#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/Types.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"

//===----------------------------------------------------------------------===//
// CIR Dialect Tablegen'd Types
//===----------------------------------------------------------------------===//

#define GET_TYPEDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsTypes.h.inc"

#endif // MLIR_DIALECT_CIR_IR_CIRTYPES_H_
132 changes: 132 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//===- CIRTypes.td - CIR dialect types ---------------------*- tablegen -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares the CIR dialect types.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_CIR_DIALECT_CIR_TYPES
#define MLIR_CIR_DIALECT_CIR_TYPES

include "clang/CIR/Dialect/IR/CIRDialect.td"
include "mlir/Interfaces/DataLayoutInterfaces.td"
include "mlir/IR/AttrTypeBase.td"

//===----------------------------------------------------------------------===//
// CIR Types
//===----------------------------------------------------------------------===//

class CIR_Type<string name, string typeMnemonic, list<Trait> traits = [],
string baseCppClass = "::mlir::Type">
: TypeDef<CIR_Dialect, name, traits, baseCppClass> {
let mnemonic = typeMnemonic;
}

//===----------------------------------------------------------------------===//
// IntType
//===----------------------------------------------------------------------===//

def CIR_IntType : CIR_Type<"Int", "int",
[DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
let summary = "Integer type with arbitrary precision up to a fixed limit";
let description = [{
CIR type that represents integer types with arbitrary precision, including
standard integral types such as `int` and `long`, extended integral types
such as `__int128`, and arbitrary width types such as `_BitInt(n)`.

Those integer types that are directly available in C/C++ standard are called
primitive integer types. Said types are: `signed char`, `short`, `int`,
`long`, `long long`, and their unsigned variations.
}];
let parameters = (ins "unsigned":$width, "bool":$isSigned);
let hasCustomAssemblyFormat = 1;
let extraClassDeclaration = [{
/// Return true if this is a signed integer type.
bool isSigned() const { return getIsSigned(); }
/// Return true if this is an unsigned integer type.
bool isUnsigned() const { return !getIsSigned(); }
/// Return type alias.
std::string getAlias() const {
return (isSigned() ? 's' : 'u') + std::to_string(getWidth()) + 'i';
}
/// Return true if this is a primitive integer type (i.e. signed or unsigned
/// integer types whose bit width is 8, 16, 32, or 64).
bool isPrimitive() const {
return isValidPrimitiveIntBitwidth(getWidth());
}
bool isSignedPrimitive() const {
return isPrimitive() && isSigned();
}

/// Returns a minimum bitwidth of cir::IntType
static unsigned minBitwidth() { return 1; }
/// Returns a maximum bitwidth of cir::IntType
static unsigned maxBitwidth() { return 128; }

/// Returns true if cir::IntType that represents a primitive integer type
/// can be constructed from the provided bitwidth.
static bool isValidPrimitiveIntBitwidth(unsigned width) {
return width == 8 || width == 16 || width == 32 || width == 64;
}
}];
let genVerifyDecl = 1;
}

// Constraints

// Unsigned integer type of a specific width.
class UInt<int width>
: Type<And<[
CPred<"::mlir::isa<::cir::IntType>($_self)">,
CPred<"::mlir::cast<::cir::IntType>($_self).isUnsigned()">,
CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width>
]>, width # "-bit unsigned integer", "::cir::IntType">,
BuildableType<
"cir::IntType::get($_builder.getContext(), "
# width # ", /*isSigned=*/false)"> {
int bitwidth = width;
}

def UInt1 : UInt<1>;
def UInt8 : UInt<8>;
def UInt16 : UInt<16>;
def UInt32 : UInt<32>;
def UInt64 : UInt<64>;

// Signed integer type of a specific width.
class SInt<int width>
: Type<And<[
CPred<"::mlir::isa<::cir::IntType>($_self)">,
CPred<"::mlir::cast<::cir::IntType>($_self).isSigned()">,
CPred<"::mlir::cast<::cir::IntType>($_self).getWidth() == " # width>
]>, width # "-bit signed integer", "::cir::IntType">,
BuildableType<
"cir::IntType::get($_builder.getContext(), "
# width # ", /*isSigned=*/true)"> {
int bitwidth = width;
}

def SInt1 : SInt<1>;
def SInt8 : SInt<8>;
def SInt16 : SInt<16>;
def SInt32 : SInt<32>;
def SInt64 : SInt<64>;

def PrimitiveUInt
: AnyTypeOf<[UInt8, UInt16, UInt32, UInt64], "primitive unsigned int",
"::cir::IntType">;

def PrimitiveSInt
: AnyTypeOf<[SInt8, SInt16, SInt32, SInt64], "primitive signed int",
"::cir::IntType">;

def PrimitiveInt
: AnyTypeOf<[UInt8, UInt16, UInt32, UInt64, SInt8, SInt16, SInt32, SInt64],
"primitive int", "::cir::IntType">;

#endif // MLIR_CIR_DIALECT_CIR_TYPES
7 changes: 5 additions & 2 deletions clang/include/clang/Driver/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,11 @@ class Driver {
/// Object that stores strings read from configuration file.
llvm::StringSaver Saver;

/// Arguments originated from configuration file.
std::unique_ptr<llvm::opt::InputArgList> CfgOptions;
/// Arguments originated from configuration file (head part).
std::unique_ptr<llvm::opt::InputArgList> CfgOptionsHead;

/// Arguments originated from configuration file (tail part).
std::unique_ptr<llvm::opt::InputArgList> CfgOptionsTail;

/// Arguments originated from command line.
std::unique_ptr<llvm::opt::InputArgList> CLOptions;
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
Original file line number Diff line number Diff line change
Expand Up @@ -1749,6 +1749,10 @@ def UncountedLambdaCapturesChecker : Checker<"UncountedLambdaCapturesChecker">,

let ParentPackage = WebKitAlpha in {

def MemoryUnsafeCastChecker : Checker<"MemoryUnsafeCastChecker">,
HelpText<"Check for memory unsafe casts from base type to derived type.">,
Documentation<HasDocumentation>;

def NoUncheckedPtrMemberChecker : Checker<"NoUncheckedPtrMemberChecker">,
HelpText<"Check for no unchecked member variables.">,
Documentation<HasDocumentation>;
Expand Down
75 changes: 75 additions & 0 deletions clang/lib/AST/ByteCode/BitcastBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//
//===----------------------------------------------------------------------===//
#include "BitcastBuffer.h"
#include "llvm/ADT/STLExtras.h"

using namespace clang;
using namespace clang::interp;
Expand Down Expand Up @@ -60,6 +61,80 @@ BitcastBuffer::copyBits(Bits BitOffset, Bits BitWidth, Bits FullBitWidth,
return Out;
}

bool BitcastBuffer::allInitialized() const {
return rangeInitialized(Bits::zero(), FinalBitSize);
}

void BitcastBuffer::markInitialized(Bits Offset, Bits Length) {
if (Length.isZero())
return;

BitRange Element(Offset, Offset + Length - Bits(1));
if (InitializedBits.empty()) {
InitializedBits.push_back(Element);
return;
}

assert(InitializedBits.size() >= 1);
// Common case of just appending.
Bits End = InitializedBits.back().End;
if (End <= Offset) {
// Merge this range with the last one.
// In the best-case scenario, this means we only ever have
// one single bit range covering all bits.
if (End == (Offset - Bits(1))) {
InitializedBits.back().End = Element.End;
return;
}

// Otherwise, we can simply append.
InitializedBits.push_back(Element);
} else {
// Insert sorted.
auto It = std::upper_bound(InitializedBits.begin(), InitializedBits.end(),
Element);
InitializedBits.insert(It, Element);
}

#ifndef NDEBUG
// Ensure ranges are sorted and non-overlapping.
assert(llvm::is_sorted(InitializedBits));
for (unsigned I = 1; I != InitializedBits.size(); ++I) {
[[maybe_unused]] auto Prev = InitializedBits[I - 1];
[[maybe_unused]] auto Cur = InitializedBits[I];
assert(Prev.End.N < Cur.Start.N);
}
#endif
}

bool BitcastBuffer::rangeInitialized(Bits Offset, Bits Length) const {
if (Length.isZero())
return true;

BitRange Range(Offset, Offset + Length - Bits(1));
Bits Sum;
bool FoundStart = false;
for (BitRange BR : InitializedBits) {
if (FoundStart) {
if (BR.contains(Range.End)) {
Sum += (Range.End - BR.Start + Bits(1));
break;
}

// Else, BR is completely inside Range.
Sum += BR.size();
}
if (BR.contains(Range.Start)) {
Sum += (BR.End - Range.Start + Bits(1));
FoundStart = true;
}
}

// Note that Sum can be larger than Range, e.g. when Range is fully
// contained in one range.
return Sum >= Range.size();
}

#if 0
template<typename T>
static std::string hex(T t) {
Expand Down
35 changes: 28 additions & 7 deletions clang/lib/AST/ByteCode/BitcastBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#ifndef LLVM_CLANG_AST_INTERP_BITCAST_BUFFER_H
#define LLVM_CLANG_AST_INTERP_BITCAST_BUFFER_H

#include "llvm/ADT/SmallVector.h"
#include <cassert>
#include <cstddef>
#include <memory>
Expand All @@ -30,14 +31,20 @@ struct Bits {
bool nonZero() const { return N != 0; }
bool isZero() const { return N == 0; }

Bits operator-(Bits Other) { return Bits(N - Other.N); }
Bits operator+(Bits Other) { return Bits(N + Other.N); }
Bits operator-(Bits Other) const { return Bits(N - Other.N); }
Bits operator+(Bits Other) const { return Bits(N + Other.N); }
Bits operator+=(size_t O) {
N += O;
return *this;
}
Bits operator+=(Bits O) {
N += O.N;
return *this;
}

bool operator>=(Bits Other) { return N >= Other.N; }
bool operator>=(Bits Other) const { return N >= Other.N; }
bool operator<=(Bits Other) const { return N <= Other.N; }
bool operator==(Bits Other) const { return N == Other.N; }
};

/// A quantity in bytes.
Expand All @@ -48,11 +55,24 @@ struct Bytes {
Bits toBits() const { return Bits(N * 8); }
};

/// A bit range. Both Start and End are inclusive.
struct BitRange {
Bits Start;
Bits End;

BitRange(Bits Start, Bits End) : Start(Start), End(End) {}
Bits size() const { return End - Start + Bits(1); }
bool operator<(BitRange Other) const { return Start.N < Other.Start.N; }

bool contains(Bits B) { return Start <= B && End >= B; }
};

/// Track what bits have been initialized to known values and which ones
/// have indeterminate value.
struct BitcastBuffer {
Bits FinalBitSize;
std::unique_ptr<std::byte[]> Data;
llvm::SmallVector<BitRange> InitializedBits;

BitcastBuffer(Bits FinalBitSize) : FinalBitSize(FinalBitSize) {
assert(FinalBitSize.isFullByte());
Expand All @@ -64,10 +84,11 @@ struct BitcastBuffer {
Bits size() const { return FinalBitSize; }

/// Returns \c true if all bits in the buffer have been initialized.
bool allInitialized() const {
// FIXME: Implement.
return true;
}
bool allInitialized() const;
/// Marks the bits in the given range as initialized.
/// FIXME: Can we do this automatically in pushData()?
void markInitialized(Bits Start, Bits Length);
bool rangeInitialized(Bits Offset, Bits Length) const;

/// Push \p BitWidth bits at \p BitOffset from \p In into the buffer.
/// \p TargetEndianness is the endianness of the target we're compiling for.
Expand Down
7 changes: 1 addition & 6 deletions clang/lib/AST/ByteCode/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6483,19 +6483,14 @@ bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
QualType ToType = E->getType();
std::optional<PrimType> ToT = classify(ToType);

// Bitcasting TO nullptr_t is always fine.
if (ToType->isNullPtrType()) {
if (!this->discard(SubExpr))
return false;

return this->emitNullPtr(0, nullptr, E);
}

if (FromType->isNullPtrType() && ToT) {
if (!this->discard(SubExpr))
return false;

return visitZeroInitializer(*ToT, ToType, E);
}
assert(!ToType->isReferenceType());

// Prepare storage for the result in case we discard.
Expand Down
32 changes: 25 additions & 7 deletions clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,10 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
if (BitWidth.isZero())
return true;

if (!P.isInitialized()) {
assert(false && "Implement uninitialized value tracking");
return ReturnOnUninit;
}
// Bits will be left uninitialized and diagnosed when reading.
if (!P.isInitialized())
return true;

assert(P.isInitialized());
if (T == PT_Ptr) {
assert(P.getType()->isNullPtrType());
// Clang treats nullptr_t has having NO bits in its value
Expand All @@ -262,6 +260,7 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
return true;
}

assert(P.isInitialized());
auto Buff =
std::make_unique<std::byte[]>(ObjectReprChars.getQuantity());
// Work around floating point types that contain unused padding bytes.
Expand All @@ -287,6 +286,7 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
}

Buffer.pushData(Buff.get(), BitOffset, BitWidth, TargetEndianness);
Buffer.markInitialized(BitOffset, BitWidth);
return true;
});
}
Expand Down Expand Up @@ -354,10 +354,11 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
ToPtr, S.getContext(), Buffer.size(),
[&](const Pointer &P, PrimType T, Bits BitOffset,
bool PackedBools) -> bool {
CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
QualType PtrType = P.getType();
CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(PtrType);
Bits FullBitWidth = Bits(ASTCtx.toBits(ObjectReprChars));
if (T == PT_Float) {
const auto &Semantics = ASTCtx.getFloatTypeSemantics(P.getType());
const auto &Semantics = ASTCtx.getFloatTypeSemantics(PtrType);
Bits NumBits = Bits(llvm::APFloatBase::getSizeInBits(Semantics));
assert(NumBits.isFullByte());
assert(NumBits.getQuantity() <= FullBitWidth.getQuantity());
Expand All @@ -381,6 +382,23 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
else
BitWidth = FullBitWidth;

// If any of the bits are uninitialized, we need to abort unless the
// target type is std::byte or unsigned char.
bool Initialized = Buffer.rangeInitialized(BitOffset, BitWidth);
if (!Initialized) {
if (!PtrType->isStdByteType() &&
!PtrType->isSpecificBuiltinType(BuiltinType::UChar) &&
!PtrType->isSpecificBuiltinType(BuiltinType::Char_U)) {
const Expr *E = S.Current->getExpr(OpPC);
S.FFDiag(E, diag::note_constexpr_bit_cast_indet_dest)
<< PtrType << S.getLangOpts().CharIsSigned
<< E->getSourceRange();

return false;
}
return true;
}

auto Memory = Buffer.copyBits(BitOffset, BitWidth, FullBitWidth,
TargetEndianness);
if (llvm::sys::IsBigEndianHost)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/CommentLexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

#include "clang/AST/CommentLexer.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/DiagnosticComment.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ConvertUTF.h"
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/CommentParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

#include "clang/AST/CommentParser.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/CommentSema.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/DiagnosticComment.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/Support/ErrorHandling.h"

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/CommentSema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#include "clang/AST/CommentSema.h"
#include "clang/AST/Attr.h"
#include "clang/AST/CommentCommandTraits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/DiagnosticComment.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1639,11 +1639,19 @@ SourceLocation CallExpr::getBeginLoc() const {
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
return OCE->getBeginLoc();

if (const auto *Method =
dyn_cast_if_present<const CXXMethodDecl>(getCalleeDecl());
Method && Method->isExplicitObjectMemberFunction()) {
assert(getNumArgs() > 0 && getArg(0));
return getArg(0)->getBeginLoc();
}

SourceLocation begin = getCallee()->getBeginLoc();
if (begin.isInvalid() && getNumArgs() > 0 && getArg(0))
begin = getArg(0)->getBeginLoc();
return begin;
}

SourceLocation CallExpr::getEndLoc() const {
if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(this))
return OCE->getEndLoc();
Expand Down
24 changes: 17 additions & 7 deletions clang/lib/Basic/Diagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,8 @@ class WarningsSpecialCaseList : public llvm::SpecialCaseList {
// the last section take precedence in such cases.
void processSections(DiagnosticsEngine &Diags);

bool isDiagSuppressed(diag::kind DiagId, StringRef FilePath) const;
bool isDiagSuppressed(diag::kind DiagId, SourceLocation DiagLoc,
const SourceManager &SM) const;

private:
// Find the longest glob pattern that matches FilePath amongst
Expand Down Expand Up @@ -573,13 +574,14 @@ void DiagnosticsEngine::setDiagSuppressionMapping(llvm::MemoryBuffer &Input) {
WarningSuppressionList->processSections(*this);
DiagSuppressionMapping =
[WarningSuppressionList(std::move(WarningSuppressionList))](
diag::kind DiagId, StringRef Path) {
return WarningSuppressionList->isDiagSuppressed(DiagId, Path);
diag::kind DiagId, SourceLocation DiagLoc, const SourceManager &SM) {
return WarningSuppressionList->isDiagSuppressed(DiagId, DiagLoc, SM);
};
}

bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
StringRef FilePath) const {
SourceLocation DiagLoc,
const SourceManager &SM) const {
const Section *DiagSection = DiagToSection.lookup(DiagId);
if (!DiagSection)
return false;
Expand All @@ -589,7 +591,13 @@ bool WarningsSpecialCaseList::isDiagSuppressed(diag::kind DiagId,
return false;
const llvm::StringMap<llvm::SpecialCaseList::Matcher> &CategoriesToMatchers =
SrcEntriesIt->getValue();
return globsMatches(CategoriesToMatchers, FilePath);
// We also use presumed locations here to improve reproducibility for
// preprocessed inputs.
if (PresumedLoc PLoc = SM.getPresumedLoc(DiagLoc); PLoc.isValid())
return globsMatches(
CategoriesToMatchers,
llvm::sys::path::remove_leading_dotslash(PLoc.getFilename()));
return false;
}

bool WarningsSpecialCaseList::globsMatches(
Expand All @@ -614,8 +622,10 @@ bool WarningsSpecialCaseList::globsMatches(
}

bool DiagnosticsEngine::isSuppressedViaMapping(diag::kind DiagId,
StringRef FilePath) const {
return DiagSuppressionMapping && DiagSuppressionMapping(DiagId, FilePath);
SourceLocation DiagLoc) const {
if (!hasSourceManager() || !DiagSuppressionMapping)
return false;
return DiagSuppressionMapping(DiagId, DiagLoc, getSourceManager());
}

void DiagnosticsEngine::Report(const StoredDiagnostic &storedDiag) {
Expand Down
11 changes: 2 additions & 9 deletions clang/lib/Basic/DiagnosticIDs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -601,15 +601,8 @@ DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
return diag::Severity::Ignored;

// Clang-diagnostics pragmas always take precedence over suppression mapping.
if (!Mapping.isPragma() && Diag.DiagSuppressionMapping) {
// We also use presumed locations here to improve reproducibility for
// preprocessed inputs.
if (PresumedLoc PLoc = SM.getPresumedLoc(Loc);
PLoc.isValid() && Diag.isSuppressedViaMapping(
DiagID, llvm::sys::path::remove_leading_dotslash(
PLoc.getFilename())))
return diag::Severity::Ignored;
}
if (!Mapping.isPragma() && Diag.isSuppressedViaMapping(DiagID, Loc))
return diag::Severity::Ignored;

return Result;
}
Expand Down
19 changes: 14 additions & 5 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,23 @@ bool AArch64TargetInfo::validateTarget(DiagnosticsEngine &Diags) const {

bool AArch64TargetInfo::validateGlobalRegisterVariable(
StringRef RegName, unsigned RegSize, bool &HasSizeMismatch) const {
if ((RegName == "sp") || RegName.starts_with("x")) {
if (RegName == "sp") {
HasSizeMismatch = RegSize != 64;
return true;
} else if (RegName.starts_with("w")) {
HasSizeMismatch = RegSize != 32;
return true;
}
return false;
if (RegName.starts_with("w"))
HasSizeMismatch = RegSize != 32;
else if (RegName.starts_with("x"))
HasSizeMismatch = RegSize != 64;
else
return false;
StringRef RegNum = RegName.drop_front();
// Check if the register is reserved. See also
// AArch64TargetLowering::getRegisterByName().
return RegNum == "0" ||
(RegNum == "18" &&
llvm::AArch64::isX18ReservedByDefault(getTriple())) ||
getTargetOpts().FeatureMap.lookup(("reserve-x" + RegNum).str());
}

bool AArch64TargetInfo::validateBranchProtection(StringRef Spec, StringRef,
Expand Down
58 changes: 33 additions & 25 deletions clang/lib/CIR/CodeGen/CIRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context,
DiagnosticsEngine &diags)
: builder(&context), astCtx(astctx), langOpts(astctx.getLangOpts()),
theModule{mlir::ModuleOp::create(mlir::UnknownLoc::get(&context))},
diags(diags), target(astCtx.getTargetInfo()) {}
diags(diags), target(astCtx.getTargetInfo()), genTypes(*this) {}

mlir::Location CIRGenModule::getLoc(SourceLocation cLoc) {
assert(cLoc.isValid() && "expected valid source location");
Expand Down Expand Up @@ -67,7 +67,8 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
return;
}
} else {
errorNYI(global->getSourceRange(), "global variable declaration");
assert(cast<VarDecl>(global)->isFileVarDecl() &&
"Cannot emit local var decl as global");
}

// TODO(CIR): Defer emitting some global definitions until later
Expand All @@ -77,9 +78,27 @@ void CIRGenModule::emitGlobal(clang::GlobalDecl gd) {
void CIRGenModule::emitGlobalFunctionDefinition(clang::GlobalDecl gd,
mlir::Operation *op) {
auto const *funcDecl = cast<FunctionDecl>(gd.getDecl());
auto funcOp = builder.create<cir::FuncOp>(
getLoc(funcDecl->getSourceRange()), funcDecl->getIdentifier()->getName());
theModule.push_back(funcOp);
if (clang::IdentifierInfo *identifier = funcDecl->getIdentifier()) {
auto funcOp = builder.create<cir::FuncOp>(
getLoc(funcDecl->getSourceRange()), identifier->getName());
theModule.push_back(funcOp);
} else {
errorNYI(funcDecl->getSourceRange().getBegin(),
"function definition with a non-identifier for a name");
}
}

void CIRGenModule::emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative) {
mlir::Type type = getTypes().convertType(vd->getType());
if (clang::IdentifierInfo *identifier = vd->getIdentifier()) {
auto varOp = builder.create<cir::GlobalOp>(getLoc(vd->getSourceRange()),
identifier->getName(), type);
theModule.push_back(varOp);
} else {
errorNYI(vd->getSourceRange().getBegin(),
"variable definition with a non-identifier for a name");
}
}

void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
Expand All @@ -103,6 +122,9 @@ void CIRGenModule::emitGlobalDefinition(clang::GlobalDecl gd,
return;
}

if (const auto *vd = dyn_cast<VarDecl>(decl))
return emitGlobalVarDefinition(vd, !vd->hasDefinition());

llvm_unreachable("Invalid argument to CIRGenModule::emitGlobalDefinition");
}

Expand All @@ -126,13 +148,13 @@ void CIRGenModule::emitTopLevelDecl(Decl *decl) {
emitGlobal(fd);
break;
}
}
}

DiagnosticBuilder CIRGenModule::errorNYI(llvm::StringRef feature) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0");
return diags.Report(diagID) << feature;
case Decl::Var: {
auto *vd = cast<VarDecl>(decl);
emitGlobal(vd);
break;
}
}
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
Expand All @@ -142,21 +164,7 @@ DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
return diags.Report(loc, diagID) << feature;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceLocation loc,
llvm::StringRef feature,
llvm::StringRef name) {
unsigned diagID = diags.getCustomDiagID(
DiagnosticsEngine::Error, "ClangIR code gen Not Yet Implemented: %0: %1");
return diags.Report(loc, diagID) << feature << name;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature) {
return errorNYI(loc.getBegin(), feature) << loc;
}

DiagnosticBuilder CIRGenModule::errorNYI(SourceRange loc,
llvm::StringRef feature,
llvm::StringRef name) {
return errorNYI(loc.getBegin(), feature, name) << loc;
}
33 changes: 26 additions & 7 deletions clang/lib/CIR/CodeGen/CIRGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,22 @@
#define LLVM_CLANG_LIB_CIR_CODEGEN_CIRGENMODULE_H

#include "CIRGenTypeCache.h"
#include "CIRGenTypes.h"

#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/MLIRContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringRef.h"

namespace clang {
class ASTContext;
class CodeGenOptions;
class Decl;
class DiagnosticBuilder;
class DiagnosticsEngine;
class GlobalDecl;
class LangOptions;
class SourceLocation;
class SourceRange;
class TargetInfo;
class VarDecl;

namespace CIRGen {

Expand Down Expand Up @@ -64,8 +63,13 @@ class CIRGenModule : public CIRGenTypeCache {

const clang::TargetInfo &target;

CIRGenTypes genTypes;

public:
mlir::ModuleOp getModule() const { return theModule; }
mlir::OpBuilder &getBuilder() { return builder; }
clang::ASTContext &getASTContext() const { return astCtx; }
CIRGenTypes &getTypes() { return genTypes; }

/// Helpers to convert the presumed location of Clang's SourceLocation to an
/// MLIR Location.
Expand All @@ -81,13 +85,28 @@ class CIRGenModule : public CIRGenTypeCache {
void emitGlobalDefinition(clang::GlobalDecl gd,
mlir::Operation *op = nullptr);
void emitGlobalFunctionDefinition(clang::GlobalDecl gd, mlir::Operation *op);
void emitGlobalVarDefinition(const clang::VarDecl *vd,
bool isTentative = false);

/// Helpers to emit "not yet implemented" error diagnostics
DiagnosticBuilder errorNYI(llvm::StringRef);
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef, llvm::StringRef);

template <typename T>
DiagnosticBuilder errorNYI(SourceLocation loc, llvm::StringRef feature,
const T &name) {
unsigned diagID =
diags.getCustomDiagID(DiagnosticsEngine::Error,
"ClangIR code gen Not Yet Implemented: %0: %1");
return diags.Report(loc, diagID) << feature << name;
}

DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef);
DiagnosticBuilder errorNYI(SourceRange, llvm::StringRef, llvm::StringRef);

template <typename T>
DiagnosticBuilder errorNYI(SourceRange loc, llvm::StringRef feature,
const T &name) {
return errorNYI(loc.getBegin(), feature, name) << loc;
}
};
} // namespace CIRGen

Expand Down
87 changes: 87 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypes.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include "CIRGenTypes.h"

#include "CIRGenModule.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"

using namespace clang;
using namespace clang::CIRGen;

CIRGenTypes::CIRGenTypes(CIRGenModule &genModule)
: cgm(genModule), context(genModule.getASTContext()) {}

CIRGenTypes::~CIRGenTypes() {}

mlir::Type CIRGenTypes::convertType(QualType type) {
type = context.getCanonicalType(type);
const Type *ty = type.getTypePtr();

// For types that haven't been implemented yet or are otherwise unsupported,
// report an error and return 'int'.

mlir::Type resultType = nullptr;
switch (ty->getTypeClass()) {
case Type::Builtin: {
switch (cast<BuiltinType>(ty)->getKind()) {
// Signed types.
case BuiltinType::Char_S:
case BuiltinType::Int:
case BuiltinType::Int128:
case BuiltinType::Long:
case BuiltinType::LongLong:
case BuiltinType::SChar:
case BuiltinType::Short:
case BuiltinType::WChar_S:
resultType = cir::IntType::get(cgm.getBuilder().getContext(),
context.getTypeSize(ty),
/*isSigned=*/true);
break;
// Unsigned types.
case BuiltinType::Char8:
case BuiltinType::Char16:
case BuiltinType::Char32:
case BuiltinType::Char_U:
case BuiltinType::UChar:
case BuiltinType::UInt:
case BuiltinType::UInt128:
case BuiltinType::ULong:
case BuiltinType::ULongLong:
case BuiltinType::UShort:
case BuiltinType::WChar_U:
resultType = cir::IntType::get(cgm.getBuilder().getContext(),
context.getTypeSize(ty),
/*isSigned=*/false);
break;
default:
cgm.errorNYI(SourceLocation(), "processing of built-in type", type);
resultType = cir::IntType::get(cgm.getBuilder().getContext(), 32,
/*isSigned=*/true);
break;
}
break;
}
case Type::BitInt: {
const auto *bitIntTy = cast<BitIntType>(type);
if (bitIntTy->getNumBits() > cir::IntType::maxBitwidth()) {
cgm.errorNYI(SourceLocation(), "large _BitInt type", type);
resultType = cir::IntType::get(cgm.getBuilder().getContext(), 32,
/*isSigned=*/true);
} else {
resultType =
cir::IntType::get(cgm.getBuilder().getContext(),
bitIntTy->getNumBits(), bitIntTy->isSigned());
}
break;
}
default:
cgm.errorNYI(SourceLocation(), "processing of type", type);
resultType =
cir::IntType::get(cgm.getBuilder().getContext(), 32, /*isSigned=*/true);
break;
}

assert(resultType && "Type conversion not yet implemented");

return resultType;
}
47 changes: 47 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenTypes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===--- CIRGenTypes.h - Type translation for CIR CodeGen -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This is the code that handles AST -> CIR type lowering.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H
#define LLVM_CLANG_LIB_CODEGEN_CODEGENTYPES_H

#include "clang/CIR/Dialect/IR/CIRTypes.h"

namespace clang {
class ASTContext;
class QualType;
} // namespace clang

namespace mlir {
class Type;
}

namespace clang::CIRGen {

class CIRGenModule;

/// This class organizes the cross-module state that is used while lowering
/// AST types to CIR types.
class CIRGenTypes {
CIRGenModule &cgm;
clang::ASTContext &context;

public:
CIRGenTypes(CIRGenModule &cgm);
~CIRGenTypes();

/// Convert a Clang type into a mlir::Type.
mlir::Type convertType(clang::QualType type);
};

} // namespace clang::CIRGen

#endif
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)
add_clang_library(clangCIR
CIRGenerator.cpp
CIRGenModule.cpp
CIRGenTypes.cpp

DEPENDS
MLIRCIR
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,22 @@ void cir::CIRDialect::initialize() {
>();
}

//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//

// TODO(CIR): The properties of global variables that require verification
// haven't been implemented yet.
mlir::LogicalResult cir::GlobalOp::verify() { return success(); }

void cir::GlobalOp::build(OpBuilder &odsBuilder, OperationState &odsState,
llvm::StringRef sym_name, mlir::Type sym_type) {
odsState.addAttribute(getSymNameAttrName(odsState.name),
odsBuilder.getStringAttr(sym_name));
odsState.addAttribute(getSymTypeAttrName(odsState.name),
mlir::TypeAttr::get(sym_type));
}

//===----------------------------------------------------------------------===//
// FuncOp
//===----------------------------------------------------------------------===//
Expand All @@ -56,6 +72,8 @@ void cir::FuncOp::print(OpAsmPrinter &p) {
p.printSymbolName(getSymName());
}

// TODO(CIR): The properties of functions that require verification haven't
// been implemented yet.
mlir::LogicalResult cir::FuncOp::verify() { return success(); }

//===----------------------------------------------------------------------===//
Expand Down
120 changes: 116 additions & 4 deletions clang/lib/CIR/Dialect/IR/CIRTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@
//
//===----------------------------------------------------------------------===//

#include "clang/CIR/Dialect/IR/CIRTypes.h"

#include "mlir/IR/DialectImplementation.h"
#include "clang/CIR/Dialect/IR/CIRDialect.h"
#include "llvm/ADT/TypeSwitch.h"

//===----------------------------------------------------------------------===//
// Get autogenerated stuff
//===----------------------------------------------------------------------===//

#define GET_TYPEDEF_CLASSES
#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"

using namespace mlir;
using namespace cir;
Expand All @@ -20,18 +31,119 @@ using namespace cir;
//===----------------------------------------------------------------------===//

Type CIRDialect::parseType(DialectAsmParser &parser) const {
// No types yet to parse
return Type{};
llvm::SMLoc typeLoc = parser.getCurrentLocation();
llvm::StringRef mnemonic;
Type genType;

// Try to parse as a tablegen'd type.
OptionalParseResult parseResult =
generatedTypeParser(parser, &mnemonic, genType);
if (parseResult.has_value())
return genType;

// TODO(CIR) Attempt to parse as a raw C++ type.
parser.emitError(typeLoc) << "unknown CIR type: " << mnemonic;
return Type();
}

void CIRDialect::printType(Type type, DialectAsmPrinter &os) const {
// No types yet to print
// Try to print as a tablegen'd type.
if (generatedTypePrinter(type, os).succeeded())
return;

// TODO(CIR) Attempt to print as a raw C++ type.
llvm::report_fatal_error("printer is missing a handler for this type");
}

//===----------------------------------------------------------------------===//
// IntType Definitions
//===----------------------------------------------------------------------===//

Type IntType::parse(mlir::AsmParser &parser) {
mlir::MLIRContext *context = parser.getBuilder().getContext();
llvm::SMLoc loc = parser.getCurrentLocation();
bool isSigned;
unsigned width;

if (parser.parseLess())
return {};

// Fetch integer sign.
llvm::StringRef sign;
if (parser.parseKeyword(&sign))
return {};
if (sign == "s")
isSigned = true;
else if (sign == "u")
isSigned = false;
else {
parser.emitError(loc, "expected 's' or 'u'");
return {};
}

if (parser.parseComma())
return {};

// Fetch integer size.
if (parser.parseInteger(width))
return {};
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
parser.emitError(loc, "expected integer width to be from ")
<< IntType::minBitwidth() << " up to " << IntType::maxBitwidth();
return {};
}

if (parser.parseGreater())
return {};

return IntType::get(context, width, isSigned);
}

void IntType::print(mlir::AsmPrinter &printer) const {
char sign = isSigned() ? 's' : 'u';
printer << '<' << sign << ", " << getWidth() << '>';
}

llvm::TypeSize
IntType::getTypeSizeInBits(const mlir::DataLayout &dataLayout,
mlir::DataLayoutEntryListRef params) const {
return llvm::TypeSize::getFixed(getWidth());
}

uint64_t IntType::getABIAlignment(const mlir::DataLayout &dataLayout,
mlir::DataLayoutEntryListRef params) const {
return (uint64_t)(getWidth() / 8);
}

uint64_t
IntType::getPreferredAlignment(const ::mlir::DataLayout &dataLayout,
::mlir::DataLayoutEntryListRef params) const {
return (uint64_t)(getWidth() / 8);
}

mlir::LogicalResult
IntType::verify(llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
unsigned width, bool isSigned) {
if (width < IntType::minBitwidth() || width > IntType::maxBitwidth()) {
emitError() << "IntType only supports widths from "
<< IntType::minBitwidth() << " up to "
<< IntType::maxBitwidth();
return mlir::failure();
}
return mlir::success();
}

//===----------------------------------------------------------------------===//
// CIR Dialect
//===----------------------------------------------------------------------===//

void CIRDialect::registerTypes() {
// No types yet to register
// Register tablegen'd types.
addTypes<
#define GET_TYPEDEF_LIST
#include "clang/CIR/Dialect/IR/CIROpsTypes.cpp.inc"
>();

// Register raw C++ types.
// TODO(CIR) addTypes<StructType>();
}
4 changes: 4 additions & 0 deletions clang/lib/CIR/Dialect/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ add_clang_library(MLIRCIR

LINK_LIBS PUBLIC
MLIRIR
MLIRDLTIDialect
MLIRDataLayoutInterfaces
MLIRFuncDialect
clangAST
)
4 changes: 3 additions & 1 deletion clang/lib/CodeGen/BackendUtil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1023,12 +1023,14 @@ void EmitAssemblyHelper::RunOptimizationPipeline(
FPM.addPass(BoundsCheckingPass());
});

if (LangOpts.Sanitize.has(SanitizerKind::Realtime))
if (LangOpts.Sanitize.has(SanitizerKind::Realtime)) {
PB.registerScalarOptimizerLateEPCallback(
[](FunctionPassManager &FPM, OptimizationLevel Level) {
RealtimeSanitizerOptions Opts;
FPM.addPass(RealtimeSanitizerPass(Opts));
});
MPM.addPass(ModuleRealtimeSanitizerPass());
}

// Don't add sanitizers if we are here from ThinLTO PostLink. That already
// done on PreLink stage.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4529,7 +4529,7 @@ void CodeGenFunction::EmitCallArgs(
ArgTypes.assign(MD->param_type_begin() + ParamsToSkip,
MD->param_type_end());
} else {
const auto *FPT = Prototype.P.get<const FunctionProtoType *>();
const auto *FPT = cast<const FunctionProtoType *>(Prototype.P);
IsVariadic = FPT->isVariadic();
ExplicitCC = FPT->getExtInfo().getCC();
ArgTypes.assign(FPT->param_type_begin() + ParamsToSkip,
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2102,7 +2102,8 @@ Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) {
Expr *InitVector = E->getInit(0);

// Initialize from another scalable vector of the same type.
if (InitVector->getType() == E->getType())
if (InitVector->getType().getCanonicalType() ==
E->getType().getCanonicalType())
return Visit(InitVector);
}

Expand Down
14 changes: 7 additions & 7 deletions clang/lib/CodeGen/CGOpenMPRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7770,7 +7770,7 @@ class MappableExprsHandler {
if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>())
getPlainLayout(Base, Layout, /*AsBase=*/true);
else
Layout.push_back(Data.get<const FieldDecl *>());
Layout.push_back(cast<const FieldDecl *>(Data));
}
}

Expand Down Expand Up @@ -8333,9 +8333,9 @@ class MappableExprsHandler {
MapCombinedInfoTy &CombinedInfo, llvm::OpenMPIRBuilder &OMPBuilder,
const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet =
llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const {
assert(CurDir.is<const OMPExecutableDirective *>() &&
assert(isa<const OMPExecutableDirective *>(CurDir) &&
"Expect a executable directive");
const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, OMPBuilder,
SkipVarSet);
}
Expand All @@ -8345,9 +8345,9 @@ class MappableExprsHandler {
/// in \a CombinedInfo).
void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo,
llvm::OpenMPIRBuilder &OMPBuilder) const {
assert(CurDir.is<const OMPDeclareMapperDecl *>() &&
assert(isa<const OMPDeclareMapperDecl *>(CurDir) &&
"Expect a declare mapper directive");
const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>();
const auto *CurMapperDir = cast<const OMPDeclareMapperDecl *>(CurDir);
generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo,
OMPBuilder);
}
Expand Down Expand Up @@ -8519,9 +8519,9 @@ class MappableExprsHandler {
DeclComponentLists.emplace_back(MCL, OMPC_MAP_tofrom, Unknown,
/*IsImpicit = */ true, nullptr,
nullptr);
assert(CurDir.is<const OMPExecutableDirective *>() &&
assert(isa<const OMPExecutableDirective *>(CurDir) &&
"Expect a executable directive");
const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>();
const auto *CurExecDir = cast<const OMPExecutableDirective *>(CurDir);
bool HasMapBasePtr = false;
bool HasMapArraySec = false;
for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) {
Expand Down
12 changes: 6 additions & 6 deletions clang/lib/CodeGen/ConstantInitBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ using namespace CodeGen;

llvm::Type *ConstantInitFuture::getType() const {
assert(Data && "dereferencing null future");
if (Data.is<llvm::Constant*>()) {
return Data.get<llvm::Constant*>()->getType();
if (const auto *C = dyn_cast<llvm::Constant *>(Data)) {
return C->getType();
} else {
return Data.get<ConstantInitBuilderBase*>()->Buffer[0]->getType();
return cast<ConstantInitBuilderBase *>(Data)->Buffer[0]->getType();
}
}

Expand All @@ -37,10 +37,10 @@ void ConstantInitFuture::abandon() {

void ConstantInitFuture::installInGlobal(llvm::GlobalVariable *GV) {
assert(Data && "installing null future");
if (Data.is<llvm::Constant*>()) {
GV->setInitializer(Data.get<llvm::Constant*>());
if (auto *C = dyn_cast<llvm::Constant *>(Data)) {
GV->setInitializer(C);
} else {
auto &builder = *Data.get<ConstantInitBuilderBase*>();
auto &builder = *cast<ConstantInitBuilderBase *>(Data);
assert(builder.Buffer.size() == 1);
builder.setGlobalInitializer(GV, builder.Buffer[0]);
builder.Buffer.clear();
Expand Down
69 changes: 55 additions & 14 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1039,34 +1039,59 @@ bool Driver::readConfigFile(StringRef FileName,
}

// Try reading the given file.
SmallVector<const char *, 32> NewCfgArgs;
if (llvm::Error Err = ExpCtx.readConfigFile(FileName, NewCfgArgs)) {
SmallVector<const char *, 32> NewCfgFileArgs;
if (llvm::Error Err = ExpCtx.readConfigFile(FileName, NewCfgFileArgs)) {
Diag(diag::err_drv_cannot_read_config_file)
<< FileName << toString(std::move(Err));
return true;
}

// Populate head and tail lists. The tail list is used only when linking.
SmallVector<const char *, 32> NewCfgHeadArgs, NewCfgTailArgs;
for (const char *Opt : NewCfgFileArgs) {
// An $-prefixed option should go to the tail list.
if (Opt[0] == '$' && Opt[1])
NewCfgTailArgs.push_back(Opt + 1);
else
NewCfgHeadArgs.push_back(Opt);
}

// Read options from config file.
llvm::SmallString<128> CfgFileName(FileName);
llvm::sys::path::native(CfgFileName);
bool ContainErrors;
auto NewOptions = std::make_unique<InputArgList>(
ParseArgStrings(NewCfgArgs, /*UseDriverMode=*/true, ContainErrors));
bool ContainErrors = false;
auto NewHeadOptions = std::make_unique<InputArgList>(
ParseArgStrings(NewCfgHeadArgs, /*UseDriverMode=*/true, ContainErrors));
if (ContainErrors)
return true;
auto NewTailOptions = std::make_unique<InputArgList>(
ParseArgStrings(NewCfgTailArgs, /*UseDriverMode=*/true, ContainErrors));
if (ContainErrors)
return true;

// Claim all arguments that come from a configuration file so that the driver
// does not warn on any that is unused.
for (Arg *A : *NewOptions)
for (Arg *A : *NewHeadOptions)
A->claim();
for (Arg *A : *NewTailOptions)
A->claim();

if (!CfgOptions)
CfgOptions = std::move(NewOptions);
if (!CfgOptionsHead)
CfgOptionsHead = std::move(NewHeadOptions);
else {
// If this is a subsequent config file, append options to the previous one.
for (auto *Opt : *NewHeadOptions)
appendOneArg(*CfgOptionsHead, Opt);
}

if (!CfgOptionsTail)
CfgOptionsTail = std::move(NewTailOptions);
else {
// If this is a subsequent config file, append options to the previous one.
for (auto *Opt : *NewOptions)
appendOneArg(*CfgOptions, Opt);
for (auto *Opt : *NewTailOptions)
appendOneArg(*CfgOptionsTail, Opt);
}

ConfigFiles.push_back(std::string(CfgFileName));
return false;
}
Expand Down Expand Up @@ -1243,13 +1268,14 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Try parsing configuration file.
if (!ContainsError)
ContainsError = loadConfigFiles();
bool HasConfigFile = !ContainsError && (CfgOptions.get() != nullptr);
bool HasConfigFileHead = !ContainsError && CfgOptionsHead;
bool HasConfigFileTail = !ContainsError && CfgOptionsTail;

// All arguments, from both config file and command line.
InputArgList Args = std::move(HasConfigFile ? std::move(*CfgOptions)
: std::move(*CLOptions));
InputArgList Args =
HasConfigFileHead ? std::move(*CfgOptionsHead) : std::move(*CLOptions);

if (HasConfigFile)
if (HasConfigFileHead)
for (auto *Opt : *CLOptions)
if (!Opt->getOption().matches(options::OPT_config))
appendOneArg(Args, Opt);
Expand Down Expand Up @@ -1540,6 +1566,15 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// Construct the list of inputs.
InputList Inputs;
BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
if (HasConfigFileTail && Inputs.size()) {
Arg *FinalPhaseArg;
if (getFinalPhase(*TranslatedArgs, &FinalPhaseArg) == phases::Link) {
DerivedArgList TranslatedLinkerIns(*CfgOptionsTail);
for (Arg *A : *CfgOptionsTail)
TranslatedLinkerIns.append(A);
BuildInputs(C->getDefaultToolChain(), TranslatedLinkerIns, Inputs);
}
}

// Populate the tool chains for the offloading devices, if any.
CreateOffloadingDeviceToolChains(*C, Inputs);
Expand Down Expand Up @@ -4515,7 +4550,13 @@ Driver::getOffloadArchs(Compilation &C, const llvm::opt::DerivedArgList &Args,
ToolChain::getOpenMPTriple(Arg->getValue(0)) == TC->getTriple()) {
Arg->claim();
unsigned Index = Args.getBaseArgs().MakeIndex(Arg->getValue(1));
unsigned Prev = Index;
ExtractedArg = getOpts().ParseOneArg(Args, Index);
if (!ExtractedArg || Index > Prev + 1) {
TC->getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
<< Arg->getAsString(Args);
continue;
}
Arg = ExtractedArg.get();
}

Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Driver/ToolChain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1596,8 +1596,10 @@ llvm::opt::DerivedArgList *ToolChain::TranslateOpenMPTargetArgs(
Prev = Index;
std::unique_ptr<Arg> XOpenMPTargetArg(Opts.ParseOneArg(Args, Index));
if (!XOpenMPTargetArg || Index > Prev + 1) {
getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
<< A->getAsString(Args);
if (!A->isClaimed()) {
getDriver().Diag(diag::err_drv_invalid_Xopenmp_target_with_args)
<< A->getAsString(Args);
}
continue;
}
if (XOpenMPTargetNoTriple && XOpenMPTargetArg &&
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@ bool arm::isARMAProfile(const llvm::Triple &Triple) {
return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::A;
}

/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
bool arm::isARMEABIBareMetal(const llvm::Triple &Triple) {
auto arch = Triple.getArch();
if (arch != llvm::Triple::arm && arch != llvm::Triple::thumb &&
arch != llvm::Triple::armeb && arch != llvm::Triple::thumbeb)
return false;

if (Triple.getVendor() != llvm::Triple::UnknownVendor)
return false;

if (Triple.getOS() != llvm::Triple::UnknownOS)
return false;

if (Triple.getEnvironment() != llvm::Triple::EABI &&
Triple.getEnvironment() != llvm::Triple::EABIHF)
return false;

return true;
}

// Get Arch/CPU from args.
void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch,
llvm::StringRef &CPU, bool FromAs) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Arch/ARM.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ int getARMSubArchVersionNumber(const llvm::Triple &Triple);
bool isARMMProfile(const llvm::Triple &Triple);
bool isARMAProfile(const llvm::Triple &Triple);
bool isARMBigEndian(const llvm::Triple &Triple, const llvm::opt::ArgList &Args);
bool isARMEABIBareMetal(const llvm::Triple &Triple);

} // end namespace arm
} // end namespace tools
Expand Down
72 changes: 13 additions & 59 deletions clang/lib/Driver/ToolChains/BareMetal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,27 +128,6 @@ BareMetal::BareMetal(const Driver &D, const llvm::Triple &Triple,
}
}

/// Is the triple {arm,armeb,thumb,thumbeb}-none-none-{eabi,eabihf} ?
static bool isARMBareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::arm &&
Triple.getArch() != llvm::Triple::thumb &&
Triple.getArch() != llvm::Triple::armeb &&
Triple.getArch() != llvm::Triple::thumbeb)
return false;

if (Triple.getVendor() != llvm::Triple::UnknownVendor)
return false;

if (Triple.getOS() != llvm::Triple::UnknownOS)
return false;

if (Triple.getEnvironment() != llvm::Triple::EABI &&
Triple.getEnvironment() != llvm::Triple::EABIHF)
return false;

return true;
}

/// Is the triple {aarch64.aarch64_be}-none-elf?
static bool isAArch64BareMetal(const llvm::Triple &Triple) {
if (Triple.getArch() != llvm::Triple::aarch64 &&
Expand Down Expand Up @@ -267,7 +246,7 @@ void BareMetal::findMultilibs(const Driver &D, const llvm::Triple &Triple,
}

bool BareMetal::handlesTarget(const llvm::Triple &Triple) {
return isARMBareMetal(Triple) || isAArch64BareMetal(Triple) ||
return arm::isARMEABIBareMetal(Triple) || isAArch64BareMetal(Triple) ||
isRISCVBareMetal(Triple) || isPPCBareMetal(Triple);
}

Expand Down Expand Up @@ -414,38 +393,6 @@ void BareMetal::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
}
}

void BareMetal::AddCXXStdlibLibArgs(const ArgList &Args,
ArgStringList &CmdArgs) const {
switch (GetCXXStdlibType(Args)) {
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
CmdArgs.push_back("-lc++experimental");
CmdArgs.push_back("-lc++abi");
break;
case ToolChain::CST_Libstdcxx:
CmdArgs.push_back("-lstdc++");
CmdArgs.push_back("-lsupc++");
break;
}
CmdArgs.push_back("-lunwind");
}

void BareMetal::AddLinkRuntimeLib(const ArgList &Args,
ArgStringList &CmdArgs) const {
ToolChain::RuntimeLibType RLT = GetRuntimeLibType(Args);
switch (RLT) {
case ToolChain::RLT_CompilerRT: {
CmdArgs.push_back(getCompilerRTArgString(Args, "builtins"));
return;
}
case ToolChain::RLT_Libgcc:
CmdArgs.push_back("-lgcc");
return;
}
llvm_unreachable("Unhandled RuntimeLibType.");
}

void baremetal::StaticLibTool::ConstructJob(Compilation &C, const JobAction &JA,
const InputInfo &Output,
const InputInfoList &Inputs,
Expand Down Expand Up @@ -532,14 +479,21 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
for (const auto &LibPath : TC.getLibraryPaths())
CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-L", LibPath)));

if (TC.ShouldLinkCXXStdlib(Args))
if (TC.ShouldLinkCXXStdlib(Args)) {
bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
!Args.hasArg(options::OPT_static);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bstatic");
TC.AddCXXStdlibLibArgs(Args, CmdArgs);
if (OnlyLibstdcxxStatic)
CmdArgs.push_back("-Bdynamic");
CmdArgs.push_back("-lm");
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
CmdArgs.push_back("-lc");
CmdArgs.push_back("-lm");
AddRunTimeLibs(TC, D, CmdArgs, Args);

TC.AddLinkRuntimeLib(Args, CmdArgs);
CmdArgs.push_back("-lc");
}

if (D.isUsingLTO()) {
Expand All @@ -561,7 +515,7 @@ void baremetal::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// The R_ARM_TARGET2 relocation must be treated as R_ARM_REL32 on arm*-*-elf
// and arm*-*-eabi (the default is R_ARM_GOT_PREL, used on arm*-*-linux and
// arm*-*-*bsd).
if (isARMBareMetal(TC.getTriple()))
if (arm::isARMEABIBareMetal(TC.getTriple()))
CmdArgs.push_back("--target2=rel");

CmdArgs.push_back("-o");
Expand Down
4 changes: 0 additions & 4 deletions clang/lib/Driver/ToolChains/BareMetal.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,6 @@ class LLVM_LIBRARY_VISIBILITY BareMetal : public ToolChain {
void AddClangCXXStdlibIncludeArgs(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const override;
void AddLinkRuntimeLib(const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) const;
std::string computeSysRoot() const override;
SanitizerMask getSupportedSanitizers() const override;

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "Arch/SystemZ.h"
#include "Arch/VE.h"
#include "Arch/X86.h"
#include "BareMetal.h"
#include "HIPAMD.h"
#include "Hexagon.h"
#include "MSP430.h"
Expand Down Expand Up @@ -151,6 +152,9 @@ static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args,
}
}

if (arm::isARMEABIBareMetal(Triple))
return false;

return true;
}

Expand Down
28 changes: 23 additions & 5 deletions clang/lib/Format/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,33 @@ file(GLOB_RECURSE files

set(check_format_depends)
set(i 0)
foreach (file IN LISTS files)
add_custom_command(OUTPUT clang-format-check-format${i}
foreach(file IN LISTS files)
add_custom_command(OUTPUT check_format_depend_${i}
COMMAND clang-format ${file} | diff -u ${file} -
VERBATIM
COMMENT "Checking format of ${file}..."
COMMENT "Checking format of ${file}"
)
list(APPEND check_format_depends clang-format-check-format${i})
list(APPEND check_format_depends check_format_depend_${i})

math(EXPR i ${i}+1)
endforeach ()
endforeach()

add_custom_target(clang-format-check-format DEPENDS ${check_format_depends})

set(style_options_depends ${CMAKE_CURRENT_BINARY_DIR}/dummy_output)
set(docs_tools_dir ${CLANG_SOURCE_DIR}/docs/tools)
set(style_options_rst ${CLANG_SOURCE_DIR}/docs/ClangFormatStyleOptions.rst)
add_custom_command(OUTPUT ${style_options_depends}
COMMAND ${Python3_EXECUTABLE} dump_format_style.py &&
touch ${style_options_depends}
WORKING_DIRECTORY ${docs_tools_dir}
VERBATIM
COMMENT "Updating ${style_options_rst}"
DEPENDS ${CLANG_SOURCE_DIR}/include/clang/Format/Format.h
${CLANG_SOURCE_DIR}/include/clang/Tooling/Inclusions/IncludeStyle.h
${style_options_rst}
${docs_tools_dir}/plurals.txt
${docs_tools_dir}/dump_format_style.py
)

add_custom_target(clang-format-style-options DEPENDS ${style_options_depends})
1 change: 0 additions & 1 deletion clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ IncrementalCompilerBuilder::CreateCpp() {
#ifdef __EMSCRIPTEN__
Argv.push_back("-target");
Argv.push_back("wasm32-unknown-emscripten");
Argv.push_back("-shared");
Argv.push_back("-fvisibility=default");
#endif
Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
Expand Down
63 changes: 52 additions & 11 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,17 @@ namespace {

struct TemplateParameterListBuilder;

struct BuiltinTypeDeclBuilder {
Sema &SemaRef;
CXXRecordDecl *Record = nullptr;
class BuiltinTypeDeclBuilder {
ClassTemplateDecl *Template = nullptr;
ClassTemplateDecl *PrevTemplate = nullptr;
NamespaceDecl *HLSLNamespace = nullptr;
llvm::StringMap<FieldDecl *> Fields;

public:
Sema &SemaRef;
CXXRecordDecl *Record = nullptr;
friend struct TemplateParameterListBuilder;

BuiltinTypeDeclBuilder(Sema &SemaRef, CXXRecordDecl *R)
: SemaRef(SemaRef), Record(R) {
Record->startDefinition();
Expand All @@ -51,7 +54,7 @@ struct BuiltinTypeDeclBuilder {

BuiltinTypeDeclBuilder(Sema &SemaRef, NamespaceDecl *Namespace,
StringRef Name)
: SemaRef(SemaRef), HLSLNamespace(Namespace) {
: HLSLNamespace(Namespace), SemaRef(SemaRef) {
ASTContext &AST = SemaRef.getASTContext();
IdentifierInfo &II = AST.Idents.get(Name, tok::TokenKind::identifier);

Expand Down Expand Up @@ -91,6 +94,18 @@ struct BuiltinTypeDeclBuilder {
HLSLNamespace->addDecl(Record);
}

CXXRecordDecl *finalizeForwardDeclaration() {
// Force the QualType to be generated for the record declaration. In most
// cases this will happen naturally when something uses the type the
// QualType gets lazily created. Unfortunately, with our injected types if a
// type isn't used in a translation unit the QualType may not get
// automatically generated before a PCH is generated. To resolve this we
// just force that the QualType is generated after we create a forward
// declaration.
(void)Record->getASTContext().getRecordType(Record);
return Record;
}

BuiltinTypeDeclBuilder &
addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef<Attr *> Attrs,
AccessSpecifier Access = AccessSpecifier::AS_private) {
Expand Down Expand Up @@ -849,7 +864,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
constructTypedBufferConceptDecl(*SemaPtr, HLSLNamespace);
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer")
.addSimpleTemplateParams({"element_type"}, TypedBufferConcept)
.Record;
.finalizeForwardDeclaration();

onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
Expand All @@ -862,7 +877,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl =
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
ResourceKind::TypedBuffer, /*IsROV=*/true,
Expand All @@ -873,7 +888,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "StructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -883,7 +898,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -896,7 +911,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl =
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "AppendStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -906,7 +921,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl =
BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ConsumeStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false, /*RawBuffer=*/true)
Expand All @@ -916,7 +931,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"RasterizerOrderedStructuredBuffer")
.addSimpleTemplateParams({"element_type"})
.Record;
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/true, /*RawBuffer=*/true)
Expand All @@ -925,6 +940,32 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addDecrementCounterMethod()
.completeDefinition();
});

Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "ByteAddressBuffer")
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWByteAddressBuffer")
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
.completeDefinition();
});
Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace,
"RasterizerOrderedByteAddressBuffer")
.finalizeForwardDeclaration();
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/true,
/*RawBuffer=*/true)
.completeDefinition();
});
}

void HLSLExternalSemaSource::onCompletion(CXXRecordDecl *Record,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include "clang/AST/ASTLambda.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CommentDiagnostic.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
Expand All @@ -30,6 +29,7 @@
#include "clang/AST/StmtCXX.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticComment.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
Expand Down
17 changes: 9 additions & 8 deletions clang/lib/Sema/SemaExceptionSpec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1205,15 +1205,16 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
if (DTy.isNull() || DTy->isDependentType()) {
CT = CT_Dependent;
} else {
CT = canCalleeThrow(*this, DE, DE->getOperatorDelete());
if (const RecordType *RT = DTy->getAs<RecordType>()) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
const CXXDestructorDecl *DD = RD->getDestructor();
if (DD)
CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD));
const FunctionDecl *OperatorDelete = DE->getOperatorDelete();
CT = canCalleeThrow(*this, DE, OperatorDelete);
if (!OperatorDelete->isDestroyingOperatorDelete()) {
if (const auto *RD = DTy->getAsCXXRecordDecl()) {
if (const CXXDestructorDecl *DD = RD->getDestructor())
CT = mergeCanThrow(CT, canCalleeThrow(*this, DE, DD));
}
if (CT == CT_Can)
return CT;
}
if (CT == CT_Can)
return CT;
}
return mergeCanThrow(CT, canSubStmtsThrow(*this, DE));
}
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11843,7 +11843,9 @@ static void diagnoseTautologicalComparison(Sema &S, SourceLocation Loc,
RHSStripped->getType()->isArrayType()) {
auto IsDeprArrayComparionIgnored =
S.getDiagnostics().isIgnored(diag::warn_depr_array_comparison, Loc);
auto DiagID = !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored
auto DiagID = S.getLangOpts().CPlusPlus26
? diag::warn_array_comparison_cxx26
: !S.getLangOpts().CPlusPlus20 || IsDeprArrayComparionIgnored
? diag::warn_array_comparison
: diag::warn_depr_array_comparison;
S.Diag(Loc, DiagID) << LHS->getSourceRange() << RHS->getSourceRange()
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3747,8 +3747,7 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
} else if (!Pointee->isDependentType()) {
// FIXME: This can result in errors if the definition was imported from a
// module but is hidden.
if (!Pointee->isStructureOrClassType() ||
!RequireCompleteType(StartLoc, Pointee,
if (!RequireCompleteType(StartLoc, Pointee,
LangOpts.CPlusPlus26
? diag::err_delete_incomplete
: diag::warn_delete_incomplete,
Expand Down
Loading