4 changes: 2 additions & 2 deletions clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ class ExceptionAnalyzer {
/// Recalculate the 'Behaviour' for example after filtering.
void reevaluateBehaviour();

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

/// Keep track if the entity contains any unknown elements to keep track
Expand Down
29 changes: 29 additions & 0 deletions clang-tools-extra/clangd/Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,35 @@ bool fromJSON(const llvm::json::Value &Params, ClientCapabilities &R,
if (auto EditsNearCursor = Completion->getBoolean("editsNearCursor"))
R.CompletionFixes |= *EditsNearCursor;
}
if (auto *References = TextDocument->getObject("references")) {
if (auto ContainerSupport = References->getBoolean("container")) {
R.ReferenceContainer |= *ContainerSupport;
}
}
if (auto *Diagnostics = TextDocument->getObject("publishDiagnostics")) {
if (auto CodeActions = Diagnostics->getBoolean("codeActionsInline")) {
R.DiagnosticFixes |= *CodeActions;
}
}
if (auto *InactiveRegions =
TextDocument->getObject("inactiveRegionsCapabilities")) {
if (auto InactiveRegionsSupport =
InactiveRegions->getBoolean("inactiveRegions")) {
R.InactiveRegions |= *InactiveRegionsSupport;
}
}
}
if (auto *Window = Experimental->getObject("window")) {
if (auto Implicit =
Window->getBoolean("implicitWorkDoneProgressCreate")) {
R.ImplicitProgressCreation |= *Implicit;
}
}
if (auto *OffsetEncoding = Experimental->get("offsetEncoding")) {
R.offsetEncoding.emplace();
if (!fromJSON(*OffsetEncoding, *R.offsetEncoding,
P.field("offsetEncoding")))
return false;
}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Class template with member template
{
R"cpp(
template <typename T> struct Foo {
template <typename U> T ^bar(const T& t, const U& u) { return {}; }
};)cpp",
R"cpp(
template <typename T> struct Foo {
template <typename U> T bar(const T& t, const U& u) ;
};template <typename T>
template <typename U>
inline T Foo<T>::bar(const T& t, const U& u) { return {}; }
)cpp",
""},
};
for (const auto &Case : Cases) {
SCOPED_TRACE(Case.Test);
Expand Down
6 changes: 5 additions & 1 deletion clang/cmake/caches/CrossWinToARMLinux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ if (NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "")
endif()

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

# Avoid searching for the python3 interpreter during the runtimes configuration for the cross builds.
# It starts searching the python3 package using the target's sysroot path, that usually is not compatible with the build host.
Expand Down
26 changes: 26 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,8 @@ Non-comprehensive list of changes in this release
issues with the sanitizer because the counter is automatically set.

- ``__builtin_reduce_add`` function can now be used in constant expressions.
- ``__builtin_reduce_mul`` function can now be used in constant expressions.
- ``__builtin_reduce_and`` function can now be used in constant expressions.

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

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

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

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

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

.. code-block:: c++

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

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

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

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

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

- Initial support for gfx950

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

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

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

SourceLocation getRParenLoc() const { return RParenLoc; }
Expand Down
10 changes: 8 additions & 2 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -1498,7 +1498,7 @@ def ReduceOr : Builtin {

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

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

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

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

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

def AtomicSignalFence : Builtin {
let Spellings = ["__atomic_signal_fence"];
let Attributes = [NoThrow];
Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,14 @@ TARGET_BUILTIN(__builtin_amdgcn_cvt_pk_fp8_f32, "iffiIb", "nc", "fp8-conversion-
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_bf8_f32, "ifiiIi", "nc", "fp8-conversion-insts")
TARGET_BUILTIN(__builtin_amdgcn_cvt_sr_fp8_f32, "ifiiIi", "nc", "fp8-conversion-insts")

//===----------------------------------------------------------------------===//
// GFX950 only builtins.
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_16x16x32_f16, "V4fV8hV8hV4fIiIiIi", "nc", "gfx950-insts")
TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_f16, "V16fV8hV8hV16fIiIiIi", "nc", "gfx950-insts")

TARGET_BUILTIN(__builtin_amdgcn_mfma_f32_32x32x16_bf16, "V16fV8yV8yV16fIiIiIi", "nc", "gfx950-insts")

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

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

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

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

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

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

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

def warn_drv_delayed_template_parsing_after_cxx20 : Warning<
"-fdelayed-template-parsing is deprecated after C++20">,
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ def warn_cxx98_compat_defaulted_deleted_function : Warning<
"%select{defaulted|deleted}0 function definitions are incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;

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

let CategoryName = "Refactoring Invocation Issue" in {

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

}

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

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

def warn_asm_label_on_auto_decl : Warning<
"ignored asm label '%0' on automatic variable">;
Expand Down Expand Up @@ -10960,7 +10957,7 @@ def err_opencl_builtin_pipe_invalid_access_modifier : Error<
def err_opencl_invalid_access_qualifier : Error<
"access qualifier can only be used for pipe and image type">;
def err_opencl_invalid_read_write : Error<
"access qualifier %0 can not be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 "
"access qualifier %0 cannot be used for %1 %select{|prior to OpenCL C version 2.0 or in version 3.0 "
"and without __opencl_c_read_write_images feature}2">;
def err_opencl_multiple_access_qualifiers : Error<
"multiple access qualifiers">;
Expand Down Expand Up @@ -11460,7 +11457,7 @@ def err_omp_wrong_linear_modifier : Error<
def err_omp_wrong_linear_modifier_non_reference : Error<
"variable of non-reference type %0 can be used only with 'val' modifier, but used with '%1'">;
def err_omp_step_simple_modifier_exclusive : Error<
"step simple modifier is exclusive and can't be use with 'val', 'uval' or 'ref' modifier">;
"step simple modifier is exclusive and cannot be use with 'val', 'uval' or 'ref' modifier">;
def err_omp_wrong_simdlen_safelen_values : Error<
"the value of 'simdlen' parameter must be less than or equal to the value of the 'safelen' parameter">;
def err_omp_wrong_if_directive_name_modifier : Error<
Expand Down Expand Up @@ -11534,7 +11531,7 @@ def err_omp_schedule_nonmonotonic_static : Error<
def err_omp_simple_clause_incompatible_with_ordered : Error<
"'%0' clause with '%1' modifier cannot be specified if an 'ordered' clause is specified">;
def err_omp_ordered_simd : Error<
"'ordered' clause with a parameter can not be specified in '#pragma omp %0' directive">;
"'ordered' clause with a parameter cannot be specified in '#pragma omp %0' directive">;
def err_omp_variable_in_given_clause_and_dsa : Error<
"%0 variable cannot be in a %1 clause in '#pragma omp %2' directive">;
def err_omp_param_or_this_in_clause : Error<
Expand Down Expand Up @@ -12366,7 +12363,7 @@ def err_preserve_enum_value_not_const: Error<
"__builtin_preserve_enum_value argument %0 not a constant">;

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

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.PointerAuthFuncti
FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos)
FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini)
FEATURE(ptrauth_init_fini_address_discrimination, LangOpts.PointerAuthInitFiniAddressDiscrimination)
FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT)
EXTENSION(swiftcc,
PP.getTargetInfo().checkCallingConvention(CC_Swift) ==
clang::TargetInfo::CCCR_OK)
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/arm_mve.td
Original file line number Diff line number Diff line change
Expand Up @@ -753,8 +753,8 @@ let params = T.Float in {
defm: compare<"ne", fcmp_ne>;
defm: compare<"gt", fcmp_gt>;
defm: compare<"ge", fcmp_ge>;
defm: compare<"lt", fcmp_lt>;
defm: compare<"le", fcmp_le>;
defm: compare<"lt", fcmp_ult>;
defm: compare<"le", fcmp_ule>;
}

