48 changes: 43 additions & 5 deletions clang-tools-extra/unittests/clang-tidy/DeclRefExprUtilsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ template <int Indirections> void RunTest(StringRef Snippet) {
StringRef CommonCode = R"(
struct ConstTag{};
struct NonConstTag{};
struct Tag1{};
struct S {
void constMethod() const;
Expand All @@ -59,6 +60,13 @@ template <int Indirections> void RunTest(StringRef Snippet) {
void operator[](int);
void operator[](int) const;
int& at(int);
const int& at(int) const;
const int& at(Tag1);
int& weird_overload();
const double& weird_overload() const;
bool operator==(const S&) const;
int int_member;
Expand Down Expand Up @@ -161,9 +169,11 @@ TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) {
useIntConstRef(/*const*/target.int_member);
useIntPtr(/*const*/target.ptr_member);
useIntConstPtr(&/*const*/target.int_member);
(void)/*const*/target.at(3);
const S& const_target_ref = /*const*/target;
const S* const_target_ptr = &/*const*/target;
(void)/*const*/target.at(3);
}
)");
}
Expand All @@ -187,7 +197,7 @@ TEST(ConstReferenceDeclRefExprsTest, ValueVar) {
/*const*/target.staticMethod();
target.nonConstMethod();
/*const*/target(ConstTag{});
target[42];
/*const*/target[42];
/*const*/target(ConstTag{});
target(NonConstTag{});
useRef(target);
Expand All @@ -211,6 +221,14 @@ TEST(ConstReferenceDeclRefExprsTest, ValueVar) {
const S& const_target_ref = /*const*/target;
const S* const_target_ptr = &/*const*/target;
S* target_ptr = &target;
(void)/*const*/target.at(3);
++target.at(3);
const int civ = /*const*/target.at(3);
const int& cir = /*const*/target.at(3);
int& ir = target.at(3);
target.at(Tag1{});
target.weird_overload();
}
)");
}
Expand All @@ -227,7 +245,7 @@ TEST(ConstReferenceDeclRefExprsTest, RefVar) {
/*const*/target.staticMethod();
target.nonConstMethod();
/*const*/target(ConstTag{});
target[42];
/*const*/target[42];
useConstRef((/*const*/target));
(/*const*/target).constMethod();
(void)(/*const*/target == /*const*/target);
Expand All @@ -249,6 +267,14 @@ TEST(ConstReferenceDeclRefExprsTest, RefVar) {
const S& const_target_ref = /*const*/target;
const S* const_target_ptr = &/*const*/target;
S* target_ptr = &target;
(void)/*const*/target.at(3);
++target.at(3);
const int civ = /*const*/target.at(3);
const int& cir = /*const*/target.at(3);
int& ir = target.at(3);
target.at(Tag1{});
target.weird_overload();
}
)");
}
Expand All @@ -266,8 +292,8 @@ TEST(ConstReferenceDeclRefExprsTest, PtrVar) {
/*const*/target->staticMethod();
target->nonConstMethod();
(*/*const*/target)(ConstTag{});
(*target)[42];
target->operator[](42);
(*/*const*/target)[42];
/*const*/target->operator[](42);
useConstRef((*/*const*/target));
(/*const*/target)->constMethod();
(void)(*/*const*/target == */*const*/target);
Expand All @@ -284,7 +310,15 @@ TEST(ConstReferenceDeclRefExprsTest, PtrVar) {
const S& const_target_ref = */*const*/target;
const S* const_target_ptr = /*const*/target;
S* target_ptr = target; // FIXME: we could chect const usage of `target_ptr`.
S* target_ptr = target; // FIXME: we could chect const usage of `target_ptr`
(void)/*const*/target->at(3);
++target->at(3);
const int civ = /*const*/target->at(3);
const int& cir = /*const*/target->at(3);
int& ir = target->at(3);
target->at(Tag1{});
target->weird_overload();
}
)");
}
Expand Down Expand Up @@ -319,6 +353,10 @@ TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) {
const S& const_target_ref = */*const*/target;
const S* const_target_ptr = /*const*/target;
(void)/*const*/target->at(3);
const int civ = /*const*/target->at(3);
const int& cir = /*const*/target->at(3);
}
)");
}
Expand Down
22 changes: 9 additions & 13 deletions clang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,9 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wno-long-long")
endif ()

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nested-anon-types" )
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-nested-anon-types" )
endif ()
endif ()

# Determine HOST_LINK_VERSION on Darwin.
Expand Down Expand Up @@ -848,23 +850,17 @@ if (CLANG_ENABLE_BOOTSTRAP)
set(CLANG_BOOTSTRAP_TARGETS check-llvm check-clang check-all)
endif()
foreach(target ${CLANG_BOOTSTRAP_TARGETS})
# Install targets have side effects, so we always want to execute them.
# "install" is reserved by CMake and can't be used as a step name for
# ExternalProject_Add_Step, so we can match against "^install-" instead of
# "^install" to get a tighter match. CMake's installation scripts already
# skip up-to-date files, so there's no behavior change if you install to the
# same destination multiple times.
if(target MATCHES "^install-")
set(step_always ON)
else()
set(step_always OFF)
endif()

ExternalProject_Add_Step(${NEXT_CLANG_STAGE} ${target}
COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target ${target}
COMMENT "Performing ${target} for '${NEXT_CLANG_STAGE}'"
DEPENDEES configure
ALWAYS ${step_always}
# We need to set ALWAYS to ON here, otherwise these targets won't be
# built on a second invocation of ninja. The targets have their own
# logic to determine if they should build or not so setting ALWAYS ON
# here does not mean the targets will always rebuild it just means that
# they will check their dependenices and see if they need to be built.
ALWAYS ON
EXCLUDE_FROM_MAIN ON
USES_TERMINAL 1
)
Expand Down
45 changes: 31 additions & 14 deletions clang/cmake/caches/CrossWinToARMLinux.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@
# on Windows platform.
#
# NOTE: the build requires a development ARM Linux root filesystem to use
# proper target platform depended library and header files:
# - create <full-path-to-clang-configs> directory and put the clang configuration
# file named <TOOLCHAIN_TARGET_TRIPLE>.cfg into it.
# - add the `--sysroot=<path-to-develop-arm-linux-root-fs>` argument into
# this configuration file.
# - add other necessary target depended clang arguments there,
# such as '-mcpu=cortex-a78' & etc.
# proper target platform depended library and header files.
#
# The build generates a proper clang configuration file with stored
# --sysroot argument for specified target triple. Also it is possible
# to specify configuration path via CMake arguments, such as
# -DCLANG_CONFIG_FILE_USER_DIR=<full-path-to-clang-configs>
# and/or
# -DCLANG_CONFIG_FILE_SYSTEM_DIR=<full-path-to-clang-configs>
#
# See more details here: https://clang.llvm.org/docs/UsersManual.html#configuration-files
#
# Configure:
# cmake -G Ninja ^
# -DTOOLCHAIN_TARGET_TRIPLE=aarch64-unknown-linux-gnu ^
# -DTOOLCHAIN_TARGET_SYSROOTFS=<path-to-develop-arm-linux-root-fs> ^
# -DTOOLCHAIN_SHARED_LIBS=OFF ^
# -DCMAKE_INSTALL_PREFIX=../install ^
# -DCLANG_CONFIG_FILE_USER_DIR=<full-path-to-clang-configs> ^
# -DCMAKE_CXX_FLAGS="-D__OPTIMIZE__" ^
# -DREMOTE_TEST_HOST="<hostname>" ^
# -DREMOTE_TEST_USER="<ssh_user_name>" ^
Expand Down Expand Up @@ -81,6 +83,20 @@ endif()

message(STATUS "Toolchain target triple: ${TOOLCHAIN_TARGET_TRIPLE}")

if (DEFINED TOOLCHAIN_TARGET_SYSROOTFS)
message(STATUS "Toolchain target sysroot: ${TOOLCHAIN_TARGET_SYSROOTFS}")
# Store the --sysroot argument for the compiler-rt test flags.
set(sysroot_flags --sysroot='${TOOLCHAIN_TARGET_SYSROOTFS}')
# Generate the clang configuration file for the specified target triple
# and store --sysroot in this file.
file(WRITE "${CMAKE_BINARY_DIR}/bin/${TOOLCHAIN_TARGET_TRIPLE}.cfg" ${sysroot_flags})
endif()

# Build the shared libraries for libc++/libc++abi/libunwind.
if (NOT DEFINED TOOLCHAIN_SHARED_LIBS)
set(TOOLCHAIN_SHARED_LIBS OFF)
endif()

if (NOT DEFINED LLVM_TARGETS_TO_BUILD)
if ("${TOOLCHAIN_TARGET_TRIPLE}" MATCHES "^(armv|arm32)+")
set(LLVM_TARGETS_TO_BUILD "ARM" CACHE STRING "")
Expand Down Expand Up @@ -183,20 +199,21 @@ set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_CAN_EXECUTE_TESTS

set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_USE_BUILTINS_LIBRARY ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_CXX_LIBRARY libcxx CACHE STRING "")
# Tell Clang to seach C++ headers alongside with the just-built binaries for the C++ compiler-rt tests.
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_TEST_COMPILER_CFLAGS "--stdlib=libc++" CACHE STRING "")

# The compiler-rt tests disable the clang configuration files during the execution by setting CLANG_NO_DEFAULT_CONFIG=1
# and drops out the --sysroot from there. Provide it explicity via the test flags here if target sysroot has been specified.
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_COMPILER_RT_TEST_COMPILER_CFLAGS "--stdlib=libc++ ${sysroot_flags}" CACHE STRING "")

set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBUNWIND_ENABLE_SHARED ${TOOLCHAIN_SHARED_LIBS} CACHE BOOL "")

set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_NEW_DELETE_DEFINITIONS OFF CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXXABI_ENABLE_SHARED ${TOOLCHAIN_SHARED_LIBS} CACHE BOOL "")

set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_SHARED OFF CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_SHARED ${TOOLCHAIN_SHARED_LIBS} CACHE BOOL "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ABI_VERSION ${LIBCXX_ABI_VERSION} CACHE STRING "")
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_CXX_ABI "libcxxabi" CACHE STRING "") #!!!
set(RUNTIMES_${TOOLCHAIN_TARGET_TRIPLE}_LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "")
Expand Down
4 changes: 3 additions & 1 deletion clang/cmake/caches/Release.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ endfunction()
#
# cmake -D LLVM_RELEASE_ENABLE_PGO=ON -C Release.cmake
set(LLVM_RELEASE_ENABLE_LTO THIN CACHE STRING "")
set(LLVM_RELEASE_ENABLE_PGO OFF CACHE BOOL "")
set(LLVM_RELEASE_ENABLE_PGO ON CACHE BOOL "")
set(LLVM_RELEASE_ENABLE_RUNTIMES "compiler-rt;libcxx;libcxxabi;libunwind" CACHE STRING "")
set(LLVM_RELEASE_ENABLE_PROJECTS "clang;lld;lldb;clang-tools-extra;bolt;polly;mlir;flang" CACHE STRING "")
# Note we don't need to add install here, since it is one of the pre-defined
Expand Down Expand Up @@ -91,4 +91,6 @@ endif()
# Final Stage Config (stage2)
set_final_stage_var(LLVM_ENABLE_RUNTIMES "${LLVM_RELEASE_ENABLE_RUNTIMES}" STRING)
set_final_stage_var(LLVM_ENABLE_PROJECTS "${LLVM_RELEASE_ENABLE_PROJECTS}" STRING)
set_final_stage_var(CPACK_GENERATOR "TXZ" STRING)
set_final_stage_var(CPACK_ARCHIVE_THREADS "0" STRING)