let params = T.Signed in {
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/arm_mve_defs.td
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ def fcmp_eq: IRBuilder<"CreateFCmpOEQ">;
def fcmp_ne: IRBuilder<"CreateFCmpUNE">; // not O: it must return true on NaNs
def fcmp_gt: IRBuilder<"CreateFCmpOGT">;
def fcmp_ge: IRBuilder<"CreateFCmpOGE">;
def fcmp_lt: IRBuilder<"CreateFCmpOLT">;
def fcmp_le: IRBuilder<"CreateFCmpOLE">;
def fcmp_ult: IRBuilder<"CreateFCmpULT">;
def fcmp_ule: IRBuilder<"CreateFCmpULE">;
def splat: CGHelperFn<"ARMMVEVectorSplat">;
def select: IRBuilder<"CreateSelect">;
def fneg: IRBuilder<"CreateFNeg">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4356,6 +4356,7 @@ defm ptrauth_indirect_gotos : OptInCC1FFlag<"ptrauth-indirect-gotos",
defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">;
defm ptrauth_init_fini_address_discrimination : OptInCC1FFlag<"ptrauth-init-fini-address-discrimination",
"Enable address discrimination of function pointers in init/fini arrays">;
defm ptrauth_elf_got : OptInCC1FFlag<"ptrauth-elf-got", "Enable authentication of pointers from GOT (ELF only)">;
}

def fenable_matrix : Flag<["-"], "fenable-matrix">, Group<f_Group>,
Expand Down
8 changes: 7 additions & 1 deletion clang/include/clang/Frontend/FrontendAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
Expand Down Expand Up @@ -185,7 +186,12 @@ class FrontendAction {
virtual bool usesPreprocessorOnly() const = 0;

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

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

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

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

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

Expand Down
7 changes: 3 additions & 4 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace serialization {
/// Version 4 of AST files also requires that the version control branch and
/// revision match exactly, since there is no backward compatibility of
/// AST files at this time.
const unsigned VERSION_MAJOR = 33;
const unsigned VERSION_MAJOR = 34;

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

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

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

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

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

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

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

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

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

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

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

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

/// Emit the current record with the given path as a blob.
void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
Expand Down
18 changes: 10 additions & 8 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1615,22 +1615,24 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const {
return FnType->getReturnType();
}

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

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

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

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

SourceLocation CallExpr::getBeginLoc() const {
Expand Down
28 changes: 24 additions & 4 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13527,18 +13527,38 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(DidOverflow, E);
}

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

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

return Success(Reduced, E);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ static const OffloadArchToStringMap arch_names[] = {
GFX(940), // gfx940
GFX(941), // gfx941
GFX(942), // gfx942
GFX(950), // gfx950
{OffloadArch::GFX10_1_GENERIC, "gfx10-1-generic", "compute_amdgcn"},
GFX(1010), // gfx1010
GFX(1011), // gfx1011
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/NVPTX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ void NVPTXTargetInfo::getTargetDefines(const LangOptions &Opts,
case OffloadArch::GFX940:
case OffloadArch::GFX941:
case OffloadArch::GFX942:
case OffloadArch::GFX950:
case OffloadArch::GFX10_1_GENERIC:
case OffloadArch::GFX1010:
case OffloadArch::GFX1011:
Expand Down
130 changes: 130 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5213,6 +5213,136 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
Builder.SetInsertPoint(ContBB);
return RValue::get(nullptr);
}
case Builtin::BI__scoped_atomic_thread_fence: {
auto ScopeModel = AtomicScopeModel::create(AtomicScopeModelKind::Generic);

Value *Order = EmitScalarExpr(E->getArg(0));
Value *Scope = EmitScalarExpr(E->getArg(1));
auto Ord = dyn_cast<llvm::ConstantInt>(Order);
auto Scp = dyn_cast<llvm::ConstantInt>(Scope);
if (Ord && Scp) {
SyncScope SS = ScopeModel->isValid(Scp->getZExtValue())
? ScopeModel->map(Scp->getZExtValue())
: ScopeModel->map(ScopeModel->getFallBackValue());
switch (Ord->getZExtValue()) {
case 0: // memory_order_relaxed
default: // invalid order
break;
case 1: // memory_order_consume
case 2: // memory_order_acquire
Builder.CreateFence(
llvm::AtomicOrdering::Acquire,
getTargetHooks().getLLVMSyncScopeID(getLangOpts(), SS,
llvm::AtomicOrdering::Acquire,
getLLVMContext()));
break;
case 3: // memory_order_release
Builder.CreateFence(
llvm::AtomicOrdering::Release,
getTargetHooks().getLLVMSyncScopeID(getLangOpts(), SS,
llvm::AtomicOrdering::Release,
getLLVMContext()));
break;
case 4: // memory_order_acq_rel
Builder.CreateFence(llvm::AtomicOrdering::AcquireRelease,
getTargetHooks().getLLVMSyncScopeID(
getLangOpts(), SS,
llvm::AtomicOrdering::AcquireRelease,
getLLVMContext()));
break;
case 5: // memory_order_seq_cst
Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
getTargetHooks().getLLVMSyncScopeID(
getLangOpts(), SS,
llvm::AtomicOrdering::SequentiallyConsistent,
getLLVMContext()));
break;
}
return RValue::get(nullptr);
}

llvm::BasicBlock *ContBB = createBasicBlock("atomic.scope.continue", CurFn);

llvm::SmallVector<std::pair<llvm::BasicBlock *, llvm::AtomicOrdering>>
OrderBBs;
if (Ord) {
switch (Ord->getZExtValue()) {
case 0: // memory_order_relaxed
default: // invalid order
ContBB->eraseFromParent();
return RValue::get(nullptr);
case 1: // memory_order_consume
case 2: // memory_order_acquire
OrderBBs.emplace_back(Builder.GetInsertBlock(),
llvm::AtomicOrdering::Acquire);
break;
case 3: // memory_order_release
OrderBBs.emplace_back(Builder.GetInsertBlock(),
llvm::AtomicOrdering::Release);
break;
case 4: // memory_order_acq_rel
OrderBBs.emplace_back(Builder.GetInsertBlock(),
llvm::AtomicOrdering::AcquireRelease);
break;
case 5: // memory_order_seq_cst
OrderBBs.emplace_back(Builder.GetInsertBlock(),
llvm::AtomicOrdering::SequentiallyConsistent);
break;
}
} else {
llvm::BasicBlock *AcquireBB = createBasicBlock("acquire", CurFn);
llvm::BasicBlock *ReleaseBB = createBasicBlock("release", CurFn);
llvm::BasicBlock *AcqRelBB = createBasicBlock("acqrel", CurFn);
llvm::BasicBlock *SeqCstBB = createBasicBlock("seqcst", CurFn);

Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false);
llvm::SwitchInst *SI = Builder.CreateSwitch(Order, ContBB);
SI->addCase(Builder.getInt32(1), AcquireBB);
SI->addCase(Builder.getInt32(2), AcquireBB);
SI->addCase(Builder.getInt32(3), ReleaseBB);
SI->addCase(Builder.getInt32(4), AcqRelBB);
SI->addCase(Builder.getInt32(5), SeqCstBB);

OrderBBs.emplace_back(AcquireBB, llvm::AtomicOrdering::Acquire);
OrderBBs.emplace_back(ReleaseBB, llvm::AtomicOrdering::Release);
OrderBBs.emplace_back(AcqRelBB, llvm::AtomicOrdering::AcquireRelease);
OrderBBs.emplace_back(SeqCstBB,
llvm::AtomicOrdering::SequentiallyConsistent);
}

for (auto &[OrderBB, Ordering] : OrderBBs) {
Builder.SetInsertPoint(OrderBB);
if (Scp) {
SyncScope SS = ScopeModel->isValid(Scp->getZExtValue())
? ScopeModel->map(Scp->getZExtValue())
: ScopeModel->map(ScopeModel->getFallBackValue());
Builder.CreateFence(Ordering,
getTargetHooks().getLLVMSyncScopeID(
getLangOpts(), SS, Ordering, getLLVMContext()));
Builder.CreateBr(ContBB);
} else {
llvm::DenseMap<unsigned, llvm::BasicBlock *> BBs;
for (unsigned Scp : ScopeModel->getRuntimeValues())
BBs[Scp] = createBasicBlock(getAsString(ScopeModel->map(Scp)), CurFn);

auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false);
llvm::SwitchInst *SI = Builder.CreateSwitch(SC, ContBB);
for (unsigned Scp : ScopeModel->getRuntimeValues()) {
auto *B = BBs[Scp];
SI->addCase(Builder.getInt32(Scp), B);

Builder.SetInsertPoint(B);
Builder.CreateFence(Ordering, getTargetHooks().getLLVMSyncScopeID(
getLangOpts(), ScopeModel->map(Scp),
Ordering, getLLVMContext()));
Builder.CreateBr(ContBB);
}
}
}

Builder.SetInsertPoint(ContBB);
return RValue::get(nullptr);
}