1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@ Arm and AArch64 Support
* Arm Cortex-A520AE (cortex-a520ae).
* Arm Cortex-A720AE (cortex-a720ae).
* Arm Cortex-R82AE (cortex-r82ae).
* Arm Cortex-R52+ (cortex-r52plus).
* Arm Neoverse-N3 (neoverse-n3).
* Arm Neoverse-V3 (neoverse-v3).
* Arm Neoverse-V3AE (neoverse-v3ae).
Expand Down
1 change: 1 addition & 0 deletions clang/docs/tools/clang-formatted-files.txt
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,7 @@ clang/tools/libclang/CXCursor.h
clang/tools/scan-build-py/tests/functional/src/include/clean-one.h
clang/unittests/Analysis/CFGBuildResult.h
clang/unittests/Analysis/MacroExpansionContextTest.cpp
clang/unittests/Analysis/FlowSensitive/ASTOpsTest.cpp
clang/unittests/Analysis/FlowSensitive/CNFFormula.cpp
clang/unittests/Analysis/FlowSensitive/DataflowAnalysisContextTest.cpp
clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
Expand Down
2 changes: 1 addition & 1 deletion clang/examples/PrintFunctionNames/PrintFunctionNames.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class PrintFunctionsConsumer : public ASTConsumer {
*sema.LateParsedTemplateMap.find(FD)->second;
sema.LateTemplateParser(sema.OpaqueParser, LPT);
llvm::errs() << "late-parsed-decl: \"" << FD->getNameAsString() << "\"\n";
}
}
}
};

Expand Down
9 changes: 7 additions & 2 deletions clang/include/clang/AST/ASTUnresolvedSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "clang/AST/ASTVector.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclID.h"
#include "clang/AST/UnresolvedSet.h"
#include "clang/Basic/Specifiers.h"
#include <cassert>
Expand Down Expand Up @@ -56,6 +57,10 @@ class ASTUnresolvedSet {
Decls.push_back(DeclAccessPair::make(D, AS), C);
}

void addLazyDecl(ASTContext &C, GlobalDeclID ID, AccessSpecifier AS) {
Decls.push_back(DeclAccessPair::makeLazy(ID.get(), AS), C);
}

/// Replaces the given declaration with the new one, once.
///
/// \return true if the set changed
Expand Down Expand Up @@ -109,10 +114,10 @@ class LazyASTUnresolvedSet {

void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); }

void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) {
void addLazyDecl(ASTContext &C, GlobalDeclID ID, AccessSpecifier AS) {
assert(Impl.empty() || Impl.Decls.isLazy());
Impl.Decls.setLazy(true);
Impl.addDecl(C, reinterpret_cast<NamedDecl *>(ID << 2), AS);
Impl.addLazyDecl(C, ID, AS);
}
};

Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/AST/CommentCommands.td
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; }
// HeaderDoc command for template parameter documentation.
def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; }

def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; }
def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; }
def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; }
def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; let NumArgs = 1; }
def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; let NumArgs = 1; }
def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; let NumArgs = 1;}

def Deprecated : BlockCommand<"deprecated"> {
let IsEmptyParagraphAllowed = 1;
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/AST/CommentParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ class Parser {
ArrayRef<Comment::Argument>
parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);

/// Parse arguments for \throws command supported args are in form of class
/// or template.
ArrayRef<Comment::Argument>
parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs);

BlockCommandComment *parseBlockCommand();
InlineCommandComment *parseInlineCommand();

Expand Down
37 changes: 31 additions & 6 deletions clang/include/clang/AST/DeclAccessPair.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "clang/Basic/Specifiers.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Endian.h"

namespace clang {

Expand All @@ -27,9 +28,17 @@ class NamedDecl;
/// A POD class for pairing a NamedDecl* with an access specifier.
/// Can be put into unions.
class DeclAccessPair {
uintptr_t Ptr; // we'd use llvm::PointerUnion, but it isn't trivial
/// Use the lower 2 bit to store AccessSpecifier. Use the higher
/// 61 bit to store the pointer to a NamedDecl or the DeclID to
/// a NamedDecl. If the 3rd bit is set, storing the DeclID, otherwise
/// storing the pointer.
llvm::support::detail::packed_endian_specific_integral<
uint64_t, llvm::endianness::native, alignof(void *)>
Ptr;

enum { Mask = 0x3 };
enum { ASMask = 0x3, Mask = 0x7 };

bool isDeclID() const { return (Ptr >> 2) & 0x1; }

public:
static DeclAccessPair make(NamedDecl *D, AccessSpecifier AS) {
Expand All @@ -38,12 +47,22 @@ class DeclAccessPair {
return p;
}

static DeclAccessPair makeLazy(uint64_t ID, AccessSpecifier AS) {
DeclAccessPair p;
p.Ptr = (ID << 3) | (0x1 << 2) | uint64_t(AS);
return p;
}

uint64_t getDeclID() const {
assert(isDeclID());
return (~Mask & Ptr) >> 3;
}

NamedDecl *getDecl() const {
assert(!isDeclID());
return reinterpret_cast<NamedDecl*>(~Mask & Ptr);
}
AccessSpecifier getAccess() const {
return AccessSpecifier(Mask & Ptr);
}
AccessSpecifier getAccess() const { return AccessSpecifier(ASMask & Ptr); }

void setDecl(NamedDecl *D) {
set(D, getAccess());
Expand All @@ -52,12 +71,18 @@ class DeclAccessPair {
set(getDecl(), AS);
}
void set(NamedDecl *D, AccessSpecifier AS) {
Ptr = uintptr_t(AS) | reinterpret_cast<uintptr_t>(D);
Ptr = uint64_t(AS) | reinterpret_cast<uint64_t>(D);
}

operator NamedDecl*() const { return getDecl(); }
NamedDecl *operator->() const { return getDecl(); }
};

// Make sure DeclAccessPair is pointer-aligned types.
static_assert(alignof(DeclAccessPair) == alignof(void *));
// Make sure DeclAccessPair is still POD.
static_assert(std::is_standard_layout_v<DeclAccessPair> &&
std::is_trivial_v<DeclAccessPair>);
}

#endif
17 changes: 3 additions & 14 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -708,10 +708,7 @@ class alignas(8) Decl {

/// Set the owning module ID. This may only be called for
/// deserialized Decls.
void setOwningModuleID(unsigned ID) {
assert(isFromASTFile() && "Only works on a deserialized declaration");
*((unsigned*)this - 2) = ID;
}
void setOwningModuleID(unsigned ID);

public:
/// Determine the availability of the given declaration.
Expand Down Expand Up @@ -784,19 +781,11 @@ class alignas(8) Decl {

/// Retrieve the global declaration ID associated with this
/// declaration, which specifies where this Decl was loaded from.
GlobalDeclID getGlobalID() const {
if (isFromASTFile())
return (*((const GlobalDeclID *)this - 1));
return GlobalDeclID();
}
GlobalDeclID getGlobalID() const;

/// Retrieve the global ID of the module that owns this particular
/// declaration.
unsigned getOwningModuleID() const {
if (isFromASTFile())
return *((const unsigned*)this - 2);
return 0;
}
unsigned getOwningModuleID() const;

private:
Module *getOwningModuleSlow() const;
Expand Down
18 changes: 17 additions & 1 deletion clang/include/clang/AST/DeclID.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/iterator.h"

#include <climits>

namespace clang {

/// Predefined declaration IDs.
Expand Down Expand Up @@ -107,12 +109,16 @@ class DeclIDBase {
///
/// DeclID should only be used directly in serialization. All other users
/// should use LocalDeclID or GlobalDeclID.
using DeclID = uint32_t;
using DeclID = uint64_t;

protected:
DeclIDBase() : ID(PREDEF_DECL_NULL_ID) {}
explicit DeclIDBase(DeclID ID) : ID(ID) {}

explicit DeclIDBase(unsigned LocalID, unsigned ModuleFileIndex) {
ID = (DeclID)LocalID | ((DeclID)ModuleFileIndex << 32);
}

public:
DeclID get() const { return ID; }

Expand All @@ -124,6 +130,10 @@ class DeclIDBase {

bool isInvalid() const { return ID == PREDEF_DECL_NULL_ID; }

unsigned getModuleFileIndex() const { return ID >> 32; }

unsigned getLocalDeclIndex() const;

friend bool operator==(const DeclIDBase &LHS, const DeclIDBase &RHS) {
return LHS.ID == RHS.ID;
}
Expand Down Expand Up @@ -156,6 +166,9 @@ class LocalDeclID : public DeclIDBase {
LocalDeclID(PredefinedDeclIDs ID) : Base(ID) {}
explicit LocalDeclID(DeclID ID) : Base(ID) {}

explicit LocalDeclID(unsigned LocalID, unsigned ModuleFileIndex)
: Base(LocalID, ModuleFileIndex) {}

LocalDeclID &operator++() {
++ID;
return *this;
Expand All @@ -175,6 +188,9 @@ class GlobalDeclID : public DeclIDBase {
GlobalDeclID() : Base() {}
explicit GlobalDeclID(DeclID ID) : Base(ID) {}

explicit GlobalDeclID(unsigned LocalID, unsigned ModuleFileIndex)
: Base(LocalID, ModuleFileIndex) {}

// For DeclIDIterator<GlobalDeclID> to be able to convert a GlobalDeclID
// to a LocalDeclID.
explicit operator LocalDeclID() const { return LocalDeclID(this->ID); }
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/TemplateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ class TemplateArgument {
bool IncludeType) const;

/// Debugging aid that dumps the template argument.
void dump(raw_ostream &Out) const;
void dump(raw_ostream &Out, const ASTContext &Context) const;

/// Debugging aid that dumps the template argument to standard error.
void dump() const;
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/TemplateName.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ class TemplateName {
Qualified Qual = Qualified::AsWritten) const;

/// Debugging aid that dumps the template name.
void dump(raw_ostream &OS) const;
void dump(raw_ostream &OS, const ASTContext &Context) const;

/// Debugging aid that dumps the template name to standard
/// error.
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/UnresolvedSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class UnresolvedSetIterator : public llvm::iterator_adaptor_base<
// temporaries with defaulted ctors are not zero initialized.
UnresolvedSetIterator() : iterator_adaptor_base(nullptr) {}

uint64_t getDeclID() const { return I->getDeclID(); }
NamedDecl *getDecl() const { return I->getDecl(); }
void setDecl(NamedDecl *ND) const { return I->setDecl(ND); }
AccessSpecifier getAccess() const { return I->getAccess(); }
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,9 @@ class CapabilityExpr {

bool shouldIgnore() const { return sexpr() == nullptr; }

bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); }
bool isInvalid() const { return isa_and_nonnull<til::Undefined>(sexpr()); }

bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); }
bool isUniversal() const { return isa_and_nonnull<til::Wildcard>(sexpr()); }
};

// Translate clang::Expr to til::SExpr.
Expand Down
27 changes: 5 additions & 22 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -4470,37 +4470,20 @@ def HLSLShader : InheritableAttr {
let Subjects = SubjectList<[HLSLEntry]>;
let LangOpts = [HLSL];
let Args = [
EnumArgument<"Type", "ShaderType", /*is_string=*/true,
EnumArgument<"Type", "llvm::Triple::EnvironmentType", /*is_string=*/true,
["pixel", "vertex", "geometry", "hull", "domain", "compute",
"raygeneration", "intersection", "anyhit", "closesthit",
"miss", "callable", "mesh", "amplification"],
["Pixel", "Vertex", "Geometry", "Hull", "Domain", "Compute",
"RayGeneration", "Intersection", "AnyHit", "ClosestHit",
"Miss", "Callable", "Mesh", "Amplification"]>
"Miss", "Callable", "Mesh", "Amplification"],
/*opt=*/0, /*fake=*/0, /*isExternalType=*/1>
];
let Documentation = [HLSLSV_ShaderTypeAttrDocs];
let AdditionalMembers =
[{
static const unsigned ShaderTypeMaxValue = (unsigned)HLSLShaderAttr::Amplification;

static llvm::Triple::EnvironmentType getTypeAsEnvironment(HLSLShaderAttr::ShaderType ShaderType) {
switch (ShaderType) {
case HLSLShaderAttr::Pixel: return llvm::Triple::Pixel;
case HLSLShaderAttr::Vertex: return llvm::Triple::Vertex;
case HLSLShaderAttr::Geometry: return llvm::Triple::Geometry;
case HLSLShaderAttr::Hull: return llvm::Triple::Hull;
case HLSLShaderAttr::Domain: return llvm::Triple::Domain;
case HLSLShaderAttr::Compute: return llvm::Triple::Compute;
case HLSLShaderAttr::RayGeneration: return llvm::Triple::RayGeneration;
case HLSLShaderAttr::Intersection: return llvm::Triple::Intersection;
case HLSLShaderAttr::AnyHit: return llvm::Triple::AnyHit;
case HLSLShaderAttr::ClosestHit: return llvm::Triple::ClosestHit;
case HLSLShaderAttr::Miss: return llvm::Triple::Miss;
case HLSLShaderAttr::Callable: return llvm::Triple::Callable;
case HLSLShaderAttr::Mesh: return llvm::Triple::Mesh;
case HLSLShaderAttr::Amplification: return llvm::Triple::Amplification;
}
llvm_unreachable("unknown enumeration value");
static bool isValidShaderType(llvm::Triple::EnvironmentType ShaderType) {
return ShaderType >= llvm::Triple::Pixel && ShaderType <= llvm::Triple::Amplification;
}
}];
}
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -482,11 +482,11 @@ def SqrtF16F128 : Builtin, F16F128MathTemplate {
let Prototype = "T(T)";
}

def TanF128 : Builtin {
let Spellings = ["__builtin_tanf128"];
def TanF16F128 : Builtin, F16F128MathTemplate {
let Spellings = ["__builtin_tan"];
let Attributes = [FunctionWithBuiltinPrefix, NoThrow,
ConstIgnoringErrnoAndExceptions];
let Prototype = "__float128(__float128)";
let Prototype = "T(T)";
}

def TanhF128 : Builtin {
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ CODEGENOPT(SeparateNamedSections, 1, 0) ///< Set for -fseparate-named-sections.
CODEGENOPT(EnableAIXExtendedAltivecABI, 1, 0) ///< Set for -mabi=vec-extabi. Enables the extended Altivec ABI on AIX.
CODEGENOPT(XCOFFReadOnlyPointers, 1, 0) ///< Set for -mxcoff-roptr.
CODEGENOPT(AllTocData, 1, 0) ///< AIX -mtocdata
ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,none
ENUM_CODEGENOPT(FramePointer, FramePointerKind, 2, FramePointerKind::None) /// frame-pointer: all,non-leaf,reserved,none

CODEGENOPT(ClearASTBeforeBackend , 1, 0) ///< Free the AST before running backend code generation. Only works with -disable-free.
CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory.
Expand Down
9 changes: 6 additions & 3 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,15 +127,18 @@ class CodeGenOptions : public CodeGenOptionsBase {
std::string BinutilsVersion;

enum class FramePointerKind {
None, // Omit all frame pointers.
NonLeaf, // Keep non-leaf frame pointers.
All, // Keep all frame pointers.
None, // Omit all frame pointers.
Reserved, // Maintain valid frame pointer chain.
NonLeaf, // Keep non-leaf frame pointers.
All, // Keep all frame pointers.
};

static StringRef getFramePointerKindName(FramePointerKind Kind) {
switch (Kind) {
case FramePointerKind::None:
return "none";
case FramePointerKind::Reserved:
return "reserved";
case FramePointerKind::NonLeaf:
return "non-leaf";
case FramePointerKind::All:
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/DiagnosticOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
/// default).
std::vector<std::string> VerifyPrefixes;

/// The list of -Wsystem-header-in-module=... options used to override
/// The list of -Wsystem-headers-in-module=... options used to override
/// whether -Wsystem-headers is enabled on a per-module basis.
std::vector<std::string> SystemHeaderWarningsModules;

Expand Down
13 changes: 10 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,8 @@ def note_using_decl_class_member_workaround : Note<
"a const variable|a constexpr variable}0 instead">;
def err_using_decl_can_not_refer_to_namespace : Error<
"using declaration cannot refer to a namespace">;
def note_namespace_using_decl : Note<
"did you mean 'using namespace'?">;
def warn_cxx17_compat_using_decl_scoped_enumerator: Warning<
"using declaration naming a scoped enumerator is incompatible with "
"C++ standards before C++20">, InGroup<CXXPre20Compat>, DefaultIgnore;
Expand Down Expand Up @@ -6088,9 +6090,9 @@ def err_redefinition_different_concept : Error<
"redefinition of concept %0 with different template parameters or requirements">;
def err_tag_reference_non_tag : Error<
"%select{non-struct type|non-class type|non-union type|non-enum "
"type|typedef|type alias|template|type alias template|template "
"template argument}1 %0 cannot be referenced with a "
"%select{struct|interface|union|class|enum}2 specifier">;
"type|typedef|type alias|template|alias template|template "
"template argument}1 %0 cannot be referenced with the '"
"%select{struct|interface|union|class|enum}2' specifier">;
def err_tag_reference_conflict : Error<
"implicit declaration introduced by elaborated type conflicts with a "
"%select{non-struct type|non-class type|non-union type|non-enum "
Expand Down Expand Up @@ -9013,6 +9015,11 @@ def err_cuda_ovl_target : Error<
"cannot overload %select{__device__|__global__|__host__|__host__ __device__}2 function %3">;
def note_cuda_ovl_candidate_target_mismatch : Note<
"candidate template ignored: target attributes do not match">;
def warn_offload_incompatible_redeclare : Warning<
"target-attribute based function overloads are not supported by NVCC and will be treated as a function redeclaration:"
"new declaration is %select{__device__|__global__|__host__|__host__ __device__}0 function, "
"old declaration is %select{__device__|__global__|__host__|__host__ __device__}1 function">,
InGroup<DiagGroup<"nvcc-compat">>, DefaultIgnore;

def err_cuda_device_builtin_surftex_cls_template : Error<
"illegal device builtin %select{surface|texture}0 reference "
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 @@ -96,6 +96,7 @@ FEATURE(nullability, true)
FEATURE(nullability_on_arrays, true)
FEATURE(nullability_on_classes, true)
FEATURE(nullability_nullable_result, true)
FEATURE(numerical_stability_sanitizer, LangOpts.Sanitize.has(SanitizerKind::NumericalStability))
FEATURE(memory_sanitizer,
LangOpts.Sanitize.hasOneOf(SanitizerKind::Memory |
SanitizerKind::KernelMemory))
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/Sanitizers.def
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ SANITIZER("fuzzer-no-link", FuzzerNoLink)
// ThreadSanitizer
SANITIZER("thread", Thread)

// Numerical stability sanitizer.
SANITIZER("numerical", NumericalStability)

// LeakSanitizer
SANITIZER("leak", Leak)

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -7724,8 +7724,8 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">,
MarshallingInfoFlag<LangOpts<"PIE">>;

def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">,
HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none">,
NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None"]>,
HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,reserved,none">,
NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "Reserved", "None"]>,
MarshallingInfoEnum<CodeGenOpts<"FramePointer">, "None">;


Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Driver/SanitizerArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class SanitizerArgs {
bool needsCfiDiagRt() const;
bool needsStatsRt() const { return Stats; }
bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); }
bool needsNsanRt() const {
return Sanitizers.has(SanitizerKind::NumericalStability);
}

bool hasMemTag() const {
return hasMemtagHeap() || hasMemtagStack() || hasMemtagGlobals();
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Driver/ToolChain.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ class ToolChain {

/// Executes the given \p Executable and returns the stdout.
llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>>
executeToolChainProgram(StringRef Executable) const;
executeToolChainProgram(StringRef Executable,
unsigned SecondsToWait = 0) const;

void setTripleEnvironment(llvm::Triple::EnvironmentType Env);

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Lex/Preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -1360,7 +1360,7 @@ class Preprocessor {

MacroState &S = CurSubmoduleState->Macros[II];
auto *MD = S.getLatest();
while (MD && isa<VisibilityMacroDirective>(MD))
while (isa_and_nonnull<VisibilityMacroDirective>(MD))
MD = MD->getPrevious();
return MacroDefinition(dyn_cast_or_null<DefMacroDirective>(MD),
S.getActiveModuleMacros(*this, II),
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/Initialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class alignas(8) InitializedEntity {
struct C Capture;
};

InitializedEntity() {};
InitializedEntity() {}

/// Create the initialization entity for a variable.
InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable)
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Sema/SemaHLSL.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class SemaHLSL : public SemaBase {
const AttributeCommonInfo &AL, int X,
int Y, int Z);
HLSLShaderAttr *mergeShaderAttr(Decl *D, const AttributeCommonInfo &AL,
HLSLShaderAttr::ShaderType ShaderType);
llvm::Triple::EnvironmentType ShaderType);
HLSLParamModifierAttr *
mergeParamModifierAttr(Decl *D, const AttributeCommonInfo &AL,
HLSLParamModifierAttr::Spelling Spelling);
Expand All @@ -48,8 +48,8 @@ class SemaHLSL : public SemaBase {
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
const HLSLAnnotationAttr *AnnotationAttr);
void DiagnoseAttrStageMismatch(
const Attr *A, HLSLShaderAttr::ShaderType Stage,
std::initializer_list<HLSLShaderAttr::ShaderType> AllowedStages);
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);

void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Sema/SemaObjC.h
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ class SemaObjC : public SemaBase {
void AddAnyMethodToGlobalPool(Decl *D);

void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
bool isObjCMethodDecl(Decl *D) { return D && isa<ObjCMethodDecl>(D); }
bool isObjCMethodDecl(Decl *D) { return isa_and_nonnull<ObjCMethodDecl>(D); }

/// CheckImplementationIvars - This routine checks if the instance variables
/// listed in the implelementation match those listed in the interface.
Expand Down
29 changes: 23 additions & 6 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ class DeclOffset {
}
};

// The unaligned decl ID used in the Blobs of bistreams.
using unaligned_decl_id_t =
llvm::support::detail::packed_endian_specific_integral<
serialization::DeclID, llvm::endianness::native,
llvm::support::unaligned>;

/// The number of predefined preprocessed entity IDs.
const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1;

Expand Down Expand Up @@ -1980,33 +1986,44 @@ enum CleanupObjectKind { COK_Block, COK_CompoundLiteral };

/// Describes the categories of an Objective-C class.
struct ObjCCategoriesInfo {
// The ID of the definition
LocalDeclID DefinitionID;
// The ID of the definition. Use unaligned_decl_id_t to keep
// ObjCCategoriesInfo 32-bit aligned.
unaligned_decl_id_t DefinitionID;

// Offset into the array of category lists.
unsigned Offset;

ObjCCategoriesInfo() = default;
ObjCCategoriesInfo(LocalDeclID ID, unsigned Offset)
: DefinitionID(ID.get()), Offset(Offset) {}

LocalDeclID getDefinitionID() const { return LocalDeclID(DefinitionID); }

friend bool operator<(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID < Y.DefinitionID;
return X.getDefinitionID() < Y.getDefinitionID();
}

friend bool operator>(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID > Y.DefinitionID;
return X.getDefinitionID() > Y.getDefinitionID();
}

friend bool operator<=(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID <= Y.DefinitionID;
return X.getDefinitionID() <= Y.getDefinitionID();
}

friend bool operator>=(const ObjCCategoriesInfo &X,
const ObjCCategoriesInfo &Y) {
return X.DefinitionID >= Y.DefinitionID;
return X.getDefinitionID() >= Y.getDefinitionID();
}
};

static_assert(alignof(ObjCCategoriesInfo) <= 4);
static_assert(std::is_standard_layout_v<ObjCCategoriesInfo> &&
std::is_trivial_v<ObjCCategoriesInfo>);

/// A key used when looking up entities by \ref DeclarationName.
///
/// Different \ref DeclarationNames are mapped to different keys, but the
Expand Down
36 changes: 16 additions & 20 deletions clang/include/clang/Serialization/ASTReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,12 +504,6 @@ class ASTReader
/// = I + 1 has already been loaded.
llvm::PagedVector<Decl *> DeclsLoaded;

using GlobalDeclMapType = ContinuousRangeMap<GlobalDeclID, ModuleFile *, 4>;

/// Mapping from global declaration IDs to the module in which the
/// declaration resides.
GlobalDeclMapType GlobalDeclMap;

using FileOffset = std::pair<ModuleFile *, uint64_t>;
using FileOffsetsTy = SmallVector<FileOffset, 2>;
using DeclUpdateOffsetsMap = llvm::DenseMap<GlobalDeclID, FileOffsetsTy>;
Expand Down Expand Up @@ -592,10 +586,11 @@ class ASTReader

struct FileDeclsInfo {
ModuleFile *Mod = nullptr;
ArrayRef<LocalDeclID> Decls;
ArrayRef<serialization::unaligned_decl_id_t> Decls;

FileDeclsInfo() = default;
FileDeclsInfo(ModuleFile *Mod, ArrayRef<LocalDeclID> Decls)
FileDeclsInfo(ModuleFile *Mod,
ArrayRef<serialization::unaligned_decl_id_t> Decls)
: Mod(Mod), Decls(Decls) {}
};

Expand All @@ -604,11 +599,7 @@ class ASTReader

/// An array of lexical contents of a declaration context, as a sequence of
/// Decl::Kind, DeclID pairs.
using unaligned_decl_id_t =
llvm::support::detail::packed_endian_specific_integral<
serialization::DeclID, llvm::endianness::native,
llvm::support::unaligned>;
using LexicalContents = ArrayRef<unaligned_decl_id_t>;
using LexicalContents = ArrayRef<serialization::unaligned_decl_id_t>;

/// Map from a DeclContext to its lexical contents.
llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>>
Expand Down Expand Up @@ -1489,22 +1480,23 @@ class ASTReader
unsigned ClientLoadCapabilities);

public:
class ModuleDeclIterator : public llvm::iterator_adaptor_base<
ModuleDeclIterator, const LocalDeclID *,
std::random_access_iterator_tag, const Decl *,
ptrdiff_t, const Decl *, const Decl *> {
class ModuleDeclIterator
: public llvm::iterator_adaptor_base<
ModuleDeclIterator, const serialization::unaligned_decl_id_t *,
std::random_access_iterator_tag, const Decl *, ptrdiff_t,
const Decl *, const Decl *> {
ASTReader *Reader = nullptr;
ModuleFile *Mod = nullptr;

public:
ModuleDeclIterator() : iterator_adaptor_base(nullptr) {}

ModuleDeclIterator(ASTReader *Reader, ModuleFile *Mod,
const LocalDeclID *Pos)
const serialization::unaligned_decl_id_t *Pos)
: iterator_adaptor_base(Pos), Reader(Reader), Mod(Mod) {}

value_type operator*() const {
return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, *I));
return Reader->GetDecl(Reader->getGlobalDeclID(*Mod, (LocalDeclID)*I));
}

value_type operator->() const { return **this; }
Expand Down Expand Up @@ -1544,6 +1536,9 @@ class ASTReader
StringRef Arg2 = StringRef(), StringRef Arg3 = StringRef()) const;
void Error(llvm::Error &&Err) const;

/// Translate a \param GlobalDeclID to the index of DeclsLoaded array.
unsigned translateGlobalDeclIDToIndex(GlobalDeclID ID) const;

public:
/// Load the AST file and validate its contents against the given
/// Preprocessor.
Expand Down Expand Up @@ -1915,7 +1910,8 @@ class ASTReader

/// Retrieve the module file that owns the given declaration, or NULL
/// if the declaration is not from a module file.
ModuleFile *getOwningModuleFile(const Decl *D);
ModuleFile *getOwningModuleFile(const Decl *D) const;
ModuleFile *getOwningModuleFile(GlobalDeclID ID) const;

/// Returns the source location for the decl \p ID.
SourceLocation getSourceLocationForDeclID(GlobalDeclID ID);
Expand Down
18 changes: 3 additions & 15 deletions clang/include/clang/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -454,23 +454,11 @@ class ModuleFile {
/// by the declaration ID (-1).
const DeclOffset *DeclOffsets = nullptr;

/// Base declaration ID for declarations local to this module.
serialization::DeclID BaseDeclID = 0;

/// Remapping table for declaration IDs in this module.
ContinuousRangeMap<serialization::DeclID, int, 2> DeclRemap;

/// Mapping from the module files that this module file depends on
/// to the base declaration ID for that module as it is understood within this
/// module.
///
/// This is effectively a reverse global-to-local mapping for declaration
/// IDs, so that we can interpret a true global ID (for this translation unit)
/// as a local ID (for this module file).
llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs;
/// Base declaration index in ASTReader for declarations local to this module.
unsigned BaseDeclIndex = 0;

/// Array of file-level DeclIDs sorted by file.
const LocalDeclID *FileSortedDecls = nullptr;
const serialization::unaligned_decl_id_t *FileSortedDecls = nullptr;
unsigned NumFileSortedDecls = 0;

/// Array of category list location information within this
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Serialization/ModuleManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ namespace serialization {
/// Manages the set of modules loaded by an AST reader.
class ModuleManager {
/// The chain of AST files, in the order in which we started to load
/// them (this order isn't really useful for anything).
/// them.
SmallVector<std::unique_ptr<ModuleFile>, 2> Chain;

/// The chain of non-module PCH files. The first entry is the one named
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,7 @@ class SymbolicRegion : public SubRegion {
: SubRegion(sreg, SymbolicRegionKind), sym(s) {
// Because pointer arithmetic is represented by ElementRegion layers,
// the base symbol here should not contain any arithmetic.
assert(s && isa<SymbolData>(s));
assert(isa_and_nonnull<SymbolData>(s));
assert(s->getType()->isAnyPointerType() ||
s->getType()->isReferenceType() ||
s->getType()->isBlockPointerType());
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Tooling/Syntax/Tokens.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,9 @@ class TokenBuffer {
/// "DECL", "(", "a", ")", ";"}
llvm::ArrayRef<syntax::Token> spelledTokens(FileID FID) const;

/// Returns the spelled Token starting at Loc, if there are no such tokens
/// Returns the spelled Token containing the Loc, if there are no such tokens
/// returns nullptr.
const syntax::Token *spelledTokenAt(SourceLocation Loc) const;
const syntax::Token *spelledTokenContaining(SourceLocation Loc) const;

/// Get all tokens that expand a macro in \p FID. For the following input
/// #define FOO B
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
Stmt *parent = E;
do {
parent = StmtMap->getParentIgnoreParenImpCasts(parent);
} while (parent && isa<FullExpr>(parent));
} while (isa_and_nonnull<FullExpr>(parent));

if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
std::string note = "remove the cast and change return type of function "
Expand Down
34 changes: 34 additions & 0 deletions clang/lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,3 +360,37 @@ LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const {
ASTDumper P(OS, Ctx, Ctx.getDiagnostics().getShowColors());
P.Visit(this);
}

//===----------------------------------------------------------------------===//
// TemplateName method implementations
//===----------------------------------------------------------------------===//

// FIXME: These are actually using the TemplateArgument dumper, through
// an implicit conversion. The dump will claim this is a template argument,
// which is misleading.

LLVM_DUMP_METHOD void TemplateName::dump() const {
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
Dumper.Visit(*this);
}

LLVM_DUMP_METHOD void TemplateName::dump(llvm::raw_ostream &OS,
const ASTContext &Context) const {
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
Dumper.Visit(*this);
}

//===----------------------------------------------------------------------===//
// TemplateArgument method implementations
//===----------------------------------------------------------------------===//

LLVM_DUMP_METHOD void TemplateArgument::dump() const {
ASTDumper Dumper(llvm::errs(), /*ShowColors=*/false);
Dumper.Visit(*this);
}

LLVM_DUMP_METHOD void TemplateArgument::dump(llvm::raw_ostream &OS,
const ASTContext &Context) const {
ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
Dumper.Visit(*this);
}
2 changes: 1 addition & 1 deletion clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,7 +1505,7 @@ ExpectedType ASTNodeImporter::VisitInjectedClassNameType(
// The InjectedClassNameType is created in VisitRecordDecl when the
// T->getDecl() is imported. Here we can return the existing type.
const Type *Ty = (*ToDeclOrErr)->getTypeForDecl();
assert(Ty && isa<InjectedClassNameType>(Ty));
assert(isa_and_nonnull<InjectedClassNameType>(Ty));
return QualType(Ty, 0);
}

Expand Down
93 changes: 93 additions & 0 deletions clang/lib/AST/CommentParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,31 @@ class TextTokenRetokenizer {
}
}

/// Extract a template type
bool lexTemplate(SmallString<32> &WordText) {
unsigned BracketCount = 0;
while (!isEnd()) {
const char C = peek();
WordText.push_back(C);
consumeChar();
switch (C) {
case '<': {
BracketCount++;
break;
}
case '>': {
BracketCount--;
if (!BracketCount)
return true;
break;
}
default:
break;
}
}
return false;
}

/// Add a token.
/// Returns true on success, false if there are no interesting tokens to
/// fetch from lexer.
Expand Down Expand Up @@ -149,6 +174,54 @@ class TextTokenRetokenizer {
addToken();
}

/// Extract a type argument
bool lexType(Token &Tok) {
if (isEnd())
return false;

// Save current position in case we need to rollback because the type is
// empty.
Position SavedPos = Pos;

// Consume any leading whitespace.
consumeWhitespace();
SmallString<32> WordText;
const char *WordBegin = Pos.BufferPtr;
SourceLocation Loc = getSourceLocation();

while (!isEnd()) {
const char C = peek();
// For non-whitespace characters we check if it's a template or otherwise
// continue reading the text into a word.
if (!isWhitespace(C)) {
if (C == '<') {
if (!lexTemplate(WordText))
return false;
} else {
WordText.push_back(C);
consumeChar();
}
} else {
consumeChar();
break;
}
}

const unsigned Length = WordText.size();
if (Length == 0) {
Pos = SavedPos;
return false;
}

char *TextPtr = Allocator.Allocate<char>(Length + 1);

memcpy(TextPtr, WordText.c_str(), Length + 1);
StringRef Text = StringRef(TextPtr, Length);

formTokenWithChars(Tok, Loc, WordBegin, Length, Text);
return true;
}

/// Extract a word -- sequence of non-whitespace characters.
bool lexWord(Token &Tok) {
if (isEnd())
Expand Down Expand Up @@ -304,6 +377,23 @@ Parser::parseCommandArgs(TextTokenRetokenizer &Retokenizer, unsigned NumArgs) {
return llvm::ArrayRef(Args, ParsedArgs);
}

ArrayRef<Comment::Argument>
Parser::parseThrowCommandArgs(TextTokenRetokenizer &Retokenizer,
unsigned NumArgs) {
auto *Args = new (Allocator.Allocate<Comment::Argument>(NumArgs))
Comment::Argument[NumArgs];
unsigned ParsedArgs = 0;
Token Arg;

while (ParsedArgs < NumArgs && Retokenizer.lexType(Arg)) {
Args[ParsedArgs] = Comment::Argument{
SourceRange(Arg.getLocation(), Arg.getEndLocation()), Arg.getText()};
ParsedArgs++;
}

return llvm::ArrayRef(Args, ParsedArgs);
}

BlockCommandComment *Parser::parseBlockCommand() {
assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command));

Expand Down Expand Up @@ -356,6 +446,9 @@ BlockCommandComment *Parser::parseBlockCommand() {
parseParamCommandArgs(PC, Retokenizer);
else if (TPC)
parseTParamCommandArgs(TPC, Retokenizer);
else if (Info->IsThrowsCommand)
S.actOnBlockCommandArgs(
BC, parseThrowCommandArgs(Retokenizer, Info->NumArgs));
else
S.actOnBlockCommandArgs(BC, parseCommandArgs(Retokenizer, Info->NumArgs));

Expand Down
42 changes: 34 additions & 8 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,17 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Context,
GlobalDeclID ID, std::size_t Extra) {
// Allocate an extra 8 bytes worth of storage, which ensures that the
// resulting pointer will still be 8-byte aligned.
static_assert(sizeof(unsigned) * 2 >= alignof(Decl),
"Decl won't be misaligned");
static_assert(sizeof(uint64_t) >= alignof(Decl), "Decl won't be misaligned");
void *Start = Context.Allocate(Size + Extra + 8);
void *Result = (char*)Start + 8;

unsigned *PrefixPtr = (unsigned *)Result - 2;
uint64_t *PrefixPtr = (uint64_t *)Result - 1;

// Zero out the first 4 bytes; this is used to store the owning module ID.
PrefixPtr[0] = 0;
*PrefixPtr = ID.get();

// Store the global declaration ID in the second 4 bytes.
PrefixPtr[1] = ID.get();
// We leave the upper 16 bits to store the module IDs. 48 bits should be
// sufficient to store a declaration ID.
assert(*PrefixPtr < llvm::maskTrailingOnes<uint64_t>(48));

return Result;
}
Expand All @@ -111,6 +110,29 @@ void *Decl::operator new(std::size_t Size, const ASTContext &Ctx,
return ::operator new(Size + Extra, Ctx);
}

GlobalDeclID Decl::getGlobalID() const {
if (!isFromASTFile())
return GlobalDeclID();
// See the comments in `Decl::operator new` for details.
uint64_t ID = *((const uint64_t *)this - 1);
return GlobalDeclID(ID & llvm::maskTrailingOnes<uint64_t>(48));
}

unsigned Decl::getOwningModuleID() const {
if (!isFromASTFile())
return 0;

uint64_t ID = *((const uint64_t *)this - 1);
return ID >> 48;
}

void Decl::setOwningModuleID(unsigned ID) {
assert(isFromASTFile() && "Only works on a deserialized declaration");
uint64_t *IDAddress = (uint64_t *)this - 1;
*IDAddress &= llvm::maskTrailingOnes<uint64_t>(48);
*IDAddress |= (uint64_t)ID << 48;
}

Module *Decl::getOwningModuleSlow() const {
assert(isFromASTFile() && "Not from AST file?");
return getASTContext().getExternalSource()->getModule(getOwningModuleID());
Expand Down Expand Up @@ -1094,7 +1116,7 @@ bool Decl::isInExportDeclContext() const {
while (DC && !isa<ExportDecl>(DC))
DC = DC->getLexicalParent();

return DC && isa<ExportDecl>(DC);
return isa_and_nonnull<ExportDecl>(DC);
}

bool Decl::isInAnotherModuleUnit() const {
Expand Down Expand Up @@ -2163,3 +2185,7 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C,

return DD;
}

unsigned DeclIDBase::getLocalDeclIndex() const {
return ID & llvm::maskTrailingOnes<DeclID>(32);
}
4 changes: 2 additions & 2 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const {
assert(Source && "getFromExternalSource with no external source");

for (ASTUnresolvedSet::iterator I = Impl.begin(); I != Impl.end(); ++I)
I.setDecl(cast<NamedDecl>(Source->GetExternalDecl(
GlobalDeclID(reinterpret_cast<uintptr_t>(I.getDecl()) >> 2))));
I.setDecl(
cast<NamedDecl>(Source->GetExternalDecl(GlobalDeclID(I.getDeclID()))));
Impl.Decls.setLazy(false);
}

Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
typedef SmallVector<const ClassTemplateSpecializationDecl *, 8> SpecsTy;
SpecsTy Specs;
const DeclContext *Ctx = FD->getDeclContext();
while (Ctx && isa<NamedDecl>(Ctx)) {
while (isa_and_nonnull<NamedDecl>(Ctx)) {
const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Ctx);
if (Spec && !Spec->isExplicitSpecialization())
Expand Down Expand Up @@ -3067,7 +3067,7 @@ Expr *Expr::IgnoreParenCasts() {

Expr *Expr::IgnoreConversionOperatorSingleStep() {
if (auto *MCE = dyn_cast<CXXMemberCallExpr>(this)) {
if (MCE->getMethodDecl() && isa<CXXConversionDecl>(MCE->getMethodDecl()))
if (isa_and_nonnull<CXXConversionDecl>(MCE->getMethodDecl()))
return MCE->getImplicitObjectArgument();
}
return this;
Expand Down
29 changes: 22 additions & 7 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2130,7 +2130,7 @@ static bool IsWeakLValue(const LValue &Value) {

static bool isZeroSized(const LValue &Value) {
const ValueDecl *Decl = GetLValueBaseDecl(Value);
if (Decl && isa<VarDecl>(Decl)) {
if (isa_and_nonnull<VarDecl>(Decl)) {
QualType Ty = Decl->getType();
if (Ty->isArrayType())
return Ty->isIncompleteType() ||
Expand Down Expand Up @@ -15209,11 +15209,21 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat &ResI = Result.getComplexFloatImag();
if (LHSReal) {
assert(!RHSReal && "Cannot have two real operands for a complex op!");
ResR = A * C;
ResI = A * D;
ResR = A;
ResI = A;
// ResR = A * C;
// ResI = A * D;
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, C) ||
!handleFloatFloatBinOp(Info, E, ResI, BO_Mul, D))
return false;
} else if (RHSReal) {
ResR = C * A;
ResI = C * B;
// ResR = C * A;
// ResI = C * B;
ResR = C;
ResI = C;
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Mul, A) ||
!handleFloatFloatBinOp(Info, E, ResI, BO_Mul, B))
return false;
} else {
// In the fully general case, we need to handle NaNs and infinities
// robustly.
Expand Down Expand Up @@ -15289,8 +15299,13 @@ bool ComplexExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
APFloat &ResR = Result.getComplexFloatReal();
APFloat &ResI = Result.getComplexFloatImag();
if (RHSReal) {
ResR = A / C;
ResI = B / C;
ResR = A;
ResI = B;
// ResR = A / C;
// ResI = B / C;
if (!handleFloatFloatBinOp(Info, E, ResR, BO_Div, C) ||
!handleFloatFloatBinOp(Info, E, ResI, BO_Div, C))
return false;
} else {
if (LHSReal) {
// No real optimizations we can do here, stub out with zero.
Expand Down
154 changes: 106 additions & 48 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,15 +318,24 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (DiscardResult)
return this->discard(SubExpr);

std::optional<PrimType> FromT = classify(SubExpr->getType());
QualType SubExprTy = SubExpr->getType();
std::optional<PrimType> FromT = classify(SubExprTy);
std::optional<PrimType> ToT = classify(CE->getType());
if (!FromT || !ToT)
return false;

assert(isPtrType(*FromT));
assert(isPtrType(*ToT));
if (FromT == ToT)
return this->delegate(SubExpr);
if (FromT == ToT) {
if (CE->getType()->isVoidPointerType())
return this->delegate(SubExpr);

if (!this->visit(SubExpr))
return false;
if (FromT == PT_Ptr)
return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE);
return true;
}

if (!this->visit(SubExpr))
return false;
Expand Down Expand Up @@ -1104,14 +1113,9 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
if (!this->visit(Init))
return false;

if (FieldToInit->isBitField()) {
if (!this->emitInitBitField(T, FieldToInit, E))
return false;
} else {
if (!this->emitInitField(T, FieldToInit->Offset, E))
return false;
}
return this->emitPopPtr(E);
if (FieldToInit->isBitField())
return this->emitInitBitField(T, FieldToInit, E);
return this->emitInitField(T, FieldToInit->Offset, E);
};

auto initCompositeField = [=](const Record::Field *FieldToInit,
Expand Down Expand Up @@ -1147,9 +1151,6 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
else
FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();

if (!this->emitDupPtr(E))
return false;

const Record::Field *FieldToInit = R->getField(FToInit);
if (std::optional<PrimType> T = classify(Init)) {
if (!initPrimitiveField(FieldToInit, Init, *T))
Expand All @@ -1169,8 +1170,6 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
while (InitIndex < R->getNumFields() &&
R->getField(InitIndex)->Decl->isUnnamedBitField())
++InitIndex;
if (!this->emitDupPtr(E))
return false;

if (std::optional<PrimType> T = classify(Init)) {
const Record::Field *FieldToInit = R->getField(InitIndex);
Expand All @@ -1180,7 +1179,7 @@ bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
} else {
// Initializer for a direct base class.
if (const Record::Base *B = R->getBase(Init->getType())) {
if (!this->emitGetPtrBasePop(B->Offset, Init))
if (!this->emitGetPtrBase(B->Offset, Init))
return false;

if (!this->visitInitializer(Init))
Expand Down Expand Up @@ -1495,6 +1494,9 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
return false;
}

if (!isa<FieldDecl>(Member))
return this->discard(Base) && this->visitDeclRef(Member, E);

if (Initializing) {
if (!this->delegate(Base))
return false;
Expand All @@ -1504,19 +1506,16 @@ bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
}

// Base above gives us a pointer on the stack.
if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
const RecordDecl *RD = FD->getParent();
const Record *R = getRecord(RD);
if (!R)
return false;
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
return this->emitGetPtrField(F->Offset, E) && maybeLoadValue();
}

return false;
const auto *FD = cast<FieldDecl>(Member);
const RecordDecl *RD = FD->getParent();
const Record *R = getRecord(RD);
if (!R)
return false;
const Record::Field *F = R->getField(FD);
// Leave a pointer to the field on the stack.
if (F->Decl->getType()->isReferenceType())
return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();
}

template <class Emitter>
Expand Down Expand Up @@ -1689,6 +1688,17 @@ bool ByteCodeExprGen<Emitter>::VisitObjCStringLiteral(
return this->delegate(E->getString());
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
auto &A = Ctx.getASTContext();
std::string Str;
A.getObjCEncodingForType(E->getEncodedType(), Str);
StringLiteral *SL =
StringLiteral::Create(A, Str, StringLiteralKind::Ordinary,
/*Pascal=*/false, E->getType(), E->getAtLoc());
return this->delegate(SL);
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitSYCLUniqueStableNameExpr(
const SYCLUniqueStableNameExpr *E) {
Expand Down Expand Up @@ -1844,6 +1854,9 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
std::optional<PrimType> RT = classify(RHS->getType());
std::optional<PrimType> ResultT = classify(E->getType());

if (!Ctx.getLangOpts().CPlusPlus14)
return this->visit(RHS) && this->visit(LHS) && this->emitError(E);

if (!LT || !RT || !ResultT || !LHSComputationT)
return false;

Expand Down Expand Up @@ -2147,9 +2160,6 @@ bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
if (!this->emitInitField(*T, F.Offset, E))
return false;
} else {
if (!this->emitDupPtr(E))
return false;

if (!this->emitGetPtrField(F.Offset, E))
return false;

Expand Down Expand Up @@ -2846,9 +2856,6 @@ bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R,
continue;
}

// TODO: Add GetPtrFieldPop and get rid of this dup.
if (!this->emitDupPtr(E))
return false;
if (!this->emitGetPtrField(Field.Offset, E))
return false;

Expand Down Expand Up @@ -3218,9 +3225,18 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
return this->emitConst(Val.getInt(), ValType, E);

if (Val.isLValue()) {
if (Val.isNullPointer())
return this->emitNull(ValType, nullptr, E);
APValue::LValueBase Base = Val.getLValueBase();
if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
return this->visit(BaseExpr);
else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
return this->visitDeclRef(VD, E);
}
} else if (Val.isMemberPointer()) {
if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
return this->emitGetMemberPtr(MemberDecl, E);
return this->emitNullMemberPtr(nullptr, E);
}

return false;
Expand All @@ -3229,15 +3245,15 @@ bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
template <class Emitter>
bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
const Expr *E) {

if (Val.isStruct()) {
const Record *R = this->getRecord(E->getType());
assert(R);

for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {
const APValue &F = Val.getStructField(I);
const Record::Field *RF = R->getField(I);

if (F.isInt() || F.isLValue()) {
if (F.isInt() || F.isLValue() || F.isMemberPointer()) {
PrimType T = classifyPrim(RF->Decl->getType());
if (!this->visitAPValue(F, T, E))
return false;
Expand All @@ -3249,8 +3265,6 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,
PrimType ElemT = classifyPrim(ArrType->getElementType());
assert(ArrType);

if (!this->emitDupPtr(E))
return false;
if (!this->emitGetPtrField(RF->Offset, E))
return false;

Expand All @@ -3263,11 +3277,28 @@ bool ByteCodeExprGen<Emitter>::visitAPValueInitializer(const APValue &Val,

if (!this->emitPopPtr(E))
return false;
} else if (F.isStruct() || F.isUnion()) {
if (!this->emitGetPtrField(RF->Offset, E))
return false;
if (!this->visitAPValueInitializer(F, E))
return false;
if (!this->emitPopPtr(E))
return false;
} else {
assert(false && "I don't think this should be possible");
}
}
return true;
} else if (Val.isUnion()) {
const FieldDecl *UnionField = Val.getUnionField();
const Record *R = this->getRecord(UnionField->getParent());
assert(R);
const APValue &F = Val.getUnionValue();
const Record::Field *RF = R->getField(UnionField);
PrimType T = classifyPrim(RF->Decl->getType());
if (!this->visitAPValue(F, T, E))
return false;
return this->emitInitElem(T, 0, E);
}
// TODO: Other types.

Expand Down Expand Up @@ -3819,6 +3850,21 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
// we sometimes have to do the lvalue-to-rvalue conversion here manually.
return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);

case UO_Not: // ~x
if (!this->visit(SubExpr))
return false;
// Negate the imaginary component.
if (!this->emitArrayElem(ElemT, 1, E))
return false;
if (!this->emitNeg(ElemT, E))
return false;
if (!this->emitInitElem(ElemT, 1, E))
return false;
return DiscardResult ? this->emitPopPtr(E) : true;

case UO_Extension:
return this->delegate(SubExpr);

default:
return this->emitInvalid(E);
}
Expand All @@ -3827,12 +3873,10 @@ bool ByteCodeExprGen<Emitter>::VisitComplexUnaryOperator(
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
bool ByteCodeExprGen<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
if (DiscardResult)
return true;

const auto *D = E->getDecl();

if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
return this->emitConst(ECD->getInitVal(), E);
} else if (const auto *BD = dyn_cast<BindingDecl>(D)) {
Expand Down Expand Up @@ -3888,6 +3932,14 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
if (IsPtr)
return this->emitGetThisFieldPtr(Offset, E);
return this->emitGetPtrThisField(Offset, E);
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(E);
DRE && DRE->refersToEnclosingVariableOrCapture()) {
if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture()) {
if (!this->visitVarDecl(cast<VarDecl>(D)))
return false;
// Retry.
return this->visitDeclRef(D, E);
}
}

// Try to lazily visit (or emit dummy pointers for) declarations
Expand All @@ -3900,7 +3952,7 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
return this->VisitDeclRefExpr(E);
return this->visitDeclRef(VD, E);
}
}
} else {
Expand All @@ -3910,7 +3962,7 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
if (!this->visitVarDecl(VD))
return false;
// Retry.
return this->VisitDeclRefExpr(E);
return this->visitDeclRef(VD, E);
}
}

Expand All @@ -3927,7 +3979,15 @@ bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
return true;
}

return this->emitInvalidDeclRef(E, E);
if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
return this->emitInvalidDeclRef(DRE, E);
return false;
}

template <class Emitter>
bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
const auto *D = E->getDecl();
return this->visitDeclRef(D, E);
}

template <class Emitter>
Expand Down Expand Up @@ -4167,8 +4227,6 @@ bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Record *R) {
for (const Record::Field &Field : llvm::reverse(R->fields())) {
const Descriptor *D = Field.Desc;
if (!D->isPrimitive() && !D->isPrimitiveArray()) {
if (!this->emitDupPtr(SourceInfo{}))
return false;
if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
return false;
if (!this->emitDestruction(D))
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E);
bool VisitStringLiteral(const StringLiteral *E);
bool VisitObjCStringLiteral(const ObjCStringLiteral *E);
bool VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
bool VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr *E);
bool VisitCharacterLiteral(const CharacterLiteral *E);
bool VisitCompoundAssignOperator(const CompoundAssignOperator *E);
Expand Down Expand Up @@ -189,6 +190,8 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>,
/// Visit an APValue.
bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
bool visitAPValueInitializer(const APValue &Val, const Expr *E);
/// Visit the given decl as if we have a reference to it.
bool visitDeclRef(const ValueDecl *D, const Expr *E);

/// Visits an expression and converts it to a boolean.
bool visitBool(const Expr *E);
Expand Down
35 changes: 19 additions & 16 deletions clang/lib/AST/Interp/EvalEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ void EvalEmitter::cleanup() { S.cleanup(); }
EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
bool ConvertResultToRValue) {
S.setEvalLocation(E->getExprLoc());
this->ConvertResultToRValue = ConvertResultToRValue;
this->ConvertResultToRValue = ConvertResultToRValue && !isa<ConstantExpr>(E);
this->CheckFullyInitialized = isa<ConstantExpr>(E);
EvalResult.setSource(E);

if (!this->visitExpr(E)) {
Expand All @@ -55,10 +56,14 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
bool CheckFullyInitialized) {
this->CheckFullyInitialized = CheckFullyInitialized;
this->ConvertResultToRValue =
VD->getAnyInitializer() &&
(VD->getAnyInitializer()->getType()->isAnyComplexType() ||
VD->getAnyInitializer()->getType()->isVectorType());

if (const Expr *Init = VD->getAnyInitializer()) {
QualType T = VD->getType();
this->ConvertResultToRValue = !Init->isGLValue() && !T->isPointerType() &&
!T->isObjCObjectPointerType();
} else
this->ConvertResultToRValue = false;

EvalResult.setSource(VD);

if (!this->visitDecl(VD) && EvalResult.empty())
Expand Down Expand Up @@ -137,6 +142,10 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
return true;

const Pointer &Ptr = S.Stk.pop<Pointer>();

if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
return false;

// Implicitly convert lvalue to rvalue, if requested.
if (ConvertResultToRValue) {
if (std::optional<APValue> V = Ptr.toRValue(Ctx)) {
Expand All @@ -145,17 +154,7 @@ template <> bool EvalEmitter::emitRet<PT_Ptr>(const SourceInfo &Info) {
return false;
}
} else {
if (CheckFullyInitialized) {
if (!EvalResult.checkFullyInitialized(S, Ptr))
return false;

std::optional<APValue> RValueResult = Ptr.toRValue(Ctx);
if (!RValueResult)
return false;
EvalResult.setValue(*RValueResult);
} else {
EvalResult.setValue(Ptr.toAPValue());
}
EvalResult.setValue(Ptr.toAPValue());
}

return true;
Expand All @@ -175,6 +174,10 @@ bool EvalEmitter::emitRetVoid(const SourceInfo &Info) {

bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
const auto &Ptr = S.Stk.pop<Pointer>();

if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
return false;

if (std::optional<APValue> APV = Ptr.toRValue(S.getCtx())) {
EvalResult.setValue(*APV);
return true;
Expand Down
23 changes: 12 additions & 11 deletions clang/lib/AST/Interp/EvaluationResult.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,21 +141,22 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
const Pointer &Ptr) const {
assert(Source);
assert(empty());

// Our Source must be a VarDecl.
const Decl *SourceDecl = Source.dyn_cast<const Decl *>();
assert(SourceDecl);
const auto *VD = cast<VarDecl>(SourceDecl);
assert(VD->getType()->isRecordType() || VD->getType()->isArrayType());
SourceLocation InitLoc = VD->getAnyInitializer()->getExprLoc();

assert(!Ptr.isZero());

SourceLocation InitLoc;
if (const auto *D = Source.dyn_cast<const Decl *>())
InitLoc = cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
else if (const auto *E = Source.dyn_cast<const Expr *>())
InitLoc = E->getExprLoc();

if (const Record *R = Ptr.getRecord())
return CheckFieldsInitialized(S, InitLoc, Ptr, R);
const auto *CAT =
cast<ConstantArrayType>(Ptr.getType()->getAsArrayTypeUnsafe());
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);

if (const auto *CAT = dyn_cast_if_present<ConstantArrayType>(
Ptr.getType()->getAsArrayTypeUnsafe()))
return CheckArrayInitialized(S, InitLoc, Ptr, CAT);

return true;
}

} // namespace interp
Expand Down
56 changes: 55 additions & 1 deletion clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1283,9 +1283,32 @@ inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
return true;
}

/// 1) Pops a Pointer from the stack
/// 1) Peeks a Pointer
/// 2) Pushes Pointer.atField(Off) on the stack
inline bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.peek<Pointer>();

if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
!CheckNull(S, OpPC, Ptr, CSK_Field))
return false;

if (!CheckExtern(S, OpPC, Ptr))
return false;
if (!CheckRange(S, OpPC, Ptr, CSK_Field))
return false;
if (!CheckArray(S, OpPC, Ptr))
return false;
if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
return false;

if (Ptr.isBlockPointer() && Off > Ptr.block()->getSize())
return false;

S.Stk.push<Pointer>(Ptr.atField(Off));
return true;
}

inline bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (S.getLangOpts().CPlusPlus && S.inConstantContext() &&
Expand Down Expand Up @@ -1914,6 +1937,9 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
Expand All @@ -1926,6 +1952,9 @@ static inline bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
Expand All @@ -1939,6 +1968,9 @@ static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
uint32_t BitWidth) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isDummy())
return false;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
Expand All @@ -1948,6 +1980,28 @@ static inline bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC,
return true;
}

static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
const auto &Ptr = S.Stk.peek<Pointer>();

if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
bool HasValidResult = !Ptr.isZero();

if (HasValidResult) {
// FIXME: note_constexpr_invalid_void_star_cast
} else if (!S.getLangOpts().CPlusPlus26) {
const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 3 << "'void *'" << S.Current->getRange(OpPC);
}
} else {
const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
}

return true;
}

//===----------------------------------------------------------------------===//
// Zero, Nullptr
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/Interp/MemberPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class MemberPointer final {
bool hasBase() const { return !Base.isZero(); }

void print(llvm::raw_ostream &OS) const {
OS << "MemberPtr(" << Base << " " << (void *)Dcl << " + " << PtrOffset
OS << "MemberPtr(" << Base << " " << (const void *)Dcl << " + " << PtrOffset
<< ")";
}

Expand Down
74 changes: 19 additions & 55 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ class AluOpcode : Opcode {
}

class FloatOpcode : Opcode {
let Types = [];
let Args = [ArgRoundingMode];
}

Expand Down Expand Up @@ -195,17 +194,14 @@ def NoRet : Opcode {}

def Call : Opcode {
let Args = [ArgFunction, ArgUint32];
let Types = [];
}

def CallVirt : Opcode {
let Args = [ArgFunction, ArgUint32];
let Types = [];
}

def CallBI : Opcode {
let Args = [ArgFunction, ArgCallExpr];
let Types = [];
}

def CallPtr : Opcode {
Expand All @@ -214,7 +210,6 @@ def CallPtr : Opcode {

def CallVar : Opcode {
let Args = [ArgFunction, ArgUint32];
let Types = [];
}

def OffsetOf : Opcode {
Expand Down Expand Up @@ -281,53 +276,31 @@ def Null : Opcode {
//===----------------------------------------------------------------------===//
// Pointer generation
//===----------------------------------------------------------------------===//
class OffsetOpcode : Opcode {
let Args = [ArgUint32];
}

// [] -> [Pointer]
def GetPtrLocal : Opcode {
// Offset of local.
let Args = [ArgUint32];
def GetPtrLocal : OffsetOpcode {
bit HasCustomEval = 1;
}
// [] -> [Pointer]
def GetPtrParam : Opcode {
// Offset of parameter.
let Args = [ArgUint32];
}
def GetPtrParam : OffsetOpcode;
// [] -> [Pointer]
def GetPtrGlobal : Opcode {
// Index of global.
let Args = [ArgUint32];
}
def GetPtrGlobal : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrField : OffsetOpcode;
def GetPtrFieldPop : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrActiveField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrActiveField : OffsetOpcode;
// [] -> [Pointer]
def GetPtrActiveThisField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrActiveThisField : OffsetOpcode;
// [] -> [Pointer]
def GetPtrThisField : Opcode {
// Offset of field.
let Args = [ArgUint32];
}
def GetPtrThisField : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrBase : Opcode {
// Offset of field, which is a base.
let Args = [ArgUint32];
}
def GetPtrBase : OffsetOpcode;
// [Pointer] -> [Pointer]
def GetPtrBasePop : Opcode {
// Offset of field, which is a base.
let Args = [ArgUint32];
}
def GetPtrBasePop : OffsetOpcode;
def GetMemberPtrBasePop : Opcode {
// Offset of field, which is a base.
let Args = [ArgSint32];
Expand Down Expand Up @@ -421,8 +394,6 @@ def InitGlobalTemp : AccessOpcode {
// [Pointer] -> [Pointer]
def InitGlobalTempComp : Opcode {
let Args = [ArgLETD];
let Types = [];
let HasGroup = 0;
}
// [Value] -> []
def SetGlobal : AccessOpcode;
Expand Down Expand Up @@ -527,13 +498,9 @@ def SubPtr : Opcode {
}

// [Pointer] -> [Pointer]
def IncPtr : Opcode {
let HasGroup = 0;
}
def IncPtr : Opcode;
// [Pointer] -> [Pointer]
def DecPtr : Opcode {
let HasGroup = 0;
}
def DecPtr : Opcode;

//===----------------------------------------------------------------------===//
// Function pointers.
Expand Down Expand Up @@ -629,7 +596,6 @@ def Cast: Opcode {
}

def CastFP : Opcode {
let Types = [];
let Args = [ArgFltSemantics, ArgRoundingMode];
}

Expand Down Expand Up @@ -664,12 +630,10 @@ def CastFloatingIntegral : Opcode {
}

def CastFloatingIntegralAP : Opcode {
let Types = [];
let Args = [ArgUint32];
}

def CastFloatingIntegralAPS : Opcode {
let Types = [];
let Args = [ArgUint32];
}

Expand All @@ -678,15 +642,15 @@ def CastPointerIntegral : Opcode {
let HasGroup = 1;
}
def CastPointerIntegralAP : Opcode {
let Types = [];
let HasGroup = 0;
let Args = [ArgUint32];
}
def CastPointerIntegralAPS : Opcode {
let Types = [];
let HasGroup = 0;
let Args = [ArgUint32];
}
def PtrPtrCast : Opcode {
let Args = [ArgBool];

}

def DecayPtr : Opcode {
let Types = [PtrTypeClass, PtrTypeClass];
Expand Down
46 changes: 24 additions & 22 deletions clang/lib/AST/Interp/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,53 +64,55 @@ Pointer::~Pointer() {
}

void Pointer::operator=(const Pointer &P) {
if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));

// If the current storage type is Block, we need to remove
// this pointer from the block.
bool WasBlockPointer = isBlockPointer();
StorageKind = P.StorageKind;
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
if (WasBlockPointer && PointeeStorage.BS.Pointee)
if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
Old->cleanup();
}
}

Offset = P.Offset;
StorageKind = P.StorageKind;
Offset = P.Offset;

if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee;

if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);

if (WasBlockPointer && Old)
Old->cleanup();

} else if (StorageKind == Storage::Int) {
} else if (P.isIntegralPointer()) {
PointeeStorage.Int = P.PointeeStorage.Int;
} else {
assert(false && "Unhandled storage kind");
}
}

void Pointer::operator=(Pointer &&P) {
if (!this->isIntegralPointer() || !P.isBlockPointer())
assert(P.StorageKind == StorageKind || (this->isZero() && P.isZero()));

// If the current storage type is Block, we need to remove
// this pointer from the block.
bool WasBlockPointer = isBlockPointer();
StorageKind = P.StorageKind;
if (StorageKind == Storage::Block) {
Block *Old = PointeeStorage.BS.Pointee;
if (WasBlockPointer && PointeeStorage.BS.Pointee)
if (WasBlockPointer && Old) {
PointeeStorage.BS.Pointee->removePointer(this);
Old->cleanup();
}
}

Offset = P.Offset;
StorageKind = P.StorageKind;
Offset = P.Offset;

if (P.isBlockPointer()) {
PointeeStorage.BS = P.PointeeStorage.BS;
PointeeStorage.BS.Pointee = P.PointeeStorage.BS.Pointee;

if (PointeeStorage.BS.Pointee)
PointeeStorage.BS.Pointee->addPointer(this);

if (WasBlockPointer && Old)
Old->cleanup();

} else if (StorageKind == Storage::Int) {
} else if (P.isIntegralPointer()) {
PointeeStorage.Int = P.PointeeStorage.Int;
} else {
assert(false && "Unhandled storage kind");
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/AST/Mangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,9 +301,8 @@ void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD,
} else {
assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) &&
"expected a NamedDecl or BlockDecl");
if (isa<BlockDecl>(DC))
for (; DC && isa<BlockDecl>(DC); DC = DC->getParent())
(void) getBlockId(cast<BlockDecl>(DC), true);
for (; isa_and_nonnull<BlockDecl>(DC); DC = DC->getParent())
(void)getBlockId(cast<BlockDecl>(DC), true);
assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) &&
"expected a TranslationUnitDecl or a NamedDecl");
if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC))
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,8 @@ void MicrosoftCXXNameMangler::mangleFloat(llvm::APFloat Number) {
case APFloat::S_Float8E4M3FNUZ:
case APFloat::S_Float8E4M3B11FNUZ:
case APFloat::S_FloatTF32:
case APFloat::S_Float6E3M2FN:
case APFloat::S_Float6E2M3FN:
llvm_unreachable("Tried to mangle unexpected APFloat semantics");
}

Expand Down Expand Up @@ -2748,7 +2750,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
return;
}
Out << '@';
} else if (IsInLambda && D && isa<CXXConversionDecl>(D)) {
} else if (IsInLambda && isa_and_nonnull<CXXConversionDecl>(D)) {
// The only lambda conversion operators are to function pointers, which
// can differ by their calling convention and are typically deduced. So
// we make sure that this type gets mangled properly.
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/ParentMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,9 @@ Stmt* ParentMap::getParent(Stmt* S) const {
}

Stmt *ParentMap::getParentIgnoreParens(Stmt *S) const {
do { S = getParent(S); } while (S && isa<ParenExpr>(S));
do {
S = getParent(S);
} while (isa_and_nonnull<ParenExpr>(S));
return S;
}

Expand All @@ -155,7 +157,8 @@ Stmt *ParentMap::getParentIgnoreParenCasts(Stmt *S) const {
Stmt *ParentMap::getParentIgnoreParenImpCasts(Stmt *S) const {
do {
S = getParent(S);
} while (S && isa<Expr>(S) && cast<Expr>(S)->IgnoreParenImpCasts() != S);
} while (isa_and_nonnull<Expr>(S) &&
cast<Expr>(S)->IgnoreParenImpCasts() != S);

return S;
}
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/StmtPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ namespace {

void PrintStmt(Stmt *S, int SubIndent) {
IndentLevel += SubIndent;
if (S && isa<Expr>(S)) {
if (isa_and_nonnull<Expr>(S)) {
// If this is an expr used in a stmt context, indent and newline it.
Indent();
Visit(S);
Expand Down Expand Up @@ -1939,7 +1939,7 @@ void StmtPrinter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
void StmtPrinter::VisitCXXMemberCallExpr(CXXMemberCallExpr *Node) {
// If we have a conversion operator call only print the argument.
CXXMethodDecl *MD = Node->getMethodDecl();
if (MD && isa<CXXConversionDecl>(MD)) {
if (isa_and_nonnull<CXXConversionDecl>(MD)) {
PrintExpr(Node->getImplicitObjectArgument());
return;
}
Expand Down
9 changes: 0 additions & 9 deletions clang/lib/AST/TemplateBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,6 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
}
}

void TemplateArgument::dump(raw_ostream &Out) const {
LangOptions LO; // FIXME! see also TemplateName::dump().
LO.CPlusPlus = true;
LO.Bool = true;
print(PrintingPolicy(LO), Out, /*IncludeType*/ true);
}

LLVM_DUMP_METHOD void TemplateArgument::dump() const { dump(llvm::errs()); }

//===----------------------------------------------------------------------===//
// TemplateArgumentLoc Implementation
//===----------------------------------------------------------------------===//
Expand Down
11 changes: 0 additions & 11 deletions clang/lib/AST/TemplateName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,14 +360,3 @@ const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,
OS.flush();
return DB << NameStr;
}

void TemplateName::dump(raw_ostream &OS) const {
LangOptions LO; // FIXME!
LO.CPlusPlus = true;
LO.Bool = true;
print(OS, PrintingPolicy(LO));
}

LLVM_DUMP_METHOD void TemplateName::dump() const {
dump(llvm::errs());
}
11 changes: 7 additions & 4 deletions clang/lib/Analysis/FlowSensitive/ASTOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ getFieldsForInitListExpr(const InitListT *InitList) {
std::vector<const FieldDecl *> Fields;

if (InitList->getType()->isUnionType()) {
Fields.push_back(InitList->getInitializedFieldInUnion());
if (const FieldDecl *Field = InitList->getInitializedFieldInUnion())
Fields.push_back(Field);
return Fields;
}

Expand Down Expand Up @@ -137,9 +138,11 @@ RecordInitListHelper::RecordInitListHelper(
// it doesn't do this -- so we create an `ImplicitValueInitExpr` ourselves.
SmallVector<Expr *> InitsForUnion;
if (Ty->isUnionType() && Inits.empty()) {
assert(Fields.size() == 1);
ImplicitValueInitForUnion.emplace(Fields.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
assert(Fields.size() <= 1);
if (!Fields.empty()) {
ImplicitValueInitForUnion.emplace(Fields.front()->getType());
InitsForUnion.push_back(&*ImplicitValueInitForUnion);
}
Inits = InitsForUnion;
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ class ResultObjectVisitor : public AnalysisASTVisitor<ResultObjectVisitor> {
// below them can initialize the same object (or part of it).
if (isa<CXXConstructExpr>(E) || isa<CallExpr>(E) || isa<LambdaExpr>(E) ||
isa<CXXDefaultArgExpr>(E) || isa<CXXDefaultInitExpr>(E) ||
isa<CXXStdInitializerListExpr>(E) ||
isa<CXXStdInitializerListExpr>(E) || isa<AtomicExpr>(E) ||
// We treat `BuiltinBitCastExpr` as an "original initializer" too as
// it may not even be casting from a record type -- and even if it is,
// the two objects are in general of unrelated type.
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Basic/Targets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,8 +673,11 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
}
case llvm::Triple::spirv64: {
if (os != llvm::Triple::UnknownOS ||
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment)
Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) {
if (os == llvm::Triple::OSType::AMDHSA)
return std::make_unique<SPIRV64AMDGCNTargetInfo>(Triple, Opts);
return nullptr;
}
return std::make_unique<SPIRV64TargetInfo>(Triple, Opts);
}
case llvm::Triple::wasm32:
Expand Down
6 changes: 4 additions & 2 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,6 @@ void AArch64TargetInfo::getTargetDefinesARMV84A(const LangOptions &Opts,
void AArch64TargetInfo::getTargetDefinesARMV85A(const LangOptions &Opts,
MacroBuilder &Builder) const {
Builder.defineMacro("__ARM_FEATURE_FRINT", "1");
Builder.defineMacro("__ARM_FEATURE_BTI", "1");
// Also include the Armv8.4 defines
getTargetDefinesARMV84A(Opts, Builder);
}
Expand Down Expand Up @@ -499,6 +498,9 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts,
if (HasPAuthLR)
Builder.defineMacro("__ARM_FEATURE_PAUTH_LR", "1");

if (HasBTI)
Builder.defineMacro("__ARM_FEATURE_BTI", "1");

if (HasUnalignedAccess)
Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");

Expand Down Expand Up @@ -1085,7 +1087,7 @@ bool AArch64TargetInfo::initFeatureMap(
std::string UpdatedFeature = Feature;
if (Feature[0] == '+') {
std::optional<llvm::AArch64::ExtensionInfo> Extension =
llvm::AArch64::parseArchExtension(Feature.substr(1));
llvm::AArch64::parseArchExtension(Feature.substr(1));
if (Extension)
UpdatedFeature = Extension->Feature.str();
}
Expand Down
75 changes: 75 additions & 0 deletions clang/lib/Basic/Targets/SPIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
//===----------------------------------------------------------------------===//

#include "SPIR.h"
#include "AMDGPU.h"
#include "Targets.h"
#include "llvm/TargetParser/TargetParser.h"

using namespace clang;
using namespace clang::targets;
Expand Down Expand Up @@ -54,3 +56,76 @@ void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts,
BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
DefineStd(Builder, "SPIRV64", Opts);
}

static const AMDGPUTargetInfo AMDGPUTI(llvm::Triple("amdgcn-amd-amdhsa"), {});

ArrayRef<const char *> SPIRV64AMDGCNTargetInfo::getGCCRegNames() const {
return AMDGPUTI.getGCCRegNames();
}

bool SPIRV64AMDGCNTargetInfo::initFeatureMap(
llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef,
const std::vector<std::string> &FeatureVec) const {
llvm::AMDGPU::fillAMDGPUFeatureMap({}, getTriple(), Features);

return TargetInfo::initFeatureMap(Features, Diags, {}, FeatureVec);
}

bool SPIRV64AMDGCNTargetInfo::validateAsmConstraint(
const char *&Name, TargetInfo::ConstraintInfo &Info) const {
return AMDGPUTI.validateAsmConstraint(Name, Info);
}

std::string
SPIRV64AMDGCNTargetInfo::convertConstraint(const char *&Constraint) const {
return AMDGPUTI.convertConstraint(Constraint);
}

ArrayRef<Builtin::Info> SPIRV64AMDGCNTargetInfo::getTargetBuiltins() const {
return AMDGPUTI.getTargetBuiltins();
}

void SPIRV64AMDGCNTargetInfo::getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const {
BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder);
DefineStd(Builder, "SPIRV64", Opts);

Builder.defineMacro("__AMD__");
Builder.defineMacro("__AMDGPU__");
Builder.defineMacro("__AMDGCN__");
}

void SPIRV64AMDGCNTargetInfo::setAuxTarget(const TargetInfo *Aux) {
assert(Aux && "Cannot invoke setAuxTarget without a valid auxiliary target!");

// This is a 1:1 copy of AMDGPUTargetInfo::setAuxTarget()
assert(HalfFormat == Aux->HalfFormat);
assert(FloatFormat == Aux->FloatFormat);
assert(DoubleFormat == Aux->DoubleFormat);

// On x86_64 long double is 80-bit extended precision format, which is
// not supported by AMDGPU. 128-bit floating point format is also not
// supported by AMDGPU. Therefore keep its own format for these two types.
auto SaveLongDoubleFormat = LongDoubleFormat;
auto SaveFloat128Format = Float128Format;
auto SaveLongDoubleWidth = LongDoubleWidth;
auto SaveLongDoubleAlign = LongDoubleAlign;
copyAuxTarget(Aux);
LongDoubleFormat = SaveLongDoubleFormat;
Float128Format = SaveFloat128Format;
LongDoubleWidth = SaveLongDoubleWidth;
LongDoubleAlign = SaveLongDoubleAlign;
// For certain builtin types support on the host target, claim they are
// supported to pass the compilation of the host code during the device-side
// compilation.
// FIXME: As the side effect, we also accept `__float128` uses in the device
// code. To reject these builtin types supported in the host target but not in
// the device target, one approach would support `device_builtin` attribute
// so that we could tell the device builtin types from the host ones. This
// also solves the different representations of the same builtin type, such
// as `size_t` in the MSVC environment.
if (Aux->hasFloat128Type()) {
HasFloat128 = true;
Float128Format = DoubleFormat;
}
}
51 changes: 51 additions & 0 deletions clang/lib/Basic/Targets/SPIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,57 @@ class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo {
MacroBuilder &Builder) const override;
};

class LLVM_LIBRARY_VISIBILITY SPIRV64AMDGCNTargetInfo final
: public BaseSPIRVTargetInfo {
public:
SPIRV64AMDGCNTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: BaseSPIRVTargetInfo(Triple, Opts) {
assert(Triple.getArch() == llvm::Triple::spirv64 &&
"Invalid architecture for 64-bit AMDGCN SPIR-V.");
assert(Triple.getVendor() == llvm::Triple::VendorType::AMD &&
"64-bit AMDGCN SPIR-V target must use AMD vendor");
assert(getTriple().getOS() == llvm::Triple::OSType::AMDHSA &&
"64-bit AMDGCN SPIR-V target must use AMDHSA OS");
assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment &&
"64-bit SPIR-V target must use unknown environment type");
PointerWidth = PointerAlign = 64;
SizeType = TargetInfo::UnsignedLong;
PtrDiffType = IntPtrType = TargetInfo::SignedLong;

resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-"
"v96:128-v192:256-v256:256-v512:512-v1024:1024-G1-P4-A0");

BFloat16Width = BFloat16Align = 16;
BFloat16Format = &llvm::APFloat::BFloat();

HasLegalHalfType = true;
HasFloat16 = true;
HalfArgsAndReturns = true;
}

bool hasBFloat16Type() const override { return true; }

ArrayRef<const char *> getGCCRegNames() const override;

bool initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags,
StringRef,
const std::vector<std::string> &) const override;

bool validateAsmConstraint(const char *&Name,
TargetInfo::ConstraintInfo &Info) const override;

std::string convertConstraint(const char *&Constraint) const override;

ArrayRef<Builtin::Info> getTargetBuiltins() const override;

void getTargetDefines(const LangOptions &Opts,
MacroBuilder &Builder) const override;

void setAuxTarget(const TargetInfo *Aux) override;

bool hasInt128Type() const override { return TargetInfo::hasInt128Type(); }
};

} // namespace targets
} // namespace clang
#endif // LLVM_CLANG_LIB_BASIC_TARGETS_SPIR_H
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGBlocks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF,

// First, 'this'.
if (block->capturesCXXThis()) {
assert(CGF && CGF->CurFuncDecl && isa<CXXMethodDecl>(CGF->CurFuncDecl) &&
assert(CGF && isa_and_nonnull<CXXMethodDecl>(CGF->CurFuncDecl) &&
"Can't capture 'this' outside a method");
QualType thisType = cast<CXXMethodDecl>(CGF->CurFuncDecl)->getThisType();

Expand Down
19 changes: 19 additions & 0 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2923,6 +2923,18 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
SetSqrtFPAccuracy(Call);
return RValue::get(Call);
}

case Builtin::BItan:
case Builtin::BItanf:
case Builtin::BItanl:
case Builtin::BI__builtin_tan:
case Builtin::BI__builtin_tanf:
case Builtin::BI__builtin_tanf16:
case Builtin::BI__builtin_tanl:
case Builtin::BI__builtin_tanf128:
return RValue::get(emitUnaryMaybeConstrainedFPBuiltin(
*this, E, Intrinsic::tan, Intrinsic::experimental_constrained_tan));

case Builtin::BItrunc:
case Builtin::BItruncf:
case Builtin::BItruncl:
Expand Down Expand Up @@ -6012,6 +6024,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
llvm::Triple::getArchTypePrefix(getTarget().getTriple().getArch());
if (!Prefix.empty()) {
IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin(Prefix.data(), Name);
if (IntrinsicID == Intrinsic::not_intrinsic && Prefix == "spv" &&
getTarget().getTriple().getOS() == llvm::Triple::OSType::AMDHSA)
IntrinsicID = Intrinsic::getIntrinsicForClangBuiltin("amdgcn", Name);
// NOTE we don't need to perform a compatibility flag check here since the
// intrinsics are declared in Builtins*.def via LANGBUILTIN which filter the
// MS builtins via ALL_MS_LANGUAGES and are filtered earlier.
Expand Down Expand Up @@ -6182,6 +6197,10 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF,
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
return CGF->EmitRISCVBuiltinExpr(BuiltinID, E, ReturnValue);
case llvm::Triple::spirv64:
if (CGF->getTarget().getTriple().getOS() != llvm::Triple::OSType::AMDHSA)
return nullptr;
return CGF->EmitAMDGPUBuiltinExpr(BuiltinID, E);
default:
return nullptr;
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1917,6 +1917,7 @@ static void getTrivialDefaultFunctionAttributes(
case CodeGenOptions::FramePointerKind::None:
// This is the default behavior.
break;
case CodeGenOptions::FramePointerKind::Reserved:
case CodeGenOptions::FramePointerKind::NonLeaf:
case CodeGenOptions::FramePointerKind::All:
FuncAttrs.addAttribute("frame-pointer",
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -859,7 +859,7 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {

// Enter the function-try-block before the constructor prologue if
// applicable.
bool IsTryBody = (Body && isa<CXXTryStmt>(Body));
bool IsTryBody = isa_and_nonnull<CXXTryStmt>(Body);
if (IsTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);

Expand Down Expand Up @@ -1475,7 +1475,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {

// If the body is a function-try-block, enter the try before
// anything else.
bool isTryBody = (Body && isa<CXXTryStmt>(Body));
bool isTryBody = isa_and_nonnull<CXXTryStmt>(Body);
if (isTryBody)
EnterCXXTryStmt(*cast<CXXTryStmt>(Body), true);
EmitAsanPrologueOrEpilogue(false);
Expand Down
43 changes: 20 additions & 23 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,16 @@ using namespace clang::CodeGen;

static uint32_t getTypeAlignIfRequired(const Type *Ty, const ASTContext &Ctx) {
auto TI = Ctx.getTypeInfo(Ty);
return TI.isAlignRequired() ? TI.Align : 0;
if (TI.isAlignRequired())
return TI.Align;

// MaxFieldAlignmentAttr is the attribute added to types
// declared after #pragma pack(n).
if (auto *Decl = Ty->getAsRecordDecl())
if (Decl->hasAttr<MaxFieldAlignmentAttr>())
return TI.Align;

return 0;
}

static uint32_t getTypeAlignIfRequired(QualType Ty, const ASTContext &Ctx) {
Expand Down Expand Up @@ -5757,28 +5766,16 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder,
// it is loaded upon use, so we identify such pattern here.
if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) {
llvm::Value *Var = Load->getPointerOperand();
if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) {
if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists(
CGM.getLLVMContext(), MDValue)) {
for (llvm::User *U : DbgValue->users()) {
if (llvm::CallInst *DbgDeclare = dyn_cast<llvm::CallInst>(U)) {
if (DbgDeclare->getCalledFunction()->getIntrinsicID() ==
llvm::Intrinsic::dbg_declare &&
DbgDeclare->getArgOperand(0) == DbgValue) {
// There can be implicit type cast applied on a variable if it is
// an opaque ptr, in this case its debug info may not match the
// actual type of object being used as in the next instruction, so
// we will need to emit a pseudo variable for type-casted value.
llvm::DILocalVariable *MDNode = cast<llvm::DILocalVariable>(
cast<llvm::MetadataAsValue>(DbgDeclare->getOperand(1))
->getMetadata());
if (MDNode->getType() == Type)
return;
}
}
}
}
}
// There can be implicit type cast applied on a variable if it is an opaque
// ptr, in this case its debug info may not match the actual type of object
// being used as in the next instruction, so we will need to emit a pseudo
// variable for type-casted value.
auto DeclareTypeMatches = [&](auto *DbgDeclare) {
return DbgDeclare->getVariable()->getType() == Type;
};
if (any_of(llvm::findDbgDeclares(Var), DeclareTypeMatches) ||
any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches))
return;
}

// Find the correct location to insert a sequence of instructions to
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,10 @@ llvm::Function *CodeGenModule::CreateGlobalInitOrCleanUpFunction(
!isInNoSanitizeList(SanitizerKind::Thread, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeThread);

if (getLangOpts().Sanitize.has(SanitizerKind::NumericalStability) &&
!isInNoSanitizeList(SanitizerKind::NumericalStability, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeNumericalStability);

if (getLangOpts().Sanitize.has(SanitizerKind::Memory) &&
!isInNoSanitizeList(SanitizerKind::Memory, Fn, Loc))
Fn->addFnAttr(llvm::Attribute::SanitizeMemory);
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3571,9 +3571,8 @@ void CodeGenFunction::EmitCheck(
llvm::BasicBlock *Handlers = createBasicBlock("handler." + CheckName);
llvm::Instruction *Branch = Builder.CreateCondBr(JointCond, Cont, Handlers);
// Give hint that we very much don't expect to execute the handler
// Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
llvm::MDBuilder MDHelper(getLLVMContext());
llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1);
llvm::MDNode *Node = MDHelper.createLikelyBranchWeights();
Branch->setMetadata(llvm::LLVMContext::MD_prof, Node);
EmitBlock(Handlers);

Expand Down Expand Up @@ -3641,7 +3640,7 @@ void CodeGenFunction::EmitCfiSlowPathCheck(
llvm::BranchInst *BI = Builder.CreateCondBr(Cond, Cont, CheckBB);

llvm::MDBuilder MDHelper(getLLVMContext());
llvm::MDNode *Node = MDHelper.createBranchWeights((1U << 20) - 1, 1);
llvm::MDNode *Node = MDHelper.createLikelyBranchWeights();
BI->setMetadata(llvm::LLVMContext::MD_prof, Node);

EmitBlock(CheckBB);
Expand Down
Loading