case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGExprComplex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ ComplexPairTy ComplexExprEmitter::VisitExpr(Expr *E) {
CGF.ErrorUnsupported(E, "complex expression");
llvm::Type *EltTy =
CGF.ConvertType(getComplexType(E->getType())->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
llvm::Value *U = llvm::PoisonValue::get(EltTy);
return ComplexPairTy(U, U);
}

Expand Down Expand Up @@ -1449,7 +1449,7 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
CGF.ErrorUnsupported(E, "complex va_arg expression");
llvm::Type *EltTy =
CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
llvm::Value *U = llvm::UndefValue::get(EltTy);
llvm::Value *U = llvm::PoisonValue::get(EltTy);
return ComplexPairTy(U, U);
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1828,7 +1828,7 @@ Value *ScalarExprEmitter::VisitExpr(Expr *E) {
CGF.ErrorUnsupported(E, "scalar expression");
if (E->getType()->isVoidType())
return nullptr;
return llvm::UndefValue::get(CGF.ConvertType(E->getType()));
return llvm::PoisonValue::get(CGF.ConvertType(E->getType()));
}

Value *
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2304,6 +2304,7 @@ void CGOpenMPRuntimeGPU::processRequiresDirective(const OMPRequiresDecl *D) {
case OffloadArch::GFX940:
case OffloadArch::GFX941:
case OffloadArch::GFX942:
case OffloadArch::GFX950:
case OffloadArch::GFX10_1_GENERIC:
case OffloadArch::GFX1010:
case OffloadArch::GFX1011:
Expand Down
12 changes: 8 additions & 4 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ void CodeGenFunction::FinishFunction(SourceLocation EndLoc) {
if (IndirectBranch) {
llvm::PHINode *PN = cast<llvm::PHINode>(IndirectBranch->getAddress());
if (PN->getNumIncomingValues() == 0) {
PN->replaceAllUsesWith(llvm::UndefValue::get(PN->getType()));
PN->replaceAllUsesWith(llvm::PoisonValue::get(PN->getType()));
PN->eraseFromParent();
}
}
Expand Down Expand Up @@ -635,7 +635,9 @@ void CodeGenFunction::EmitKernelMetadata(const FunctionDecl *FD,

CGM.GenKernelArgMetadata(Fn, FD, this);

if (!getLangOpts().OpenCL)
if (!(getLangOpts().OpenCL ||
(getLangOpts().CUDA &&
getContext().getTargetInfo().getTriple().isSPIRV())))
return;

if (const VecTypeHintAttr *A = FD->getAttr<VecTypeHintAttr>()) {
Expand Down Expand Up @@ -1022,6 +1024,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
}

if (FD && (getLangOpts().OpenCL ||
(getLangOpts().CUDA &&
getContext().getTargetInfo().getTriple().isSPIRV()) ||
((getLangOpts().HIP || getLangOpts().OffloadViaLLVM) &&
getLangOpts().CUDAIsDevice))) {
// Add metadata for a kernel function.
Expand Down Expand Up @@ -1106,8 +1110,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
// Create a marker to make it easy to insert allocas into the entryblock
// later. Don't create this with the builder, because we don't want it
// folded.
llvm::Value *Undef = llvm::UndefValue::get(Int32Ty);
AllocaInsertPt = new llvm::BitCastInst(Undef, Int32Ty, "allocapt", EntryBB);
llvm::Value *Poison = llvm::PoisonValue::get(Int32Ty);
AllocaInsertPt = new llvm::BitCastInst(Poison, Int32Ty, "allocapt", EntryBB);

ReturnBlock = getJumpDestInCurrentScope("return");

Expand Down
7 changes: 5 additions & 2 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,7 @@ void CodeGenModule::checkAliases() {
for (const GlobalDecl &GD : Aliases) {
StringRef MangledName = getMangledName(GD);
llvm::GlobalValue *Alias = GetGlobalValue(MangledName);
Alias->replaceAllUsesWith(llvm::UndefValue::get(Alias->getType()));
Alias->replaceAllUsesWith(llvm::PoisonValue::get(Alias->getType()));
Alias->eraseFromParent();
}
}
Expand Down Expand Up @@ -1213,6 +1213,9 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Min,
"sign-return-address-with-bkey", 1);

if (LangOpts.PointerAuthELFGOT)
getModule().addModuleFlag(llvm::Module::Min, "ptrauth-elf-got", 1);

if (getTriple().isOSLinux()) {
assert(getTriple().isOSBinFormatELF());
using namespace llvm::ELF;
Expand Down Expand Up @@ -5569,7 +5572,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
}
} else {
ErrorUnsupported(D, "static initializer");
Init = llvm::UndefValue::get(getTypes().ConvertType(T));
Init = llvm::PoisonValue::get(getTypes().ConvertType(T));
}
} else {
Init = Initializer;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1554,7 +1554,7 @@ class AnnotatingParser {
};

if (IsInstancePort())
Tok->setFinalizedType(TT_VerilogInstancePortLParen);
Tok->setType(TT_VerilogInstancePortLParen);
}

if (!parseParens())
Expand Down Expand Up @@ -1730,7 +1730,7 @@ class AnnotatingParser {
Tok->setType(TT_InheritanceComma);
break;
case Context::VerilogInstancePortList:
Tok->setFinalizedType(TT_VerilogInstancePortComma);
Tok->setType(TT_VerilogInstancePortComma);
break;
default:
if (Style.isVerilog() && Contexts.size() == 1 &&
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4441,7 +4441,8 @@ unsigned UnwrappedLineParser::parseVerilogHierarchyHeader() {
Prev->setFinalizedType(TT_VerilogDimensionedTypeName);
parseSquare();
} else if (Keywords.isVerilogIdentifier(*FormatTok) ||
FormatTok->isOneOf(Keywords.kw_automatic, tok::kw_static)) {
FormatTok->isOneOf(tok::hash, tok::hashhash, tok::coloncolon,
Keywords.kw_automatic, tok::kw_static)) {
nextToken();
} else {
break;
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3452,6 +3452,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts,
GenerateArg(Consumer, OPT_fptrauth_init_fini);
if (Opts.PointerAuthInitFiniAddressDiscrimination)
GenerateArg(Consumer, OPT_fptrauth_init_fini_address_discrimination);
if (Opts.PointerAuthELFGOT)
GenerateArg(Consumer, OPT_fptrauth_elf_got);
}

static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Expand All @@ -3472,6 +3474,7 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args,
Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini);
Opts.PointerAuthInitFiniAddressDiscrimination =
Args.hasArg(OPT_fptrauth_init_fini_address_discrimination);
Opts.PointerAuthELFGOT = Args.hasArg(OPT_fptrauth_elf_got);
}

/// Check if input file kind and language standard are compatible.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Headers/lasxintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -2585,7 +2585,7 @@ extern __inline
extern __inline
__attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m256i
__lasx_xvorn_v(__m256i _1, __m256i _2) {
return (__m256i)__builtin_lasx_xvorn_v((v32i8)_1, (v32i8)_2);
return (__m256i)__builtin_lasx_xvorn_v((v32u8)_1, (v32u8)_2);
}

#define __lasx_xvldi(/*i13*/ _1) ((__m256i)__builtin_lasx_xvldi((_1)))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Headers/lsxintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -3425,7 +3425,7 @@ extern __inline
extern __inline
__attribute__((__gnu_inline__, __always_inline__, __artificial__)) __m128i
__lsx_vorn_v(__m128i _1, __m128i _2) {
return (__m128i)__builtin_lsx_vorn_v((v16i8)_1, (v16i8)_2);
return (__m128i)__builtin_lsx_vorn_v((v16u8)_1, (v16u8)_2);
}

#define __lsx_vldi(/*i13*/ _1) ((__m128i)__builtin_lsx_vldi((_1)))
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Interpreter/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ set(LLVM_LINK_COMPONENTS
Support
Target
TargetParser
)
TransformUtils
)

if (EMSCRIPTEN AND "lld" IN_LIST LLVM_ENABLE_PROJECTS)
set(WASM_SRC Wasm.cpp)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Interpreter/IncrementalExecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class IncrementalExecutor {
virtual llvm::Error addModule(PartialTranslationUnit &PTU);
virtual llvm::Error removeModule(PartialTranslationUnit &PTU);
virtual llvm::Error runCtors() const;
llvm::Error cleanUp();
virtual llvm::Error cleanUp();
llvm::Expected<llvm::orc::ExecutorAddr>
getSymbolAddress(llvm::StringRef Name, SymbolNameKind NameKind) const;

Expand Down
72 changes: 43 additions & 29 deletions clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/Transforms/Utils/Cloning.h" // for CloneModule

#define DEBUG_TYPE "clang-repl"

using namespace clang;
// FIXME: Figure out how to unify with namespace init_convenience from
Expand Down Expand Up @@ -196,7 +199,6 @@ IncrementalCompilerBuilder::CreateCpp() {
#ifdef __EMSCRIPTEN__
Argv.push_back("-target");
Argv.push_back("wasm32-unknown-emscripten");
Argv.push_back("-pie");
Argv.push_back("-shared");
#endif
Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());
Expand Down Expand Up @@ -339,19 +341,8 @@ class IncrementalAction : public WrapperFrontendAction {
}

void ExecuteAction() override {
CompilerInstance &CI = getCompilerInstance();
assert(CI.hasPreprocessor() && "No PP!");

// Use a code completion consumer?
CodeCompleteConsumer *CompletionConsumer = nullptr;
if (CI.hasCodeCompletionConsumer())
CompletionConsumer = &CI.getCodeCompletionConsumer();

Preprocessor &PP = CI.getPreprocessor();
PP.EnterMainSourceFile();

if (!CI.hasSema())
CI.createSema(getTranslationUnitKind(), CompletionConsumer);
WrapperFrontendAction::ExecuteAction();
getCompilerInstance().getSema().CurContext = nullptr;
}

// Do not terminate after processing the input. This allows us to keep various
Expand Down Expand Up @@ -385,27 +376,29 @@ Interpreter::Interpreter(std::unique_ptr<CompilerInstance> Instance,
return;
CI->ExecuteAction(*Act);

ASTContext &C = CI->getASTContext();

IncrParser = std::make_unique<IncrementalParser>(*CI, ErrOut);

if (ErrOut)
return;

if (getCodeGen()) {
CachedInCodeGenModule = GenModule();
// The initial PTU is filled by `-include` or by CUDA includes
// automatically.
if (!CI->getPreprocessorOpts().Includes.empty()) {
// We can't really directly pass the CachedInCodeGenModule to the Jit
// because it will steal it, causing dangling references as explained in
// Interpreter::Execute
auto M = llvm::CloneModule(*CachedInCodeGenModule);
ASTContext &C = CI->getASTContext();
RegisterPTU(C.getTranslationUnitDecl(), std::move(M));
}
if (llvm::Error Err = CreateExecutor()) {
ErrOut = joinErrors(std::move(ErrOut), std::move(Err));
return;
}
}

// The initial PTU is filled by `-include` or by CUDA includes automatically.
RegisterPTU(C.getTranslationUnitDecl());

// Prepare the IncrParser for input.
llvm::cantFail(Parse(""));

// Not all frontends support code-generation, e.g. ast-dump actions don't
if (getCodeGen()) {
// Process the PTUs that came from initialization. For example -include will
Expand Down Expand Up @@ -535,14 +528,25 @@ size_t Interpreter::getEffectivePTUSize() const {
return PTUs.size() - InitPTUSize;
}

PartialTranslationUnit &Interpreter::RegisterPTU(TranslationUnitDecl *TU) {
PartialTranslationUnit &
Interpreter::RegisterPTU(TranslationUnitDecl *TU,
std::unique_ptr<llvm::Module> M /*={}*/) {
PTUs.emplace_back(PartialTranslationUnit());
PartialTranslationUnit &LastPTU = PTUs.back();
LastPTU.TUPart = TU;

if (std::unique_ptr<llvm::Module> M = GenModule())
LastPTU.TheModule = std::move(M);
if (!M)
M = GenModule();

assert((!getCodeGen() || M) && "Must have a llvm::Module at this point");

LastPTU.TheModule = std::move(M);
LLVM_DEBUG(llvm::dbgs() << "compile-ptu " << PTUs.size() - 1
<< ": [TU=" << LastPTU.TUPart);
if (LastPTU.TheModule)
LLVM_DEBUG(llvm::dbgs() << ", M=" << LastPTU.TheModule.get() << " ("
<< LastPTU.TheModule->getName() << ")");
LLVM_DEBUG(llvm::dbgs() << "]\n");
return LastPTU;
}

Expand Down Expand Up @@ -615,6 +619,14 @@ void Interpreter::ResetExecutor() { IncrExecutor.reset(); }

llvm::Error Interpreter::Execute(PartialTranslationUnit &T) {
assert(T.TheModule);
LLVM_DEBUG(llvm::dbgs()
<< "execute-ptu "
<< ((std::find(PTUs.begin(), PTUs.end(), T) != PTUs.end())
? std::distance(PTUs.begin(),
std::find(PTUs.begin(), PTUs.end(), T))
: -1)
<< ": [TU=" << T.TUPart << ", M=" << T.TheModule.get() << " ("
<< T.TheModule->getName() << ")]\n");
if (!IncrExecutor) {
auto Err = CreateExecutor();
if (Err)
Expand Down Expand Up @@ -723,10 +735,12 @@ std::unique_ptr<llvm::Module> Interpreter::GenModule() {
// of the module which does not map well to CodeGen's design. To work this
// around we created an empty module to make CodeGen happy. We should make
// sure it always stays empty.
assert((!CachedInCodeGenModule || (CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
CachedInCodeGenModule->ifunc_empty())) &&
assert(((!CachedInCodeGenModule ||
!getCompilerInstance()->getPreprocessorOpts().Includes.empty()) ||
(CachedInCodeGenModule->empty() &&
CachedInCodeGenModule->global_empty() &&
CachedInCodeGenModule->alias_empty() &&
CachedInCodeGenModule->ifunc_empty())) &&
"CodeGen wrote to a readonly module");
std::unique_ptr<llvm::Module> M(CG->ReleaseModule());
CG->StartModule("incr_module_" + std::to_string(ID++), M->getContext());
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Interpreter/Wasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ llvm::Error WasmIncrementalExecutor::addModule(PartialTranslationUnit &PTU) {
OutputFile.close();

std::vector<const char *> LinkerArgs = {"wasm-ld",
"-pie",
"-shared",
"--import-memory",
"--no-entry",
"--export-all",
"--experimental-pic",
"--no-export-dynamic",
"--stack-first",
"--allow-undefined",
OutputFileName.c_str(),
"-o",
OutputFileName.c_str()};
Expand Down Expand Up @@ -109,6 +109,12 @@ llvm::Error WasmIncrementalExecutor::runCtors() const {
return llvm::Error::success();
}

llvm::Error WasmIncrementalExecutor::cleanUp() const {
// Can't call cleanUp through IncrementalExecutor as it
// tries to deinitialize JIT which hasn't been initialized
return llvm::Error::success();
}

WasmIncrementalExecutor::~WasmIncrementalExecutor() = default;

} // namespace clang
1 change: 1 addition & 0 deletions clang/lib/Interpreter/Wasm.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class WasmIncrementalExecutor : public IncrementalExecutor {
llvm::Error addModule(PartialTranslationUnit &PTU) override;
llvm::Error removeModule(PartialTranslationUnit &PTU) override;
llvm::Error runCtors() const override;
llvm::Error cleanUp() override;

~WasmIncrementalExecutor() override;
};
Expand Down
17 changes: 13 additions & 4 deletions clang/lib/Parse/ParseObjc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,

SmallVector<const IdentifierInfo *, 12> KeyIdents;
SmallVector<SourceLocation, 12> KeyLocs;
SmallVector<ParmVarDecl *, 12> ObjCParamInfo;
SmallVector<SemaObjC::ObjCArgInfo, 12> ArgInfos;
ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
Scope::FunctionDeclarationScope | Scope::DeclScope);

Expand Down Expand Up @@ -1495,9 +1495,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
ArgInfo.NameLoc = Tok.getLocation();
ConsumeToken(); // Eat the identifier.

ParmVarDecl *Param = Actions.ObjC().ActOnMethodParmDeclaration(
getCurScope(), ArgInfo, ObjCParamInfo.size(), MethodDefinition);
ObjCParamInfo.push_back(Param);
ArgInfos.push_back(ArgInfo);
KeyIdents.push_back(SelIdent);
KeyLocs.push_back(selLoc);

Expand Down Expand Up @@ -1557,6 +1555,17 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
nullptr));
}

// Turn ArgInfos into parameters. This must happen after parsing all
// parameters for bug compatibility with previous versions of Clang. (For
// instance, if a method declares a parameter called "id", that parameter must
// not shadow the "id" type.)
SmallVector<ParmVarDecl *, 12> ObjCParamInfo;
for (auto &ArgInfo : ArgInfos) {
ParmVarDecl *Param = Actions.ObjC().ActOnMethodParmDeclaration(
getCurScope(), ArgInfo, ObjCParamInfo.size(), MethodDefinition);
ObjCParamInfo.push_back(Param);
}

// FIXME: Add support for optional parameter list...
// If attributes exist after the method, parse them.
MaybeParseAttributes(PAKM_CXX11 | (getLangOpts().ObjC ? PAKM_GNU : 0),
Expand Down
23 changes: 16 additions & 7 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2262,19 +2262,28 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
MsgParam = 5;
} else if (const auto *ECE = dyn_cast<ExplicitCastExpr>(Operation)) {
QualType destType = ECE->getType();
bool destTypeComplete = true;

if (!isa<PointerType>(destType))
return;
destType = destType.getTypePtr()->getPointeeType();
if (const auto *D = destType->getAsTagDecl())
destTypeComplete = D->isCompleteDefinition();

const uint64_t dSize =
Ctx.getTypeSize(destType.getTypePtr()->getPointeeType());
// If destination type is incomplete, it is unsafe to cast to anyway, no
// need to check its type:
if (destTypeComplete) {
const uint64_t dSize = Ctx.getTypeSize(destType);
QualType srcType = ECE->getSubExpr()->getType();

QualType srcType = ECE->getSubExpr()->getType();
const uint64_t sSize =
Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());
assert(srcType->isPointerType());

if (sSize >= dSize)
return;
const uint64_t sSize =
Ctx.getTypeSize(srcType.getTypePtr()->getPointeeType());

if (sSize >= dSize)
return;
}
if (const auto *CE = dyn_cast<CXXMemberCallExpr>(
ECE->getSubExpr()->IgnoreParens())) {
D = CE->getMethodDecl();
Expand Down
4 changes: 1 addition & 3 deletions clang/lib/Sema/CheckExprLifetime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,9 +1095,7 @@ static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path) {
}

static bool isAssignmentOperatorLifetimeBound(CXXMethodDecl *CMD) {
if (!CMD)
return false;
return isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 &&
return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 &&
CMD->getParamDecl(0)->hasAttr<LifetimeBoundAttr>();
}

Expand Down
25 changes: 10 additions & 15 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ struct BuiltinTypeDeclBuilder {
Attr *ResourceAttr = HLSLResourceAttr::CreateImplicit(Ctx, RK);
if (CreateHLSLAttributedResourceType(S, Ctx.HLSLResourceTy, Attrs,
AttributedResTy))
addMemberVariable("h", AttributedResTy, {ResourceAttr}, Access);
addMemberVariable("__handle", AttributedResTy, {ResourceAttr}, Access);
return *this;
}

Expand Down Expand Up @@ -212,11 +212,11 @@ struct BuiltinTypeDeclBuilder {

// Subscript operators return references to elements, const makes the
// reference and method const so that the underlying data is not mutable.
ReturnTy = AST.getLValueReferenceType(ReturnTy);
if (IsConst) {
ExtInfo.TypeQuals.addConst();
ReturnTy.addConst();
}
ReturnTy = AST.getLValueReferenceType(ReturnTy);

QualType MethodTy =
AST.getFunctionType(ReturnTy, {AST.UnsignedIntTy}, ExtInfo);
Expand Down Expand Up @@ -480,8 +480,8 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
ResourceKind::TypedBuffer,
/*IsROV=*/false, /*RawBuffer=*/false)
ResourceKind::TypedBuffer, /*IsROV=*/false,
/*RawBuffer=*/false)
.addArraySubscriptOperators()
.completeDefinition();
});
Expand All @@ -503,8 +503,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.Record;
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::SRV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
/*IsROV=*/false, /*RawBuffer=*/true)
.addArraySubscriptOperators()
.completeDefinition();
});
Expand All @@ -514,8 +513,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.Record;
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
/*IsROV=*/false, /*RawBuffer=*/true)
.addArraySubscriptOperators()
.completeDefinition();
});
Expand All @@ -526,8 +524,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.Record;
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
/*IsROV=*/false, /*RawBuffer=*/true)
.completeDefinition();
});

Expand All @@ -537,8 +534,7 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.Record;
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/false,
/*RawBuffer=*/true)
/*IsROV=*/false, /*RawBuffer=*/true)
.completeDefinition();
});

Expand All @@ -547,9 +543,8 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {
.addSimpleTemplateParams(*SemaPtr, {"element_type"})
.Record;
onCompletion(Decl, [this](CXXRecordDecl *Decl) {
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV,
ResourceKind::TypedBuffer, /*IsROV=*/true,
/*RawBuffer=*/true)
setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, ResourceKind::RawBuffer,
/*IsROV=*/true, /*RawBuffer=*/true)
.addArraySubscriptOperators()
.completeDefinition();
});
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/Sema/JumpDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ static ScopePair GetDiagForGotoScopeDecl(Sema &S, const Decl *D) {
}
}

const Expr *Init = VD->getInit();
if (S.Context.getLangOpts().CPlusPlus && VD->hasLocalStorage() && Init &&
!Init->containsErrors()) {
if (const Expr *Init = VD->getInit(); S.Context.getLangOpts().CPlusPlus &&
VD->hasLocalStorage() && Init &&
!Init->containsErrors()) {
// C++11 [stmt.dcl]p3:
// A program that jumps from a point where a variable with automatic
// storage duration is not in scope to a point where it is in scope
Expand Down
11 changes: 8 additions & 3 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8350,9 +8350,15 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
return;

// Only warn about certain kinds of shadowing for class members.
if (NewDC && NewDC->isRecord()) {
if (NewDC) {
// In particular, don't warn about shadowing non-class members.
if (!OldDC->isRecord())
if (NewDC->isRecord() && !OldDC->isRecord())
return;

// Skip shadowing check if we're in a class scope, dealing with an enum
// constant in a different context.
DeclContext *ReDC = NewDC->getRedeclContext();
if (ReDC->isRecord() && isa<EnumConstantDecl>(D) && !OldDC->Equals(ReDC))
return;

// TODO: should we warn about static data members shadowing
Expand All @@ -8363,7 +8369,6 @@ void Sema::CheckShadow(NamedDecl *D, NamedDecl *ShadowedDecl,
// shadowing context, but that's just a false negative.
}


DeclarationName Name = R.getLookupName();

// Emit warning and note.
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7368,7 +7368,9 @@ void Sema::ProcessDeclAttributeList(
// good to have a way to specify "these attributes must appear as a group",
// for these. Additionally, it would be good to have a way to specify "these
// attribute must never appear as a group" for attributes like cold and hot.
if (!D->hasAttr<OpenCLKernelAttr>()) {
if (!(D->hasAttr<OpenCLKernelAttr>() ||
(D->hasAttr<CUDAGlobalAttr>() &&
Context.getTargetInfo().getTriple().isSPIRV()))) {
// These attributes cannot be applied to a non-kernel function.
if (const auto *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
// FIXME: This emits a different error message than
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,8 @@ class Analyzer {

auto MaybeAddTemplateNote = [&](const Decl *D) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
while (FD != nullptr && FD->isTemplateInstantiation()) {
while (FD != nullptr && FD->isTemplateInstantiation() &&
FD->getPointOfInstantiation().isValid()) {
S.Diag(FD->getPointOfInstantiation(),
diag::note_func_effect_from_template);
FD = FD->getTemplateInstantiationPattern();
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaLambda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1950,8 +1950,6 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) {
LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back());
ActOnFinishFunctionBody(LSI.CallOperator, Body);

maybeAddDeclWithEffects(LSI.CallOperator);

return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI);
}

Expand Down Expand Up @@ -2284,6 +2282,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
break;
}
maybeAddDeclWithEffects(LSI->CallOperator);
}

return MaybeBindToTemporary(Lambda);
Expand Down
47 changes: 30 additions & 17 deletions clang/lib/Sema/SemaStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,30 @@ static bool DiagnoseUnusedComparison(Sema &S, const Expr *E) {
return true;
}

static bool DiagnoseNoDiscard(Sema &S, const WarnUnusedResultAttr *A,
SourceLocation Loc, SourceRange R1,
SourceRange R2, bool IsCtor) {
static bool DiagnoseNoDiscard(Sema &S, const NamedDecl *OffendingDecl,
const WarnUnusedResultAttr *A, SourceLocation Loc,
SourceRange R1, SourceRange R2, bool IsCtor) {
if (!A)
return false;
StringRef Msg = A->getMessage();

if (Msg.empty()) {
if (OffendingDecl)
return S.Diag(Loc, diag::warn_unused_return_type)
<< IsCtor << A << OffendingDecl << false << R1 << R2;
if (IsCtor)
return S.Diag(Loc, diag::warn_unused_constructor) << A << R1 << R2;
return S.Diag(Loc, diag::warn_unused_result) << A << R1 << R2;
return S.Diag(Loc, diag::warn_unused_constructor)
<< A << false << R1 << R2;
return S.Diag(Loc, diag::warn_unused_result) << A << false << R1 << R2;
}

if (OffendingDecl)
return S.Diag(Loc, diag::warn_unused_return_type)
<< IsCtor << A << OffendingDecl << true << Msg << R1 << R2;
if (IsCtor)
return S.Diag(Loc, diag::warn_unused_constructor_msg) << A << Msg << R1
<< R2;
return S.Diag(Loc, diag::warn_unused_result_msg) << A << Msg << R1 << R2;
return S.Diag(Loc, diag::warn_unused_constructor)
<< A << true << Msg << R1 << R2;
return S.Diag(Loc, diag::warn_unused_result) << A << true << Msg << R1 << R2;
}

void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
Expand Down Expand Up @@ -286,9 +293,10 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
if (E->getType()->isVoidType())
return;

if (DiagnoseNoDiscard(*this, cast_or_null<WarnUnusedResultAttr>(
CE->getUnusedResultAttr(Context)),
Loc, R1, R2, /*isCtor=*/false))
auto [OffendingDecl, A] = CE->getUnusedResultAttr(Context);
if (DiagnoseNoDiscard(*this, OffendingDecl,
cast_or_null<WarnUnusedResultAttr>(A), Loc, R1, R2,
/*isCtor=*/false))
return;

// If the callee has attribute pure, const, or warn_unused_result, warn with
Expand All @@ -309,16 +317,21 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
}
} else if (const auto *CE = dyn_cast<CXXConstructExpr>(E)) {
if (const CXXConstructorDecl *Ctor = CE->getConstructor()) {
const NamedDecl *OffendingDecl = nullptr;
const auto *A = Ctor->getAttr<WarnUnusedResultAttr>();
A = A ? A : Ctor->getParent()->getAttr<WarnUnusedResultAttr>();
if (DiagnoseNoDiscard(*this, A, Loc, R1, R2, /*isCtor=*/true))
if (!A) {
OffendingDecl = Ctor->getParent();
A = OffendingDecl->getAttr<WarnUnusedResultAttr>();
}
if (DiagnoseNoDiscard(*this, OffendingDecl, A, Loc, R1, R2,
/*isCtor=*/true))
return;
}
} else if (const auto *ILE = dyn_cast<InitListExpr>(E)) {
if (const TagDecl *TD = ILE->getType()->getAsTagDecl()) {

if (DiagnoseNoDiscard(*this, TD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
R2, /*isCtor=*/false))
if (DiagnoseNoDiscard(*this, TD, TD->getAttr<WarnUnusedResultAttr>(), Loc,
R1, R2, /*isCtor=*/false))
return;
}
} else if (ShouldSuppress)
Expand All @@ -332,8 +345,8 @@ void Sema::DiagnoseUnusedExprResult(const Stmt *S, unsigned DiagID) {
}
const ObjCMethodDecl *MD = ME->getMethodDecl();
if (MD) {
if (DiagnoseNoDiscard(*this, MD->getAttr<WarnUnusedResultAttr>(), Loc, R1,
R2, /*isCtor=*/false))
if (DiagnoseNoDiscard(*this, nullptr, MD->getAttr<WarnUnusedResultAttr>(),
Loc, R1, R2, /*isCtor=*/false))
return;
}
} else if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4882,9 +4882,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
cast<AutoType>(T)->getKeyword() !=
AutoTypeKeyword::Auto ||
cast<AutoType>(T)->isConstrained())) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
// Attach a valid source location for diagnostics on functions with
// trailing return types missing 'auto'. Attempt to get the location
// from the declared type; if invalid, fall back to the trailing
// return type's location.
SourceLocation Loc = D.getDeclSpec().getTypeSpecTypeLoc();
SourceRange SR = D.getDeclSpec().getSourceRange();
if (Loc.isInvalid()) {
Loc = FTI.getTrailingReturnTypeLoc();
SR = D.getSourceRange();
}
S.Diag(Loc, diag::err_trailing_return_without_auto) << T << SR;
D.setInvalidType(true);
// FIXME: recover and fill decls in `TypeLoc`s.
AreDeclaratorChunksValid = false;
Expand Down
224 changes: 120 additions & 104 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3092,98 +3092,97 @@ ASTReader::ReadControlBlock(ModuleFile &F,
break;
}

case IMPORTS: {
case IMPORT: {
// Validate the AST before processing any imports (otherwise, untangling
// them can be error-prone and expensive). A module will have a name and
// will already have been validated, but this catches the PCH case.
if (ASTReadResult Result = readUnhashedControlBlockOnce())
return Result;

// Load each of the imported PCH files.
unsigned Idx = 0, N = Record.size();
while (Idx < N) {
// Read information about the AST file.
ModuleKind ImportedKind = (ModuleKind)Record[Idx++];
// Whether we're importing a standard c++ module.
bool IsImportingStdCXXModule = Record[Idx++];
// The import location will be the local one for now; we will adjust
// all import locations of module imports after the global source
// location info are setup, in ReadAST.
auto [ImportLoc, ImportModuleFileIndex] =
ReadUntranslatedSourceLocation(Record[Idx++]);
// The import location must belong to the current module file itself.
assert(ImportModuleFileIndex == 0);
off_t StoredSize = !IsImportingStdCXXModule ? (off_t)Record[Idx++] : 0;
time_t StoredModTime =
!IsImportingStdCXXModule ? (time_t)Record[Idx++] : 0;

ASTFileSignature StoredSignature;
if (!IsImportingStdCXXModule) {
auto FirstSignatureByte = Record.begin() + Idx;
StoredSignature = ASTFileSignature::create(
FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size);
Idx += ASTFileSignature::size;
}
unsigned Idx = 0;
// Read information about the AST file.
ModuleKind ImportedKind = (ModuleKind)Record[Idx++];

// The import location will be the local one for now; we will adjust
// all import locations of module imports after the global source
// location info are setup, in ReadAST.
auto [ImportLoc, ImportModuleFileIndex] =
ReadUntranslatedSourceLocation(Record[Idx++]);
// The import location must belong to the current module file itself.
assert(ImportModuleFileIndex == 0);

StringRef ImportedName = ReadStringBlob(Record, Idx, Blob);

bool IsImportingStdCXXModule = Record[Idx++];

off_t StoredSize = 0;
time_t StoredModTime = 0;
ASTFileSignature StoredSignature;
std::string ImportedFile;

// For prebuilt and explicit modules first consult the file map for
// an override. Note that here we don't search prebuilt module
// directories if we're not importing standard c++ module, only the
// explicit name to file mappings. Also, we will still verify the
// size/signature making sure it is essentially the same file but
// perhaps in a different location.
if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule)
ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName(
ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule);

if (IsImportingStdCXXModule && ImportedFile.empty()) {
Diag(diag::err_failed_to_find_module_file) << ImportedName;
return Missing;
}

std::string ImportedName = ReadString(Record, Idx);
std::string ImportedFile;

// For prebuilt and explicit modules first consult the file map for
// an override. Note that here we don't search prebuilt module
// directories if we're not importing standard c++ module, only the
// explicit name to file mappings. Also, we will still verify the
// size/signature making sure it is essentially the same file but
// perhaps in a different location.
if (ImportedKind == MK_PrebuiltModule || ImportedKind == MK_ExplicitModule)
ImportedFile = PP.getHeaderSearchInfo().getPrebuiltModuleFileName(
ImportedName, /*FileMapOnly*/ !IsImportingStdCXXModule);

// For C++20 Modules, we won't record the path to the imported modules
// in the BMI
if (!IsImportingStdCXXModule) {
if (ImportedFile.empty()) {
// Use BaseDirectoryAsWritten to ensure we use the same path in the
// ModuleCache as when writing.
ImportedFile = ReadPath(BaseDirectoryAsWritten, Record, Idx);
} else
SkipPath(Record, Idx);
} else if (ImportedFile.empty()) {
Diag(clang::diag::err_failed_to_find_module_file) << ImportedName;
return Missing;
}
if (!IsImportingStdCXXModule) {
StoredSize = (off_t)Record[Idx++];
StoredModTime = (time_t)Record[Idx++];

// If our client can't cope with us being out of date, we can't cope with
// our dependency being missing.
unsigned Capabilities = ClientLoadCapabilities;
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Capabilities &= ~ARR_Missing;

// Load the AST file.
auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
Loaded, StoredSize, StoredModTime,
StoredSignature, Capabilities);

// If we diagnosed a problem, produce a backtrace.
bool recompilingFinalized =
Result == OutOfDate && (Capabilities & ARR_OutOfDate) &&
getModuleManager().getModuleCache().isPCMFinal(F.FileName);
if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized)
Diag(diag::note_module_file_imported_by)
<< F.FileName << !F.ModuleName.empty() << F.ModuleName;
if (recompilingFinalized)
Diag(diag::note_module_file_conflict);

switch (Result) {
case Failure: return Failure;
// If we have to ignore the dependency, we'll have to ignore this too.
case Missing:
case OutOfDate: return OutOfDate;
case VersionMismatch: return VersionMismatch;
case ConfigurationMismatch: return ConfigurationMismatch;
case HadErrors: return HadErrors;
case Success: break;
StringRef SignatureBytes = Blob.substr(0, ASTFileSignature::size);
StoredSignature = ASTFileSignature::create(SignatureBytes.begin(),
SignatureBytes.end());
Blob = Blob.substr(ASTFileSignature::size);

if (ImportedFile.empty()) {
// Use BaseDirectoryAsWritten to ensure we use the same path in the
// ModuleCache as when writing.
ImportedFile =
ReadPathBlob(BaseDirectoryAsWritten, Record, Idx, Blob);
}
}

// If our client can't cope with us being out of date, we can't cope with
// our dependency being missing.
unsigned Capabilities = ClientLoadCapabilities;
if ((ClientLoadCapabilities & ARR_OutOfDate) == 0)
Capabilities &= ~ARR_Missing;

// Load the AST file.
auto Result = ReadASTCore(ImportedFile, ImportedKind, ImportLoc, &F,
Loaded, StoredSize, StoredModTime,
StoredSignature, Capabilities);

// If we diagnosed a problem, produce a backtrace.
bool recompilingFinalized =
Result == OutOfDate && (Capabilities & ARR_OutOfDate) &&
getModuleManager().getModuleCache().isPCMFinal(F.FileName);
if (isDiagnosedResult(Result, Capabilities) || recompilingFinalized)
Diag(diag::note_module_file_imported_by)
<< F.FileName << !F.ModuleName.empty() << F.ModuleName;
if (recompilingFinalized)
Diag(diag::note_module_file_conflict);

switch (Result) {
case Failure: return Failure;
// If we have to ignore the dependency, we'll have to ignore this too.
case Missing:
case OutOfDate: return OutOfDate;
case VersionMismatch: return VersionMismatch;
case ConfigurationMismatch: return ConfigurationMismatch;
case HadErrors: return HadErrors;
case Success: break;
}
break;
}

Expand Down Expand Up @@ -5624,36 +5623,38 @@ bool ASTReader::readASTFileControlBlock(
break;
}

case IMPORTS: {
case IMPORT: {
if (!NeedsImports)
break;

unsigned Idx = 0, N = Record.size();
while (Idx < N) {
// Read information about the AST file.
unsigned Idx = 0;
// Read information about the AST file.

// Skip Kind
Idx++;

// Skip Kind
Idx++;
bool IsStandardCXXModule = Record[Idx++];
// Skip ImportLoc
Idx++;

// Skip ImportLoc
Idx++;
StringRef ModuleName = ReadStringBlob(Record, Idx, Blob);

// In C++20 Modules, we don't record the path to imported
// modules in the BMI files.
if (IsStandardCXXModule) {
std::string ModuleName = ReadString(Record, Idx);
Listener.visitImport(ModuleName, /*Filename=*/"");
continue;
}
bool IsStandardCXXModule = Record[Idx++];

// Skip Size, ModTime and Signature
Idx += 1 + 1 + ASTFileSignature::size;
std::string ModuleName = ReadString(Record, Idx);
std::string FilenameStr = ReadString(Record, Idx);
auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir);
Listener.visitImport(ModuleName, *Filename);
// In C++20 Modules, we don't record the path to imported
// modules in the BMI files.
if (IsStandardCXXModule) {
Listener.visitImport(ModuleName, /*Filename=*/"");
continue;
}

// Skip Size and ModTime.
Idx += 1 + 1;
// Skip signature.
Blob = Blob.substr(ASTFileSignature::size);

StringRef FilenameStr = ReadStringBlob(Record, Idx, Blob);
auto Filename = ResolveImportedPath(PathBuf, FilenameStr, ModuleDir);
Listener.visitImport(ModuleName, *Filename);
break;
}

Expand Down Expand Up @@ -9602,6 +9603,14 @@ std::string ASTReader::ReadString(const RecordDataImpl &Record, unsigned &Idx) {
return Result;
}

StringRef ASTReader::ReadStringBlob(const RecordDataImpl &Record, unsigned &Idx,
StringRef &Blob) {
unsigned Len = Record[Idx++];
StringRef Result = Blob.substr(0, Len);
Blob = Blob.substr(Len);
return Result;
}

std::string ASTReader::ReadPath(ModuleFile &F, const RecordData &Record,
unsigned &Idx) {
return ReadPath(F.BaseDirectory, Record, Idx);
Expand All @@ -9613,6 +9622,13 @@ std::string ASTReader::ReadPath(StringRef BaseDirectory,
return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory);
}

std::string ASTReader::ReadPathBlob(StringRef BaseDirectory,
const RecordData &Record, unsigned &Idx,
StringRef &Blob) {
StringRef Filename = ReadStringBlob(Record, Idx, Blob);
return ResolveImportedPathAndAllocate(PathBuf, Filename, BaseDirectory);
}

VersionTuple ASTReader::ReadVersionTuple(const RecordData &Record,
unsigned &Idx) {
unsigned Major = Record[Idx++];
Expand Down
56 changes: 44 additions & 12 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(MODULE_NAME);
RECORD(MODULE_DIRECTORY);
RECORD(MODULE_MAP_FILE);
RECORD(IMPORTS);
RECORD(IMPORT);
RECORD(ORIGINAL_FILE);
RECORD(ORIGINAL_FILE_ID);
RECORD(INPUT_FILE_OFFSETS);
Expand Down Expand Up @@ -1536,34 +1536,53 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, StringRef isysroot) {

// Imports
if (Chain) {
serialization::ModuleManager &Mgr = Chain->getModuleManager();
Record.clear();
auto Abbrev = std::make_shared<BitCodeAbbrev>();
Abbrev->Add(BitCodeAbbrevOp(IMPORT));
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Kind
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ImportLoc
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Module name len
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Standard C++ mod
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File size
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File timestamp
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // File name len
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Strings
unsigned AbbrevCode = Stream.EmitAbbrev(std::move(Abbrev));

for (ModuleFile &M : Mgr) {
SmallString<128> Blob;

for (ModuleFile &M : Chain->getModuleManager()) {
// Skip modules that weren't directly imported.
if (!M.isDirectlyImported())
continue;

Record.clear();
Blob.clear();

Record.push_back(IMPORT);
Record.push_back((unsigned)M.Kind); // FIXME: Stable encoding
Record.push_back(M.StandardCXXModule);
AddSourceLocation(M.ImportLoc, Record);
AddStringBlob(M.ModuleName, Record, Blob);
Record.push_back(M.StandardCXXModule);

// We don't want to hard code the information about imported modules
// in the C++20 named modules.
if (!M.StandardCXXModule) {
if (M.StandardCXXModule) {
Record.push_back(0);
Record.push_back(0);
Record.push_back(0);
} else {
// If we have calculated signature, there is no need to store
// the size or timestamp.
Record.push_back(M.Signature ? 0 : M.File.getSize());
Record.push_back(M.Signature ? 0 : getTimestampForOutput(M.File));
llvm::append_range(Record, M.Signature);
}

AddString(M.ModuleName, Record);
llvm::append_range(Blob, M.Signature);

if (!M.StandardCXXModule)
AddPath(M.FileName, Record);
AddPathBlob(M.FileName, Record, Blob);
}

Stream.EmitRecordWithBlob(AbbrevCode, Record, Blob);
}
Stream.EmitRecord(IMPORTS, Record);
}

// Write the options block.
Expand Down Expand Up @@ -4777,6 +4796,12 @@ void ASTWriter::AddString(StringRef Str, RecordDataImpl &Record) {
Record.insert(Record.end(), Str.begin(), Str.end());
}

void ASTWriter::AddStringBlob(StringRef Str, RecordDataImpl &Record,
SmallVectorImpl<char> &Blob) {
Record.push_back(Str.size());
Blob.insert(Blob.end(), Str.begin(), Str.end());
}

bool ASTWriter::PreparePathForOutput(SmallVectorImpl<char> &Path) {
assert(WritingAST && "can't prepare path for output when not writing AST");

Expand Down Expand Up @@ -4805,6 +4830,13 @@ void ASTWriter::AddPath(StringRef Path, RecordDataImpl &Record) {
AddString(FilePath, Record);
}

void ASTWriter::AddPathBlob(StringRef Path, RecordDataImpl &Record,
SmallVectorImpl<char> &Blob) {
SmallString<128> FilePath(Path);
PreparePathForOutput(FilePath);
AddStringBlob(FilePath, Record, Blob);
}

void ASTWriter::EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record,
StringRef Path) {
SmallString<128> FilePath(Path);
Expand Down
108 changes: 52 additions & 56 deletions clang/lib/Serialization/GlobalModuleIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -614,62 +614,58 @@ llvm::Error GlobalModuleIndexBuilder::loadModuleFile(FileEntryRef File) {
unsigned Code = MaybeCode.get();

// Handle module dependencies.
if (State == ControlBlock && Code == IMPORTS) {
// Load each of the imported PCH files.
unsigned Idx = 0, N = Record.size();
while (Idx < N) {
// Read information about the AST file.

// Skip the imported kind
++Idx;

// Skip if it is standard C++ module
++Idx;

// Skip the import location
++Idx;

// Load stored size/modification time.
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];

// Skip the stored signature.
// FIXME: we could read the signature out of the import and validate it.
auto FirstSignatureByte = Record.begin() + Idx;
ASTFileSignature StoredSignature = ASTFileSignature::create(
FirstSignatureByte, FirstSignatureByte + ASTFileSignature::size);
Idx += ASTFileSignature::size;

// Skip the module name (currently this is only used for prebuilt
// modules while here we are only dealing with cached).
Idx += Record[Idx] + 1;

// Retrieve the imported file name.
unsigned Length = Record[Idx++];
SmallString<128> ImportedFile(Record.begin() + Idx,
Record.begin() + Idx + Length);
Idx += Length;

// Find the imported module file.
auto DependsOnFile =
FileMgr.getOptionalFileRef(ImportedFile, /*OpenFile=*/false,
/*CacheFailure=*/false);

if (!DependsOnFile)
return llvm::createStringError(std::errc::bad_file_descriptor,
"imported file \"%s\" not found",
ImportedFile.c_str());

// Save the information in ImportedModuleFileInfo so we can verify after
// loading all pcms.
ImportedModuleFiles.insert(std::make_pair(
*DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime,
StoredSignature)));

// Record the dependency.
unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID;
getModuleFileInfo(File).Dependencies.push_back(DependsOnID);
}
if (State == ControlBlock && Code == IMPORT) {
unsigned Idx = 0;
// Read information about the AST file.

// Skip the imported kind
++Idx;

// Skip the import location
++Idx;

// Skip the module name (currently this is only used for prebuilt
// modules while here we are only dealing with cached).
Blob = Blob.substr(Record[Idx++]);

// Skip if it is standard C++ module
++Idx;

// Load stored size/modification time.
off_t StoredSize = (off_t)Record[Idx++];
time_t StoredModTime = (time_t)Record[Idx++];

// Skip the stored signature.
// FIXME: we could read the signature out of the import and validate it.
StringRef SignatureBytes = Blob.substr(0, ASTFileSignature::size);
auto StoredSignature = ASTFileSignature::create(SignatureBytes.begin(),
SignatureBytes.end());
Blob = Blob.substr(ASTFileSignature::size);

// Retrieve the imported file name.
unsigned Length = Record[Idx++];
StringRef ImportedFile = Blob.substr(0, Length);
Blob = Blob.substr(Length);

// Find the imported module file.
auto DependsOnFile =
FileMgr.getOptionalFileRef(ImportedFile, /*OpenFile=*/false,
/*CacheFailure=*/false);

if (!DependsOnFile)
return llvm::createStringError(std::errc::bad_file_descriptor,
"imported file \"%s\" not found",
std::string(ImportedFile).c_str());

// Save the information in ImportedModuleFileInfo so we can verify after
// loading all pcms.
ImportedModuleFiles.insert(std::make_pair(
*DependsOnFile, ImportedModuleFileInfo(StoredSize, StoredModTime,
StoredSignature)));

// Record the dependency.
unsigned DependsOnID = getModuleFileInfo(*DependsOnFile).ID;
getModuleFileInfo(File).Dependencies.push_back(DependsOnID);

continue;
}
Expand Down
Loading