63 changes: 41 additions & 22 deletions clang-tools-extra/clangd/ModulesBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/FrontendActions.h"
#include "clang/Serialization/ASTReader.h"
#include "clang/Serialization/InMemoryModuleCache.h"

namespace clang {
namespace clangd {
Expand Down Expand Up @@ -127,50 +128,68 @@ struct ModuleFile {
std::string ModuleFilePath;
};

bool IsModuleFileUpToDate(
PathRef ModuleFilePath,
const PrerequisiteModules &RequisiteModules) {
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
CompilerInstance::createDiagnostics(new DiagnosticOptions());

bool IsModuleFileUpToDate(PathRef ModuleFilePath,
const PrerequisiteModules &RequisiteModules,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
auto HSOpts = std::make_shared<HeaderSearchOptions>();
RequisiteModules.adjustHeaderSearchOptions(*HSOpts);
HSOpts->ForceCheckCXX20ModulesInputFiles = true;
HSOpts->ValidateASTInputFilesContent = true;

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

LangOptions LangOpts;
LangOpts.SkipODRCheckInGMF = true;

FileManager FileMgr(FileSystemOptions(), VFS);

SourceManager SourceMgr(*Diags, FileMgr);

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

TrivialModuleLoader ModuleLoader;
Preprocessor PP(std::make_shared<PreprocessorOptions>(), *Diags, LangOpts,
SourceMgr, HeaderInfo, ModuleLoader);

IntrusiveRefCntPtr<InMemoryModuleCache> ModuleCache = new InMemoryModuleCache;
PCHContainerOperations PCHOperations;
std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
ModuleFilePath.str(), PCHOperations.getRawReader(), ASTUnit::LoadASTOnly,
Diags, FileSystemOptions(), std::move(HSOpts));
ASTReader Reader(PP, *ModuleCache, /*ASTContext=*/nullptr,
PCHOperations.getRawReader(), {});

if (!Unit)
return false;
// We don't need any listener here. By default it will use a validator
// listener.
Reader.setListener(nullptr);

auto Reader = Unit->getASTReader();
if (!Reader)
if (Reader.ReadAST(ModuleFilePath, serialization::MK_MainFile,
SourceLocation(),
ASTReader::ARR_None) != ASTReader::Success)
return false;

bool UpToDate = true;
Reader->getModuleManager().visit([&](serialization::ModuleFile &MF) -> bool {
Reader->visitInputFiles(
Reader.getModuleManager().visit([&](serialization::ModuleFile &MF) -> bool {
Reader.visitInputFiles(
MF, /*IncludeSystem=*/false, /*Complain=*/false,
[&](const serialization::InputFile &IF, bool isSystem) {
if (!IF.getFile() || IF.isOutOfDate())
UpToDate = false;
});

return !UpToDate;
});

return UpToDate;
}

bool IsModuleFilesUpToDate(
llvm::SmallVector<PathRef> ModuleFilePaths,
const PrerequisiteModules &RequisiteModules) {
return llvm::all_of(ModuleFilePaths, [&RequisiteModules](auto ModuleFilePath) {
return IsModuleFileUpToDate(ModuleFilePath, RequisiteModules);
});
const PrerequisiteModules &RequisiteModules,
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
return llvm::all_of(
ModuleFilePaths, [&RequisiteModules, VFS](auto ModuleFilePath) {
return IsModuleFileUpToDate(ModuleFilePath, RequisiteModules, VFS);
});
}

// StandalonePrerequisiteModules - stands for PrerequisiteModules for which all
Expand Down Expand Up @@ -347,7 +366,7 @@ bool StandalonePrerequisiteModules::canReuse(
SmallVector<StringRef> BMIPaths;
for (auto &MF : RequiredModules)
BMIPaths.push_back(MF.ModuleFilePath);
return IsModuleFilesUpToDate(BMIPaths, *this);
return IsModuleFilesUpToDate(BMIPaths, *this, VFS);
}

} // namespace clangd
Expand Down
58 changes: 28 additions & 30 deletions clang-tools-extra/clangd/index/SymbolCollector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,10 @@ class SymbolCollector::HeaderFileURICache {
}

struct FrameworkHeaderPath {
// Path to the framework directory containing the Headers/PrivateHeaders
// directories e.g. /Frameworks/Foundation.framework/
llvm::StringRef HeadersParentDir;
// Path to the frameworks directory containing the .framework directory.
llvm::StringRef FrameworkParentDir;
// Name of the framework.
llvm::StringRef FrameworkName;
// Subpath relative to the Headers or PrivateHeaders dir, e.g. NSObject.h
// Note: This is NOT relative to the `HeadersParentDir`.
llvm::StringRef HeaderSubpath;
Expand All @@ -351,19 +352,17 @@ class SymbolCollector::HeaderFileURICache {
path::reverse_iterator I = path::rbegin(Path);
path::reverse_iterator Prev = I;
path::reverse_iterator E = path::rend(Path);
FrameworkHeaderPath HeaderPath;
while (I != E) {
if (*I == "Headers") {
FrameworkHeaderPath HeaderPath;
HeaderPath.HeadersParentDir = Path.substr(0, I - E);
if (*I == "Headers" || *I == "PrivateHeaders") {
HeaderPath.HeaderSubpath = Path.substr(Prev - E);
HeaderPath.IsPrivateHeader = false;
return HeaderPath;
}
if (*I == "PrivateHeaders") {
FrameworkHeaderPath HeaderPath;
HeaderPath.HeadersParentDir = Path.substr(0, I - E);
HeaderPath.HeaderSubpath = Path.substr(Prev - E);
HeaderPath.IsPrivateHeader = true;
HeaderPath.IsPrivateHeader = *I == "PrivateHeaders";
if (++I == E)
break;
HeaderPath.FrameworkName = *I;
if (!HeaderPath.FrameworkName.consume_back(".framework"))
break;
HeaderPath.FrameworkParentDir = Path.substr(0, I - E);
return HeaderPath;
}
Prev = I;
Expand All @@ -379,26 +378,27 @@ class SymbolCollector::HeaderFileURICache {
// <Foundation/NSObject_Private.h> which should be used instead of directly
// importing the header.
std::optional<std::string>
getFrameworkUmbrellaSpelling(llvm::StringRef Framework,
const HeaderSearch &HS,
getFrameworkUmbrellaSpelling(const HeaderSearch &HS,
FrameworkHeaderPath &HeaderPath) {
StringRef Framework = HeaderPath.FrameworkName;
auto Res = CacheFrameworkToUmbrellaHeaderSpelling.try_emplace(Framework);
auto *CachedSpelling = &Res.first->second;
if (!Res.second) {
return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
: CachedSpelling->PublicHeader;
}
SmallString<256> UmbrellaPath(HeaderPath.HeadersParentDir);
llvm::sys::path::append(UmbrellaPath, "Headers", Framework + ".h");
SmallString<256> UmbrellaPath(HeaderPath.FrameworkParentDir);
llvm::sys::path::append(UmbrellaPath, Framework + ".framework", "Headers",
Framework + ".h");

llvm::vfs::Status Status;
auto StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
if (!StatErr)
CachedSpelling->PublicHeader = llvm::formatv("<{0}/{0}.h>", Framework);

UmbrellaPath = HeaderPath.HeadersParentDir;
llvm::sys::path::append(UmbrellaPath, "PrivateHeaders",
Framework + "_Private.h");
UmbrellaPath = HeaderPath.FrameworkParentDir;
llvm::sys::path::append(UmbrellaPath, Framework + ".framework",
"PrivateHeaders", Framework + "_Private.h");

StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
if (!StatErr)
Expand All @@ -414,8 +414,7 @@ class SymbolCollector::HeaderFileURICache {
// give <Foundation/Foundation.h> if the umbrella header exists, otherwise
// <Foundation/NSObject.h>.
std::optional<llvm::StringRef>
getFrameworkHeaderIncludeSpelling(FileEntryRef FE, llvm::StringRef Framework,
HeaderSearch &HS) {
getFrameworkHeaderIncludeSpelling(FileEntryRef FE, HeaderSearch &HS) {
auto Res = CachePathToFrameworkSpelling.try_emplace(FE.getName());
auto *CachedHeaderSpelling = &Res.first->second;
if (!Res.second)
Expand All @@ -429,13 +428,15 @@ class SymbolCollector::HeaderFileURICache {
return std::nullopt;
}
if (auto UmbrellaSpelling =
getFrameworkUmbrellaSpelling(Framework, HS, *HeaderPath)) {
getFrameworkUmbrellaSpelling(HS, *HeaderPath)) {
*CachedHeaderSpelling = *UmbrellaSpelling;
return llvm::StringRef(*CachedHeaderSpelling);
}

*CachedHeaderSpelling =
llvm::formatv("<{0}/{1}>", Framework, HeaderPath->HeaderSubpath).str();
llvm::formatv("<{0}/{1}>", HeaderPath->FrameworkName,
HeaderPath->HeaderSubpath)
.str();
return llvm::StringRef(*CachedHeaderSpelling);
}

Expand All @@ -454,11 +455,8 @@ class SymbolCollector::HeaderFileURICache {
// Framework headers are spelled as <FrameworkName/Foo.h>, not
// "path/FrameworkName.framework/Headers/Foo.h".
auto &HS = PP->getHeaderSearchInfo();
if (const auto *HFI = HS.getExistingFileInfo(*FE))
if (!HFI->Framework.empty())
if (auto Spelling =
getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS))
return *Spelling;
if (auto Spelling = getFrameworkHeaderIncludeSpelling(*FE, HS))
return *Spelling;

if (!tooling::isSelfContainedHeader(*FE, PP->getSourceManager(),
PP->getHeaderSearchInfo())) {
Expand Down
21 changes: 19 additions & 2 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@ New checks
Warns about code that tries to cast between pointers by means of
``std::bit_cast`` or ``memcpy``.

- New :doc:`bugprone-nondeterministic-pointer-iteration-order
<clang-tidy/checks/bugprone/nondeterministic-pointer-iteration-order>`
check.

Finds nondeterministic usages of pointers in unordered containers.

- New :doc:`bugprone-tagged-union-member-count
<clang-tidy/checks/bugprone/tagged-union-member-count>` check.

Expand Down Expand Up @@ -157,6 +163,11 @@ Changes in existing checks
<clang-tidy/checks/bugprone/posix-return>` check to support integer literals
as LHS and posix call as RHS of comparison.

- Improved :doc:`bugprone-return-const-ref-from-parameter
<clang-tidy/checks/bugprone/return-const-ref-from-parameter>` check to
diagnose potential dangling references when returning a ``const &`` parameter
by using the conditional operator ``cond ? var1 : var2``.

- Improved :doc:`bugprone-sizeof-expression
<clang-tidy/checks/bugprone/sizeof-expression>` check to find suspicious
usages of ``sizeof()``, ``alignof()``, and ``offsetof()`` when adding or
Expand Down Expand Up @@ -210,6 +221,10 @@ Changes in existing checks
a false positive when only an implicit conversion happened inside an
initializer list.

- Improved :doc:`modernize-use-designated-initializers
<clang-tidy/checks/modernize/use-designated-initializers>` check to fix a
crash when a class is declared but not defined.

- Improved :doc:`modernize-use-nullptr
<clang-tidy/checks/modernize/use-nullptr>` check to also recognize
``NULL``/``__null`` (but not ``0``) when used with a templated type.
Expand Down Expand Up @@ -243,13 +258,15 @@ Changes in existing checks

- Improved :doc:`readability-enum-initial-value
<clang-tidy/checks/readability/enum-initial-value>` check by only issuing
diagnostics for the definition of an ``enum``, and by fixing a typo in the
diagnostics for the definition of an ``enum``, by not emitting a redundant
file path for anonymous enums in the diagnostic, and by fixing a typo in the
diagnostic.

- Improved :doc:`readability-implicit-bool-conversion
<clang-tidy/checks/readability/implicit-bool-conversion>` check
by adding the option `UseUpperCaseLiteralSuffix` to select the
case of the literal suffix in fixes.
case of the literal suffix in fixes and fixing false positive for implicit
conversion of comparison result in C23.

- Improved :doc:`readability-redundant-smartptr-get
<clang-tidy/checks/readability/redundant-smartptr-get>` check to
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
.. title:: clang-tidy - bugprone-nondeterministic-pointer-iteration-order

bugprone-nondeterministic-pointer-iteration-order
=================================================

Finds nondeterministic usages of pointers in unordered containers.

One canonical example is iteration across a container of pointers.

.. code-block:: c++

{
int a = 1, b = 2;
std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
for (auto i : UnorderedPtrSet)
f(i);
}
Another such example is sorting a container of pointers.

.. code-block:: c++

{
int a = 1, b = 2;
std::vector<int *> VectorOfPtr = {&a, &b};
std::sort(VectorOfPtr.begin(), VectorOfPtr.end());
}
Iteration of a containers of pointers may present the order of different
pointers differently across different runs of a program. In some cases this
may be acceptable behavior, in others this may be unexpected behavior. This
check is advisory for this reason.

This check only detects range-based for loops over unordered sets and maps. It
also detects calls sorting-like algorithms on containers holding pointers.
Other similar usages will not be found and are false negatives.

Limitations:

* This check currently does not check if a nondeterministic iteration order is
likely to be a mistake, and instead marks all such iterations as bugprone.
* std::reference_wrapper is not considered yet.
* Only for loops are considered, other iterators can be included in
improvements.
1 change: 1 addition & 0 deletions clang-tools-extra/docs/clang-tidy/checks/list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Clang-Tidy Checks
:doc:`bugprone-multiple-new-in-one-expression <bugprone/multiple-new-in-one-expression>`,
:doc:`bugprone-multiple-statement-macro <bugprone/multiple-statement-macro>`,
:doc:`bugprone-no-escape <bugprone/no-escape>`,
:doc:`bugprone-nondeterministic-pointer-iteration-order <bugprone/nondeterministic-pointer-iteration-order>`,
:doc:`bugprone-non-zero-enum-to-bool-conversion <bugprone/non-zero-enum-to-bool-conversion>`,
:doc:`bugprone-not-null-terminated-result <bugprone/not-null-terminated-result>`, "Yes"
:doc:`bugprone-optional-value-conversion <bugprone/optional-value-conversion>`, "Yes"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef _SIM_ALGORITHM
#define _SIM_ALGORITHM

#pragma clang system_header

namespace std {

template<class ForwardIt>
bool is_sorted(ForwardIt first, ForwardIt last);

template <class RandomIt>
void nth_element(RandomIt first, RandomIt nth, RandomIt last);

template<class RandomIt>
void partial_sort(RandomIt first, RandomIt middle, RandomIt last);

template<class RandomIt>
void sort (RandomIt first, RandomIt last);

template<class RandomIt>
void stable_sort(RandomIt first, RandomIt last);

template<class BidirIt, class UnaryPredicate>
BidirIt partition(BidirIt first, BidirIt last, UnaryPredicate p);

template<class BidirIt, class UnaryPredicate>
BidirIt stable_partition(BidirIt first, BidirIt last, UnaryPredicate p);

} // namespace std

#endif // _SIM_ALGORITHM
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifndef _SIM_CPP_CONFIG_H
#define _SIM_CPP_CONFIG_H

#pragma clang system_header

typedef unsigned char uint8_t;

typedef __typeof__(sizeof(int)) size_t;
typedef __typeof__((char*)0-(char*)0) ptrdiff_t;

#endif // _SIM_CPP_CONFIG_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef _INITIALIZER_LIST
#define _INITIALIZER_LIST

#pragma clang system_header
#
#include "sim_c++config.h" // size_t

namespace std {

template <class _E>
class initializer_list {
const _E* __begin_;
size_t __size_;

initializer_list(const _E* __b, size_t __s)
: __begin_(__b),
__size_(__s)
{}

public:
typedef _E value_type;
typedef const _E& reference;
typedef const _E& const_reference;
typedef size_t size_type;

typedef const _E* iterator;
typedef const _E* const_iterator;

initializer_list() : __begin_(0), __size_(0) {}

size_t size() const {return __size_;}
const _E* begin() const {return __begin_;}
const _E* end() const {return __begin_ + __size_;}

}; // class initializer_list

} // namespace std

#endif // _INITIALIZER_LIST
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef _SIM_ITERATOR_BASE
#define _SIM_ITERATOR_BASE

namespace std {

struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag : public input_iterator_tag { };
struct bidirectional_iterator_tag : public forward_iterator_tag { };
struct random_access_iterator_tag : public bidirectional_iterator_tag { };

template <typename Iterator> struct iterator_traits {
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::iterator_category iterator_category;
};

} // namespace std

#endif // _SIM_ITERATOR_BASE
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

#ifndef _SIM_MAP
#define _SIM_MAP

#pragma clang system_header
#include "sim_stl_pair"

namespace std {

template <typename Key, typename Value>
class map {
public:
using value_type = pair<Key, Value>;
map();
map(initializer_list<pair<Key, Value>> initList);
value_type& operator[](const Key& key);
value_type& operator[](Key&& key);
class iterator {
public:
iterator(Key *key): ptr(key) {}
iterator& operator++() { ++ptr; return *this; }
bool operator!=(const iterator &other) const { return ptr != other.ptr; }
const Key &operator*() const { return *ptr; }
private:
Key *ptr;
};
Key *val;
iterator begin() const { return iterator(val); }
iterator end() const { return iterator(val + 1); }
};

} // namespace std

#endif // _SIM_MAP
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

#ifndef _SIM_SET
#define _SIM_SET

#pragma clang system_header
#include "sim_initializer_list"

namespace std {

template< class T = void >
struct less;

template< class T >
struct allocator;

template< class Key >
struct hash;

template<
class Key,
class Compare = std::less<Key>,
class Alloc = std::allocator<Key>
> class set {
public:
set(initializer_list<Key> __list) {}

class iterator {
public:
iterator(Key *key): ptr(key) {}
iterator& operator++() { ++ptr; return *this; }
bool operator!=(const iterator &other) const { return ptr != other.ptr; }
const Key &operator*() const { return *ptr; }
private:
Key *ptr;
};

Key *val;
iterator begin() const { return iterator(val); }
iterator end() const { return iterator(val + 1); }
};

} // namespace std

#endif // _SIM_SET
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef _SIM_STL_PAIR
#define _SIM_STL_PAIR

#pragma clang system_header

#include "sim_type_traits"

namespace std {

template <class T1, class T2>
struct pair {
T1 first;
T2 second;

pair() : first(), second() {}
pair(const T1 &a, const T2 &b) : first(a), second(b) {}

template<class U1, class U2>
pair(const pair<U1, U2> &other) : first(other.first),
second(other.second) {}
};

template <typename T1, typename T2>
pair<typename remove_reference<T1>::type, typename remove_reference<T2>::type>
make_pair(T1 &&, T2 &&) {
return {};
};

} // namespace std

#endif // _SIM_STL_PAIR

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

#ifndef _SIM_TYPE_TRAITS
#define _SIM_TYPE_TRAITS

#pragma clang system_header
namespace std {

template< class T > struct remove_reference {typedef T type;};
template< class T > struct remove_reference<T&> {typedef T type;};
template< class T > struct remove_reference<T&&> {typedef T type;};

template<typename T> typename remove_reference<T>::type&& move(T&& a);

template< class T >
using remove_reference_t = typename remove_reference<T>::type;

} // namespace std

#endif // _SIM_TYPE_TRAITS
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#ifndef _SIM_UNORDERED_MAP
#define _SIM_UNORDERED_MAP

#pragma clang system_header
#include "sim_initializer_list"

namespace std {

template <typename Key, typename Value>
class unordered_map {
public:
using value_type = pair<Key, Value>;
unordered_map();
unordered_map(initializer_list<pair<Key, Value>> initList);
value_type& operator[](const Key& key);
value_type& operator[](Key&& key);
class iterator {
public:
iterator(Key *key): ptr(key) {}
iterator& operator++() { ++ptr; return *this; }
bool operator!=(const iterator &other) const { return ptr != other.ptr; }
const Key &operator*() const { return *ptr; }
private:
Key *ptr;
};
Key *val;
iterator begin() const { return iterator(val); }
iterator end() const { return iterator(val + 1); }
};

} // namespace std

#endif // _SIM_UNORDERED_MAP
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef _SIM_UNORDERED_SET
#define _SIM_UNORDERED_SET

#pragma clang system_header
#include "sim_initializer_list"

namespace std {

template<
class Key,
class Hash = std::hash<Key>,
class Compare = std::less<Key>,
class Alloc = std::allocator<Key>
> class unordered_set {
public:
unordered_set(initializer_list<Key> __list) {}

class iterator {
public:
iterator(Key *key): ptr(key) {}
iterator& operator++() { ++ptr; return *this; }
bool operator!=(const iterator &other) const { return ptr != other.ptr; }
const Key &operator*() const { return *ptr; }
private:
Key *ptr;
};

Key *val;
iterator begin() const { return iterator(val); }
iterator end() const { return iterator(val + 1); }
};

} // namespace std

#endif // _SIM_UNORDERED_SET
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#ifndef _SIM_VECTOR
#define _SIM_VECTOR

#pragma clang system_header

#include "sim_iterator_base"

namespace std {

template <typename T, typename Ptr, typename Ref> struct __vector_iterator {
typedef __vector_iterator<T, T *, T &> iterator;
typedef __vector_iterator<T, const T *, const T &> const_iterator;

typedef ptrdiff_t difference_type;
typedef T value_type;
typedef Ptr pointer;
typedef Ref reference;
typedef std::random_access_iterator_tag iterator_category;

__vector_iterator(const Ptr p = 0) : ptr(p) {}
__vector_iterator(const iterator &rhs): ptr(rhs.base()) {}
__vector_iterator<T, Ptr, Ref>& operator++() { ++ ptr; return *this; }
__vector_iterator<T, Ptr, Ref> operator++(int) {
auto tmp = *this;
++ ptr;
return tmp;
}
__vector_iterator<T, Ptr, Ref> operator--() { -- ptr; return *this; }
__vector_iterator<T, Ptr, Ref> operator--(int) {
auto tmp = *this; -- ptr;
return tmp;
}
__vector_iterator<T, Ptr, Ref> operator+(difference_type n) {
return ptr + n;
}
friend __vector_iterator<T, Ptr, Ref> operator+(
difference_type n,
const __vector_iterator<T, Ptr, Ref> &iter) {
return n + iter.ptr;
}
__vector_iterator<T, Ptr, Ref> operator-(difference_type n) {
return ptr - n;
}
__vector_iterator<T, Ptr, Ref> operator+=(difference_type n) {
return ptr += n;
}
__vector_iterator<T, Ptr, Ref> operator-=(difference_type n) {
return ptr -= n;
}

template<typename U, typename Ptr2, typename Ref2>
difference_type operator-(const __vector_iterator<U, Ptr2, Ref2> &rhs);

Ref operator*() const { return *ptr; }
Ptr operator->() const { return ptr; }

Ref operator[](difference_type n) {
return *(ptr+n);
}

bool operator==(const iterator &rhs) const { return ptr == rhs.ptr; }
bool operator==(const const_iterator &rhs) const { return ptr == rhs.ptr; }

bool operator!=(const iterator &rhs) const { return ptr != rhs.ptr; }
bool operator!=(const const_iterator &rhs) const { return ptr != rhs.ptr; }

const Ptr& base() const { return ptr; }

private:
Ptr ptr;
};

template<typename T>
class vector {
T *_start;
T *_finish;
T *_end_of_storage;

public:
typedef T value_type;
typedef size_t size_type;
typedef __vector_iterator<T, T *, T &> iterator;
typedef __vector_iterator<T, const T *, const T &> const_iterator;

vector() : _start(0), _finish(0), _end_of_storage(0) {}
template <typename InputIterator>
vector(InputIterator first, InputIterator last);
vector(const vector &other);
vector(vector &&other);
~vector();

size_t size() const {
return size_t(_finish - _start);
}

vector& operator=(const vector &other);
vector& operator=(vector &&other);
vector& operator=(std::initializer_list<T> ilist);

void assign(size_type count, const T &value);
template <typename InputIterator >
void assign(InputIterator first, InputIterator last);
void assign(std::initializer_list<T> ilist);

void clear();

void push_back(const T &value);
void push_back(T &&value);
template<class... Args>
void emplace_back(Args&&... args);
void pop_back();

iterator insert(const_iterator position, const value_type &val);
iterator insert(const_iterator position, size_type n,
const value_type &val);
template <typename InputIterator>
iterator insert(const_iterator position, InputIterator first,
InputIterator last);
iterator insert(const_iterator position, value_type &&val);
iterator insert(const_iterator position, initializer_list<value_type> il);

template <class... Args>
iterator emplace(const_iterator position, Args&&... args);

iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);

T &operator[](size_t n) {
return _start[n];
}

const T &operator[](size_t n) const {
return _start[n];
}

iterator begin() { return iterator(_start); }
const_iterator begin() const { return const_iterator(_start); }
const_iterator cbegin() const { return const_iterator(_start); }
iterator end() { return iterator(_finish); }
const_iterator end() const { return const_iterator(_finish); }
const_iterator cend() const { return const_iterator(_finish); }
T& front() { return *begin(); }
const T& front() const { return *begin(); }
T& back() { return *(end() - 1); }
const T& back() const { return *(end() - 1); }
};

} // namespace std

#endif // _SIM_VECTOR
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// RUN: %check_clang_tidy %s bugprone-nondeterministic-pointer-iteration-order %t -- -- -I%S -std=c++!4

#include "Inputs/system-header-simulator/sim_set"
#include "Inputs/system-header-simulator/sim_unordered_set"
#include "Inputs/system-header-simulator/sim_map"
#include "Inputs/system-header-simulator/sim_unordered_map"
#include "Inputs/system-header-simulator/sim_vector"
#include "Inputs/system-header-simulator/sim_algorithm"

template<class T>
void f(T x);

void PointerIteration() {
int a = 1, b = 2;
std::set<int> OrderedIntSet = {a, b};
std::set<int *> OrderedPtrSet = {&a, &b};
std::unordered_set<int> UnorderedIntSet = {a, b};
std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
std::map<int, int> IntMap = { std::make_pair(a,a), std::make_pair(b,b) };
std::map<int*, int*> PtrMap = { std::make_pair(&a,&a), std::make_pair(&b,&b) };
std::unordered_map<int, int> IntUnorderedMap = { std::make_pair(a,a), std::make_pair(b,b) };
std::unordered_map<int*, int*> PtrUnorderedMap = { std::make_pair(&a,&a), std::make_pair(&b,&b) };

for (auto i : OrderedIntSet) // no-warning
f(i);

for (auto i : OrderedPtrSet) // no-warning
f(i);

for (auto i : UnorderedIntSet) // no-warning
f(i);

for (auto i : UnorderedPtrSet)
f(i);
// CHECK-MESSAGES: :[[@LINE-2]]:17: warning: iteration of pointers is nondeterministic

for (auto &i : UnorderedPtrSet)
f(i);
// CHECK-MESSAGES: :[[@LINE-2]]:18: warning: iteration of pointers is nondeterministic

for (auto &i : IntMap) // no-warning
f(i);

for (auto &i : PtrMap) // no-warning
f(i);

for (auto &i : IntUnorderedMap) // no-warning
f(i);

for (auto &i : PtrUnorderedMap)
f(i);
// CHECK-MESSAGES: :[[@LINE-2]]:18: warning: iteration of pointers is nondeterministic
}

bool g (int *x) { return true; }
bool h (int x) { return true; }

void PointerSorting() {
int a = 1, b = 2, c = 3;
std::vector<int> V1 = {a, b};
std::vector<int *> V2 = {&a, &b};

std::is_sorted(V1.begin(), V1.end()); // no-warning
std::nth_element(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
std::partial_sort(V1.begin(), V1.begin() + 1, V1.end()); // no-warning
std::sort(V1.begin(), V1.end()); // no-warning
std::stable_sort(V1.begin(), V1.end()); // no-warning
std::partition(V1.begin(), V1.end(), h); // no-warning
std::stable_partition(V1.begin(), V1.end(), h); // no-warning
std::is_sorted(V2.begin(), V2.end());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
std::nth_element(V2.begin(), V2.begin() + 1, V2.end());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
std::partial_sort(V2.begin(), V2.begin() + 1, V2.end());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
std::sort(V2.begin(), V2.end());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
std::stable_sort(V2.begin(), V2.end());
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
std::partition(V2.begin(), V2.end(), g);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
std::stable_partition(V2.begin(), V2.end(), g);
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: sorting pointers is nondeterministic
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ int const &f3(TConstRef a) { return a; }
int const &f4(TConst &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter

int const &f5(TConst &a) { return true ? a : a; }
// CHECK-MESSAGES: :[[@LINE-1]]:42: warning: returning a constant reference parameter
// CHECK-MESSAGES: :[[@LINE-2]]:46: warning: returning a constant reference parameter

template <typename T>
const T& tf1(const T &a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: returning a constant reference parameter
Expand All @@ -47,6 +51,11 @@ template <typename T>
const T& itf4(typename ConstRef<T>::type a) { return a; }
// CHECK-MESSAGES: :[[@LINE-1]]:54: warning: returning a constant reference parameter

template <typename T>
const T& itf5(const T &a) { return true ? a : a; }
// CHECK-MESSAGES: :[[@LINE-1]]:43: warning: returning a constant reference parameter
// CHECK-MESSAGES: :[[@LINE-2]]:47: warning: returning a constant reference parameter

void instantiate(const int &param, const float &paramf, int &mut_param, float &mut_paramf) {
itf1(0);
itf1(param);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,11 @@ DECLARE_S93;
// CHECK-MESSAGES-MACROS: :[[@LINE-1]]:1: warning: use designated initializer list to initialize 'S9' [modernize-use-designated-initializers]
// CHECK-MESSAGES-MACROS: :[[@LINE-4]]:28: note: expanded from macro 'DECLARE_S93'
// CHECK-MESSAGES-MACROS: :[[@LINE-71]]:1: note: aggregate type is defined here

// Issue #113652.
struct S14;

struct S15{
S15(S14& d):d{d}{}
S14& d;
};
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,17 @@ enum EMacro2 {
// CHECK-FIXES: EMacro2_c = 3,
};


enum {
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum '<unnamed>' are not consistent
// CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum '<unnamed>' are not consistent
EAnonymous_a = 1,
EAnonymous_b,
// CHECK-FIXES: EAnonymous_b = 2,
EAnonymous_c = 3,
};


enum EnumZeroFirstInitialValue {
EnumZeroFirstInitialValue_0 = 0,
// CHECK-MESSAGES-ENABLE: :[[@LINE-1]]:3: warning: zero initial value for the first enumerator in 'EnumZeroFirstInitialValue' can be disregarded
Expand Down Expand Up @@ -114,4 +125,3 @@ enum WithFwdDeclSequential : int {
EFS2 = 4,
// CHECK-FIXES-ENABLE: EFS2 ,
};

Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,15 @@ void implicitConversionToBoolFromUnaryMinusAndZeroLiterals() {
// CHECK-FIXES: functionTakingBool((-0.0) != 0.0);
}

void ignoreImplicitCastToBoolForComparisonResult() {
bool boolFromComparison0 = 1 != 0;
bool boolFromComparison1 = 1 == 0;
bool boolFromComparison2 = 1 > 0;
bool boolFromComparison3 = 1 >= 0;
bool boolFromComparison4 = 1 < 0;
bool boolFromComparison5 = 1 <= 0;
}

void ignoreExplicitCastsToBool() {
int integer = 10;
bool boolComingFromInt = (bool)integer;
Expand Down
47 changes: 46 additions & 1 deletion clang/Maintainers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ AST matchers
| aaron\@aaronballman.com (email), aaron.ballman (Phabricator), AaronBallman (GitHub), AaronBallman (Discourse), aaronballman (Discord), AaronBallman (IRC)

AST Visitors
~~~~~~~~~~~~
| Sirraide
| aeternalmail\@gmail.com (email), Sirraide (GitHub), Ætérnal (Discord), Sirraide (Discourse)

Clang LLVM IR generation
~~~~~~~~~~~~~~~~~~~~~~~~
| John McCall
Expand All @@ -57,10 +63,16 @@ Analysis & CFG
| sgatev\@google.com (email), sgatev (Phabricator), sgatev (GitHub)

Sema
~~~~
| Sirraide
| aeternalmail\@gmail.com (email), Sirraide (GitHub), Ætérnal (Discord), Sirraide (Discourse)

Experimental new constant interpreter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| Timm Bäder
| tbaeder\@redhat.com (em), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord)
| tbaeder\@redhat.com (email), tbaeder (Phabricator), tbaederr (GitHub), tbaeder (Discourse), tbaeder (Discord)

Modules & serialization
Expand All @@ -71,13 +83,22 @@ Modules & serialization
| Michael Spencer
| bigcheesegs\@gmail.com (email), Bigcheese (Phabricator), Bigcheese (GitHub)
| Vassil Vassilev
| Vassil.Vassilev\@cern.ch (email), v.g.vassilev (Phabricator), vgvassilev (GitHub)

Templates
~~~~~~~~~
| Erich Keane
| ekeane\@nvidia.com (email), ErichKeane (Phabricator), erichkeane (GitHub)

Lambdas
~~~~~~~
| Corentin Jabot
| corentin.jabot\@gmail.com (email), cor3ntin (Phabricator), cor3ntin (GitHub)

Debug information
~~~~~~~~~~~~~~~~~
| Adrian Prantl
Expand Down Expand Up @@ -172,6 +193,12 @@ Attributes
| ekeane\@nvidia.com (email), ErichKeane (Phabricator), erichkeane (GitHub)

Plugins
~~~~~~~
| Vassil Vassilev
| Vassil.Vassilev\@cern.ch (email), v.g.vassilev (Phabricator), vgvassilev (GitHub)

Inline assembly
~~~~~~~~~~~~~~~
| Eric Christopher
Expand Down Expand Up @@ -225,6 +252,18 @@ C++ conformance
| Hubert Tong
| hubert.reinterpretcast\@gmail.com (email), hubert.reinterpretcast (Phabricator), hubert-reinterpretcast (GitHub)
| Shafik Yaghmour
| shafik.yaghmour\@intel.com (email), shafik (GitHub), shafik.yaghmour (Discord), shafik (Discourse)
| Vlad Serebrennikov
| serebrennikov.vladislav\@gmail.com (email), Endilll (GitHub), Endill (Discord), Endill (Discourse)

C++ Defect Reports
~~~~~~~~~~~~~~~~~~
| Vlad Serebrennikov
| serebrennikov.vladislav\@gmail.com (email), Endilll (GitHub), Endill (Discord), Endill (Discourse)

Objective-C/C++ conformance
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand All @@ -244,6 +283,12 @@ OpenCL conformance
| anastasia\@compiler-experts.com (email), Anastasia (Phabricator), AnastasiaStulova (GitHub)

OpenACC
~~~~~~~
| Erich Keane
| ekeane\@nvidia.com (email), ErichKeane (Phabricator), erichkeane (GitHub)

SYCL conformance
~~~~~~~~~~~~~~~~
| Alexey Bader
Expand Down
12 changes: 4 additions & 8 deletions clang/bindings/python/tests/cindex/test_access_specifiers.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import AccessSpecifier, Config

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import AccessSpecifier
from clang.cindex import Cursor
from clang.cindex import TranslationUnit

from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu


class TestAccessSpecifiers(unittest.TestCase):
def test_access_specifiers(self):
Expand Down
27 changes: 9 additions & 18 deletions clang/bindings/python/tests/cindex/test_cdb.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import CompilationDatabase, CompilationDatabaseError, Config

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import CompilationDatabase
from clang.cindex import CompilationDatabaseError
from clang.cindex import CompileCommands
from clang.cindex import CompileCommand
import os
import gc
import unittest
import sys
from .util import skip_if_no_fspath
from .util import str_to_path

from pathlib import Path

kInputsDir = os.path.join(os.path.dirname(__file__), "INPUTS")

Expand All @@ -31,7 +25,7 @@ def test_create_fail(self):
with open(os.devnull, "wb") as null:
os.dup2(null.fileno(), 2)
with self.assertRaises(CompilationDatabaseError) as cm:
cdb = CompilationDatabase.fromDirectory(path)
CompilationDatabase.fromDirectory(path)
os.dup2(stderr, 2)
os.close(stderr)

Expand All @@ -40,21 +34,18 @@ def test_create_fail(self):

def test_create(self):
"""Check we can load a compilation database"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
CompilationDatabase.fromDirectory(kInputsDir)

def test_lookup_succeed(self):
"""Check we get some results if the file exists in the db"""
cdb = CompilationDatabase.fromDirectory(kInputsDir)
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
self.assertNotEqual(len(cmds), 0)

@skip_if_no_fspath
def test_lookup_succeed_pathlike(self):
"""Same as test_lookup_succeed, but with PathLikes"""
cdb = CompilationDatabase.fromDirectory(str_to_path(kInputsDir))
cmds = cdb.getCompileCommands(
str_to_path("/home/john.doe/MyProject/project.cpp")
)
cdb = CompilationDatabase.fromDirectory(Path(kInputsDir))
cmds = cdb.getCompileCommands(Path("/home/john.doe/MyProject/project.cpp"))
self.assertNotEqual(len(cmds), 0)

def test_all_compilecommand(self):
Expand Down Expand Up @@ -175,7 +166,7 @@ def test_compilationDB_references(self):
cmds = cdb.getCompileCommands("/home/john.doe/MyProject/project.cpp")
del cdb
gc.collect()
workingdir = cmds[0].directory
cmds[0].directory

def test_compilationCommands_references(self):
"""Ensure CompilationsCommand keeps a reference to CompilationCommands"""
Expand All @@ -185,4 +176,4 @@ def test_compilationCommands_references(self):
cmd0 = cmds[0]
del cmds
gc.collect()
workingdir = cmd0.directory
cmd0.directory
15 changes: 6 additions & 9 deletions clang/bindings/python/tests/cindex/test_code_completion.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TranslationUnit

import unittest
from .util import skip_if_no_fspath
from .util import str_to_path
from pathlib import Path


class TestCodeCompletion(unittest.TestCase):
Expand Down Expand Up @@ -57,11 +55,10 @@ def test_code_complete(self):
]
self.check_completion_results(cr, expected)

@skip_if_no_fspath
def test_code_complete_pathlike(self):
files = [
(
str_to_path("fake.c"),
Path("fake.c"),
"""
/// Aaa.
int test1;
Expand All @@ -77,14 +74,14 @@ def test_code_complete_pathlike(self):
]

tu = TranslationUnit.from_source(
str_to_path("fake.c"),
Path("fake.c"),
["-std=c99"],
unsaved_files=files,
options=TranslationUnit.PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION,
)

cr = tu.codeComplete(
str_to_path("fake.c"),
Path("fake.c"),
9,
1,
unsaved_files=files,
Expand Down
8 changes: 4 additions & 4 deletions clang/bindings/python/tests/cindex/test_comment.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TranslationUnit
from tests.cindex.util import get_cursor

import unittest

from .util import get_cursor


class TestComment(unittest.TestCase):
def test_comment(self):
Expand Down
29 changes: 14 additions & 15 deletions clang/bindings/python/tests/cindex/test_cursor.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import os
from clang.cindex import Config

from clang.cindex import (
AvailabilityKind,
BinaryOperator,
Config,
CursorKind,
StorageClass,
TemplateArgumentKind,
TranslationUnit,
TypeKind,
)

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import ctypes
import gc
import unittest

from clang.cindex import AvailabilityKind
from clang.cindex import CursorKind
from clang.cindex import TemplateArgumentKind
from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from clang.cindex import BinaryOperator
from clang.cindex import StorageClass
from .util import get_cursor
from .util import get_cursors
from .util import get_tu

from .util import get_cursor, get_cursors, get_tu

kInput = """\
struct s0 {
Expand Down Expand Up @@ -170,7 +169,7 @@ def test_references(self):
self.assertIsInstance(cursor.translation_unit, TranslationUnit)

# If the TU was destroyed, this should cause a segfault.
parent = cursor.semantic_parent
cursor.semantic_parent

def test_canonical(self):
source = "struct X; struct X; struct X { int member; };"
Expand Down Expand Up @@ -344,7 +343,7 @@ class Bar {
)

self.assertEqual(len(copy_assignment_operators_cursors), 10)
self.assertTrue(len(non_copy_assignment_operators_cursors), 9)
self.assertEqual(len(non_copy_assignment_operators_cursors), 7)

self.assertTrue(
all(
Expand Down
5 changes: 2 additions & 3 deletions clang/bindings/python/tests/cindex/test_cursor_kind.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import CursorKind

import unittest


Expand Down
7 changes: 3 additions & 4 deletions clang/bindings/python/tests/cindex/test_diagnostics.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import os
from clang.cindex import Config

from clang.cindex import Config, Diagnostic

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import *
from .util import get_tu

import unittest

from .util import get_tu

# FIXME: We need support for invalid translation units to test better.

Expand Down
16 changes: 8 additions & 8 deletions clang/bindings/python/tests/cindex/test_enums.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import unittest

from clang.cindex import (
TokenKind,
AccessSpecifier,
AvailabilityKind,
BinaryOperator,
CursorKind,
TemplateArgumentKind,
ExceptionSpecificationKind,
AvailabilityKind,
AccessSpecifier,
TypeKind,
RefQualifierKind,
LinkageKind,
TLSKind,
RefQualifierKind,
StorageClass,
BinaryOperator,
TemplateArgumentKind,
TLSKind,
TokenKind,
TypeKind,
)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind, ExceptionSpecificationKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import clang.cindex
from clang.cindex import ExceptionSpecificationKind
from .util import get_tu

import unittest

from .util import get_tu


def find_function_declarations(node, declarations=[]):
if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
if node.kind == CursorKind.FUNCTION_DECL:
declarations.append(node)
for child in node.get_children():
declarations = find_function_declarations(child, declarations)
Expand Down
5 changes: 2 additions & 3 deletions clang/bindings/python/tests/cindex/test_file.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
from clang.cindex import Config

from clang.cindex import Config, File, Index

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import Index, File

import unittest


Expand Down
8 changes: 3 additions & 5 deletions clang/bindings/python/tests/cindex/test_index.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import os
from clang.cindex import Config

from clang.cindex import Config, Index, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import *
import os
import unittest


kInputsDir = os.path.join(os.path.dirname(__file__), "INPUTS")


class TestIndex(unittest.TestCase):
def test_create(self):
index = Index.create()
Index.create()

# FIXME: test Index.read

Expand Down
12 changes: 4 additions & 8 deletions clang/bindings/python/tests/cindex/test_linkage.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, LinkageKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import LinkageKind
from clang.cindex import Cursor
from clang.cindex import TranslationUnit

from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu


class TestLinkage(unittest.TestCase):
def test_linkage(self):
Expand Down
19 changes: 10 additions & 9 deletions clang/bindings/python/tests/cindex/test_location.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import os
from clang.cindex import Config

from clang.cindex import (
Config,
Cursor,
File,
SourceLocation,
SourceRange,
TranslationUnit,
)

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import Cursor
from clang.cindex import File
from clang.cindex import SourceLocation
from clang.cindex import SourceRange
from clang.cindex import TranslationUnit
from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu

baseInput = "int one;\nint two;\n"

Expand Down
10 changes: 2 additions & 8 deletions clang/bindings/python/tests/cindex/test_rewrite.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import unittest
import tempfile
import unittest

from clang.cindex import (
Rewriter,
TranslationUnit,
File,
SourceLocation,
SourceRange,
)
from clang.cindex import File, Rewriter, SourceLocation, SourceRange, TranslationUnit


class TestRewrite(unittest.TestCase):
Expand Down
4 changes: 2 additions & 2 deletions clang/bindings/python/tests/cindex/test_source_range.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import os
from clang.cindex import Config

from clang.cindex import Config, SourceLocation, SourceRange, TranslationUnit

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import unittest
from clang.cindex import SourceLocation, SourceRange, TranslationUnit

from .util import get_tu

Expand Down
12 changes: 4 additions & 8 deletions clang/bindings/python/tests/cindex/test_tls_kind.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TLSKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TLSKind
from clang.cindex import Cursor
from clang.cindex import TranslationUnit

from .util import get_cursor
from .util import get_tu

import unittest

from .util import get_cursor, get_tu


class TestTLSKind(unittest.TestCase):
def test_tls_kind(self):
Expand Down
5 changes: 2 additions & 3 deletions clang/bindings/python/tests/cindex/test_token_kind.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import os
from clang.cindex import Config

from clang.cindex import Config, TokenKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import TokenKind

import unittest


Expand Down
11 changes: 3 additions & 8 deletions clang/bindings/python/tests/cindex/test_tokens.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind, SourceLocation, SourceRange, TokenKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from clang.cindex import CursorKind
from clang.cindex import Index
from clang.cindex import SourceLocation
from clang.cindex import SourceRange
from clang.cindex import TokenKind
import unittest

from .util import get_tu

import unittest


class TestTokens(unittest.TestCase):
def test_token_to_cursor(self):
Expand Down
58 changes: 25 additions & 33 deletions clang/bindings/python/tests/cindex/test_translation_unit.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import os
from clang.cindex import Config

from clang.cindex import (
Config,
Cursor,
CursorKind,
File,
Index,
SourceLocation,
SourceRange,
TranslationUnit,
TranslationUnitLoadError,
TranslationUnitSaveError,
)

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

from contextlib import contextmanager
import gc
import os
import sys
import tempfile
import unittest
from contextlib import contextmanager
from pathlib import Path

from clang.cindex import CursorKind
from clang.cindex import Cursor
from clang.cindex import File
from clang.cindex import Index
from clang.cindex import SourceLocation
from clang.cindex import SourceRange
from clang.cindex import TranslationUnitSaveError
from clang.cindex import TranslationUnitLoadError
from clang.cindex import TranslationUnit
from .util import get_cursor
from .util import get_tu
from .util import skip_if_no_fspath
from .util import str_to_path

from .util import get_cursor, get_tu

kInputsDir = os.path.join(os.path.dirname(__file__), "INPUTS")

Expand All @@ -47,7 +45,7 @@ def save_tu_pathlike(tu):
Returns the filename it was saved to.
"""
with tempfile.NamedTemporaryFile() as t:
tu.save(str_to_path(t.name))
tu.save(Path(t.name))
yield t.name


Expand Down Expand Up @@ -105,32 +103,29 @@ def test_unsaved_files(self):
self.assertEqual(spellings[-1], "y")

def test_unsaved_files_2(self):
if sys.version_info.major >= 3:
from io import StringIO
else:
from io import BytesIO as StringIO
from io import StringIO

tu = TranslationUnit.from_source(
"fake.c", unsaved_files=[("fake.c", StringIO("int x;"))]
)
spellings = [c.spelling for c in tu.cursor.get_children()]
self.assertEqual(spellings[-1], "x")

@skip_if_no_fspath
def test_from_source_accepts_pathlike(self):
tu = TranslationUnit.from_source(
str_to_path("fake.c"),
Path("fake.c"),
["-Iincludes"],
unsaved_files=[
(
str_to_path("fake.c"),
Path("fake.c"),
"""
#include "fake.h"
int x;
int SOME_DEFINE;
""",
),
(
str_to_path("includes/fake.h"),
Path("includes/fake.h"),
"""
#define SOME_DEFINE y
""",
Expand Down Expand Up @@ -192,7 +187,6 @@ def test_save(self):
self.assertTrue(os.path.exists(path))
self.assertGreater(os.path.getsize(path), 0)

@skip_if_no_fspath
def test_save_pathlike(self):
"""Ensure TranslationUnit.save() works with PathLike filename."""

Expand Down Expand Up @@ -234,14 +228,13 @@ def test_load(self):
# Just in case there is an open file descriptor somewhere.
del tu2

@skip_if_no_fspath
def test_load_pathlike(self):
"""Ensure TranslationUnits can be constructed from saved files -
PathLike variant."""
tu = get_tu("int foo();")
self.assertEqual(len(tu.diagnostics), 0)
with save_tu(tu) as path:
tu2 = TranslationUnit.from_ast_file(filename=str_to_path(path))
tu2 = TranslationUnit.from_ast_file(filename=Path(path))
self.assertEqual(len(tu2.diagnostics), 0)

foo = get_cursor(tu2, "foo")
Expand All @@ -268,18 +261,17 @@ def test_get_file(self):
with self.assertRaises(Exception):
f = tu.get_file("foobar.cpp")

@skip_if_no_fspath
def test_get_file_pathlike(self):
"""Ensure tu.get_file() works appropriately with PathLike filenames."""

tu = get_tu("int foo();")

f = tu.get_file(str_to_path("t.c"))
f = tu.get_file(Path("t.c"))
self.assertIsInstance(f, File)
self.assertEqual(f.name, "t.c")

with self.assertRaises(Exception):
f = tu.get_file(str_to_path("foobar.cpp"))
f = tu.get_file(Path("foobar.cpp"))

def test_get_source_location(self):
"""Ensure tu.get_source_location() works."""
Expand Down
18 changes: 6 additions & 12 deletions clang/bindings/python/tests/cindex/test_type.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import os
from clang.cindex import Config

from clang.cindex import Config, CursorKind, RefQualifierKind, TranslationUnit, TypeKind

if "CLANG_LIBRARY_PATH" in os.environ:
Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])

import gc
import unittest

from clang.cindex import CursorKind
from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from clang.cindex import RefQualifierKind
from .util import get_cursor
from .util import get_cursors
from .util import get_tu

from .util import get_cursor, get_cursors, get_tu

kInput = """\
Expand Down Expand Up @@ -138,7 +132,7 @@ def test_references(self):
self.assertIsInstance(t.translation_unit, TranslationUnit)

# If the TU was destroyed, this should cause a segfault.
decl = t.get_declaration()
t.get_declaration()

def testConstantArray(self):
tu = get_tu(constarrayInput)
Expand Down Expand Up @@ -459,8 +453,8 @@ def test_offset(self):
(["-target", "i386-pc-win32"], (8, 16, 0, 32, 64, 96)),
(["-target", "msp430-none-none"], (2, 14, 0, 32, 64, 96)),
]
for flags, values in tries:
align, total, f1, bariton, foo, bar = values
for _, values in tries:
_, _, f1, bariton, foo, bar = values
tu = get_tu(source)
teststruct = get_cursor(tu, "Test")
children = list(teststruct.get_children())
Expand Down
20 changes: 1 addition & 19 deletions clang/bindings/python/tests/cindex/util.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
# This file provides common utility functions for the test suite.

import os

HAS_FSPATH = hasattr(os, "fspath")

if HAS_FSPATH:
from pathlib import Path as str_to_path
else:
str_to_path = None

import unittest

from clang.cindex import Cursor
from clang.cindex import TranslationUnit
from clang.cindex import Cursor, TranslationUnit


def get_tu(source, lang="c", all_warnings=False, flags=[]):
Expand Down Expand Up @@ -81,14 +69,8 @@ def get_cursors(source, spelling):
return cursors


skip_if_no_fspath = unittest.skipUnless(
HAS_FSPATH, "Requires file system path protocol / Python 3.6+"
)

__all__ = [
"get_cursor",
"get_cursors",
"get_tu",
"skip_if_no_fspath",
"str_to_path",
]
2 changes: 1 addition & 1 deletion clang/docs/AddressSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Typical slowdown introduced by AddressSanitizer is **2x**.
How to build
============

Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>` and enable
Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_ and enable
the ``compiler-rt`` runtime. An example CMake configuration that will allow
for the use/testing of AddressSanitizer:

Expand Down
5 changes: 0 additions & 5 deletions clang/docs/ClangFormat.rst
Original file line number Diff line number Diff line change
Expand Up @@ -363,8 +363,3 @@ those as well).

These commands use the file paths shown in the diff output
so they will only work from the root of the repository.

Current State of Clang Format for LLVM
======================================

The following table :doc:`ClangFormattedStatus` shows the current status of clang-formatting for the entire LLVM source tree.
8,536 changes: 0 additions & 8,536 deletions clang/docs/ClangFormattedStatus.rst

This file was deleted.

3 changes: 0 additions & 3 deletions clang/docs/ClangLinkerWrapper.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ only for the linker wrapper will be forwarded to the wrapped linker job.
USAGE: clang-linker-wrapper [options] -- <options to passed to the linker>
OPTIONS:
--bitcode-library=<kind>-<triple>-<arch>=<path>
Extra bitcode library to link
--cuda-path=<dir> Set the system CUDA path
--device-debug Use debugging
--device-linker=<value> or <triple>=<value>
Arguments to pass to the device linker invocation
--dry-run Print program arguments without running
--embed-bitcode Embed linked bitcode in the module
--help-hidden Display all available options
--help Display available options (--help-hidden for more)
--host-triple=<triple> Triple to use for the host compilation
Expand Down
82 changes: 82 additions & 0 deletions clang/docs/ClangSYCLLinker.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
=======================
Clang SYCL Linker
=======================

.. contents::
:local:

.. _clang-sycl-linker:

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

This tool works as a wrapper around the SYCL device code linking process.
The purpose of this tool is to provide an interface to link SYCL device bitcode
in LLVM IR format, SYCL device bitcode in SPIR-V IR format, and native binary
objects, and then use the SPIR-V LLVM Translator tool on fully linked device
objects to produce the final output.
After the linking stage, the fully linked device code in LLVM IR format may
undergo several SYCL-specific finalization steps before the SPIR-V code
generation step.
The tool will also support the Ahead-Of-Time (AOT) compilation flow. AOT
compilation is the process of invoking the back-end at compile time to produce
the final binary, as opposed to just-in-time (JIT) compilation when final code
generation is deferred until application runtime.

Device code linking for SYCL offloading has several known quirks that
make it difficult to use in a unified offloading setting. Two of the primary
issues are:
1. Several finalization steps are required to be run on the fully linked LLVM
IR bitcode to guarantee conformance to SYCL standards. This step is unique to
the SYCL offloading compilation flow.
2. The SPIR-V LLVM Translator tool is an external tool and hence SPIR-V IR code
generation cannot be done as part of LTO. This limitation can be lifted once
the SPIR-V backend is available as a viable LLVM backend.

This tool has been proposed to work around these issues.

Usage
=====

This tool can be used with the following options. Several of these options will
be passed down to downstream tools like 'llvm-link', 'llvm-spirv', etc.

.. code-block:: console
OVERVIEW: A utility that wraps around the SYCL device code linking process.
This enables linking and code generation for SPIR-V JIT targets and AOT
targets.
USAGE: clang-sycl-linker [options]
OPTIONS:
--arch <value> Specify the name of the target architecture.
--dry-run Print generated commands without running.
-g Specify that this was a debug compile.
-help-hidden Display all available options
-help Display available options (--help-hidden for more)
--library-path=<dir> Set the library path for SYCL device libraries
--device-libs=<value> A comma separated list of device libraries that are linked during the device link
-o <path> Path to file to write output
--save-temps Save intermediate results
--triple <value> Specify the target triple.
--version Display the version number and exit
-v Print verbose information
-spirv-dump-device-code=<dir> Directory to dump SPIR-V IR code into
-is-windows-msvc-env Specify if we are compiling under windows environment
-llvm-spirv-options=<value> Pass options to llvm-spirv tool
--llvm-spirv-path=<dir> Set the system llvm-spirv path
Example
=======

This tool is intended to be invoked when targeting any of the target offloading
toolchains. When the --sycl-link option is passed to the clang driver, the
driver will invoke the linking job of the target offloading toolchain, which in
turn will invoke this tool. This tool can be used to create one or more fully
linked device images that are ready to be wrapped and linked with host code to
generate the final executable.

.. code-block:: console
clang-sycl-linker --triple spirv64 --arch native input.bc
535 changes: 535 additions & 0 deletions clang/docs/FunctionEffectAnalysis.rst

Large diffs are not rendered by default.

15 changes: 10 additions & 5 deletions clang/docs/RealtimeSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,22 @@ RealtimeSanitizer (a.k.a. RTSan) is a real-time safety testing tool for C and C+
projects. RTSan can be used to detect real-time violations, i.e. calls to methods
that are not safe for use in functions with deterministic run time requirements.
RTSan considers any function marked with the ``[[clang::nonblocking]]`` attribute
to be a real-time function. If RTSan detects a call to ``malloc``, ``free``,
``pthread_mutex_lock``, or anything else that could have a non-deterministic
execution time in a function marked ``[[clang::nonblocking]]``
RTSan raises an error.
to be a real-time function. At run-time, if RTSan detects a call to ``malloc``,
``free``, ``pthread_mutex_lock``, or anything else known to have a
non-deterministic execution time in a function marked ``[[clang::nonblocking]]``
it raises an error.

RTSan performs its analysis at run-time but shares the ``[[clang::nonblocking]]``
attribute with the :doc:`FunctionEffectAnalysis` system, which operates at
compile-time to detect potential real-time safety violations. For comprehensive
detection of real-time safety issues, it is recommended to use both systems together.

The runtime slowdown introduced by RealtimeSanitizer is negligible.

How to build
============

Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>` and enable the
Build LLVM/Clang with `CMake <https://llvm.org/docs/CMake.html>`_ and enable the
``compiler-rt`` runtime. An example CMake configuration that will allow for the
use/testing of RealtimeSanitizer:

Expand Down
48 changes: 45 additions & 3 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ code bases.

- The ``clang-rename`` tool has been removed.

- Removed support for RenderScript targets. This technology is
`officially deprecated <https://developer.android.com/guide/topics/renderscript/compute>`_
and users are encouraged to
`migrate to Vulkan <https://developer.android.com/guide/topics/renderscript/migrate>`_
or other options.

C/C++ Language Potentially Breaking Changes
-------------------------------------------

Expand Down Expand Up @@ -134,7 +140,7 @@ C++ Specific Potentially Breaking Changes
unsigned operator""_udl_name(unsigned long long);

- Clang will now produce an error diagnostic when [[clang::lifetimebound]] is
applied on a parameter of a function that returns void. This was previously
applied on a parameter of a function that returns void. This was previously
ignored and had no effect. (#GH107556)

.. code-block:: c++
Expand Down Expand Up @@ -316,6 +322,11 @@ Modified Compiler Flags
to utilize these vector libraries. The behavior for all other vector function
libraries remains unchanged.

- The ``-Wnontrivial-memaccess`` warning has been updated to also warn about
passing non-trivially-copyable destrination parameter to ``memcpy``,
``memset`` and similar functions for which it is a documented undefined
behavior.

Removed Compiler Flags
-------------------------

Expand All @@ -327,6 +338,19 @@ Removed Compiler Flags
Attribute Changes in Clang
--------------------------

- The ``swift_attr`` can now be applied to types. To make it possible to use imported APIs
in Swift safely there has to be a way to annotate individual parameters and result types
with relevant attributes that indicate that e.g. a block is called on a particular actor
or it accepts a Sendable or global-actor (i.e. ``@MainActor``) isolated parameter.

For example:

.. code-block:: objc
@interface MyService
-(void) handle: (void (^ __attribute__((swift_attr("@Sendable"))))(id)) handler;
@end
- Clang now disallows more than one ``__attribute__((ownership_returns(class, idx)))`` with
different class names attached to one function.

Expand Down Expand Up @@ -458,7 +482,8 @@ Bug Fixes in This Version
- Fixed a crash using ``__array_rank`` on 64-bit targets. (#GH113044).
- The warning emitted for an unsupported register variable type now points to
the unsupported type instead of the ``register`` keyword (#GH109776).
- Fixed a crash when emit ctor for global variant with flexible array init (#GH113187).
- Fixed a crash when emit ctor for global variant with flexible array init (#GH113187).
- Fixed a crash when GNU statement expression contains invalid statement (#GH113468).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -560,7 +585,11 @@ Bug Fixes to C++ Support
- Clang incorrectly considered a class with an anonymous union member to not be
const-default-constructible even if a union member has a default member initializer.
(#GH95854).
- Fixed an assertion failure when evaluating an invalid expression in an array initializer (#GH112140)
- Fixed an assertion failure when evaluating an invalid expression in an array initializer. (#GH112140)
- Fixed an assertion failure in range calculations for conditional throw expressions. (#GH111854)
- Clang now correctly ignores previous partial specializations of member templates explicitly specialized for
an implicitly instantiated class template specialization. (#GH51051)
- Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -628,6 +657,10 @@ X86 Support
* Supported MINMAX intrinsics of ``*_(mask(z)))_minmax(ne)_p[s|d|h|bh]`` and
``*_(mask(z)))_minmax_s[s|d|h]``.

- Supported intrinsics for ``SM4 and AVX10.2``.
* Supported SM4 intrinsics of ``_mm512_sm4key4_epi32`` and
``_mm512_sm4rnds4_epi32``.

- All intrinsics in adcintrin.h can now be used in constant expressions.

- All intrinsics in adxintrin.h can now be used in constant expressions.
Expand All @@ -642,6 +675,7 @@ X86 Support

- Supported intrinsics for ``MOVRS AND AVX10.2``.
* Supported intrinsics of ``_mm(256|512)_(mask(z))_loadrs_epi(8|16|32|64)``.
- Support ISA of ``AMX-FP8``.

Arm and AArch64 Support
^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -726,6 +760,8 @@ AST Matchers

- Fixed a crash when traverse lambda expr with invalid captures. (#GH106444)

- Fixed ``isInstantiated`` and ``isInTemplateInstantiation`` to also match for variable templates. (#GH110666)

- Ensure ``hasName`` matches template specializations across inline namespaces,
making `matchesNodeFullSlow` and `matchesNodeFullFast` consistent.

Expand Down Expand Up @@ -782,6 +818,12 @@ Moved checkers
To detect too large arguments passed to malloc, consider using the checker
``alpha.taint.TaintedAlloc``.

- The checkers ``alpha.nondeterministic.PointerSorting`` and
``alpha.nondeterministic.PointerIteration`` were moved to a new bugprone
checker named ``bugprone-nondeterministic-pointer-iteration-order``. The
original checkers were implemented only using AST matching and make more
sense as a single clang-tidy check.

.. _release-notes-sanitizers:

Sanitizers
Expand Down
31 changes: 0 additions & 31 deletions clang/docs/analyzer/checkers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3447,37 +3447,6 @@ Limitations:
More details at the corresponding `GitHub issue <https://github.com/llvm/llvm-project/issues/43459>`_.
.. _alpha-nondeterminism-PointerIteration:
alpha.nondeterminism.PointerIteration (C++)
"""""""""""""""""""""""""""""""""""""""""""
Check for non-determinism caused by iterating unordered containers of pointers.
.. code-block:: c
void test() {
int a = 1, b = 2;
std::unordered_set<int *> UnorderedPtrSet = {&a, &b};
for (auto i : UnorderedPtrSet) // warn
f(i);
}
.. _alpha-nondeterminism-PointerSorting:
alpha.nondeterminism.PointerSorting (C++)
"""""""""""""""""""""""""""""""""""""""""
Check for non-determinism caused by sorting of pointers.
.. code-block:: c
void test() {
int a = 1, b = 2;
std::vector<int *> V = {&a, &b};
std::sort(V.begin(), V.end()); // warn
}
alpha.WebKit
^^^^^^^^^^^^
Expand Down
3 changes: 2 additions & 1 deletion clang/docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Using Clang as a Compiler
ThreadSafetyAnalysis
SafeBuffers
DataFlowAnalysisIntro
FunctionEffectAnalysis
AddressSanitizer
ThreadSanitizer
MemorySanitizer
Expand Down Expand Up @@ -92,12 +93,12 @@ Using Clang Tools
ClangCheck
ClangFormat
ClangFormatStyleOptions
ClangFormattedStatus
ClangLinkerWrapper
ClangNVLinkWrapper
ClangOffloadBundler
ClangOffloadPackager
ClangRepl
ClangSYCLLinker

Design Documents
================
Expand Down
8,827 changes: 0 additions & 8,827 deletions clang/docs/tools/clang-formatted-files.txt

This file was deleted.

19 changes: 10 additions & 9 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::ContextualFoldingSet<DependentTemplateSpecializationType,
ASTContext&>
DependentTemplateSpecializationTypes;
llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
mutable llvm::FoldingSet<PackExpansionType> PackExpansionTypes;
mutable llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes;
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
mutable llvm::FoldingSet<DependentUnaryTransformType>
Expand Down Expand Up @@ -1719,8 +1719,15 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST) const;

QualType getAttributedType(attr::Kind attrKind, QualType modifiedType,
QualType equivalentType,
const Attr *attr = nullptr) const;

QualType getAttributedType(const Attr *attr, QualType modifiedType,
QualType equivalentType) const;

QualType getAttributedType(NullabilityKind nullability, QualType modifiedType,
QualType equivalentType);

QualType getBTFTagAttributedType(const BTFTypeTagAttr *BTFAttr,
QualType Wrapped) const;

Expand Down Expand Up @@ -1778,13 +1785,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,
const IdentifierInfo *Name, ArrayRef<TemplateArgument> Args) const;

TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl);

/// Get a template argument list with one argument per template parameter
/// in a template parameter list, such as for the injected class name of
/// a class template.
void getInjectedTemplateArgs(const TemplateParameterList *Params,
SmallVectorImpl<TemplateArgument> &Args);
TemplateArgument getInjectedTemplateArg(NamedDecl *ParamDecl) const;

/// Form a pack expansion type with the given pattern.
/// \param NumExpansions The number of expansions for the pack, if known.
Expand All @@ -1795,7 +1796,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// if this is the canonical type of another pack expansion type.
QualType getPackExpansionType(QualType Pattern,
std::optional<unsigned> NumExpansions,
bool ExpectPackInType = true);
bool ExpectPackInType = true) const;

QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
ObjCInterfaceDecl *PrevDecl = nullptr) const;
Expand Down
44 changes: 20 additions & 24 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ NamedDecl *getAsNamedDecl(TemplateParameter P);
class TemplateParameterList final
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
Expr *> {
/// The template argument list of the template parameter list.
TemplateArgument *InjectedArgs = nullptr;

/// The location of the 'template' keyword.
SourceLocation TemplateLoc;

Expand Down Expand Up @@ -196,6 +199,9 @@ class TemplateParameterList final

bool hasAssociatedConstraints() const;

/// Get the template argument list of the template parameter list.
ArrayRef<TemplateArgument> getInjectedTemplateArgs(const ASTContext &Context);

SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
Expand Down Expand Up @@ -793,15 +799,6 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// The first value in the array is the number of specializations/partial
/// specializations that follow.
GlobalDeclID *LazySpecializations = nullptr;

/// The set of "injected" template arguments used within this
/// template.
///
/// This pointer refers to the template arguments (there are as
/// many template arguments as template parameters) for the
/// template, and is allocated lazily, since most templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs = nullptr;
};

/// Pointer to the common data shared by all declarations of this
Expand Down Expand Up @@ -927,7 +924,10 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// Although the C++ standard has no notion of the "injected" template
/// arguments for a template, the notion is convenient when
/// we need to perform substitutions inside the definition of a template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
ArrayRef<TemplateArgument>
getInjectedTemplateArgs(const ASTContext &Context) const {
return getTemplateParameters()->getInjectedTemplateArgs(Context);
}

using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator;
Expand Down Expand Up @@ -2087,10 +2087,6 @@ class ClassTemplatePartialSpecializationDecl
/// The list of template parameters
TemplateParameterList *TemplateParams = nullptr;

/// The set of "injected" template arguments used within this
/// partial specialization.
TemplateArgument *InjectedArgs = nullptr;

/// The class template partial specialization from which this
/// class template partial specialization was instantiated.
///
Expand Down Expand Up @@ -2136,9 +2132,11 @@ class ClassTemplatePartialSpecializationDecl
return TemplateParams;
}

/// Retrieve the template arguments list of the template parameter list
/// of this template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// Get the template argument list of the template parameter list.
ArrayRef<TemplateArgument>
getInjectedTemplateArgs(const ASTContext &Context) const {
return getTemplateParameters()->getInjectedTemplateArgs(Context);
}

/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
Expand Down Expand Up @@ -2864,10 +2862,6 @@ class VarTemplatePartialSpecializationDecl
/// The list of template parameters
TemplateParameterList *TemplateParams = nullptr;

/// The set of "injected" template arguments used within this
/// partial specialization.
TemplateArgument *InjectedArgs = nullptr;

/// The variable template partial specialization from which this
/// variable template partial specialization was instantiated.
///
Expand Down Expand Up @@ -2914,9 +2908,11 @@ class VarTemplatePartialSpecializationDecl
return TemplateParams;
}

/// Retrieve the template arguments list of the template parameter list
/// of this template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// Get the template argument list of the template parameter list.
ArrayRef<TemplateArgument>
getInjectedTemplateArgs(const ASTContext &Context) const {
return getTemplateParameters()->getInjectedTemplateArgs(Context);
}

/// \brief All associated constraints of this partial specialization,
/// including the requires clause and any constraints derived from
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/PropertiesBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ def APValue : PropertyType { let PassByReference = 1; }
def APValueKind : EnumPropertyType<"APValue::ValueKind">;
def ArraySizeModifier : EnumPropertyType<"ArraySizeModifier">;
def AttrKind : EnumPropertyType<"attr::Kind">;
def Attr : PropertyType<"const Attr *">;
def AutoTypeKeyword : EnumPropertyType;
def Bool : PropertyType<"bool">;
def BuiltinTypeKind : EnumPropertyType<"BuiltinType::Kind">;
Expand Down
42 changes: 17 additions & 25 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class ValueDecl;
class TagDecl;
class TemplateParameterList;
class Type;
class Attr;

enum {
TypeAlignmentInBits = 4,
Expand Down Expand Up @@ -6130,21 +6131,29 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
private:
friend class ASTContext; // ASTContext creates these

const Attr *Attribute;

QualType ModifiedType;
QualType EquivalentType;

AttributedType(QualType canon, attr::Kind attrKind, QualType modified,
QualType equivalent)
: Type(Attributed, canon, equivalent->getDependence()),
ModifiedType(modified), EquivalentType(equivalent) {
AttributedTypeBits.AttrKind = attrKind;
}
: AttributedType(canon, attrKind, nullptr, modified, equivalent) {}

AttributedType(QualType canon, const Attr *attr, QualType modified,
QualType equivalent);

private:
AttributedType(QualType canon, attr::Kind attrKind, const Attr *attr,
QualType modified, QualType equivalent);

public:
Kind getAttrKind() const {
return static_cast<Kind>(AttributedTypeBits.AttrKind);
}

const Attr *getAttr() const { return Attribute; }

QualType getModifiedType() const { return ModifiedType; }
QualType getEquivalentType() const { return EquivalentType; }

Expand Down Expand Up @@ -6176,25 +6185,6 @@ class AttributedType : public Type, public llvm::FoldingSetNode {

std::optional<NullabilityKind> getImmediateNullability() const;

/// Retrieve the attribute kind corresponding to the given
/// nullability kind.
static Kind getNullabilityAttrKind(NullabilityKind kind) {
switch (kind) {
case NullabilityKind::NonNull:
return attr::TypeNonNull;

case NullabilityKind::Nullable:
return attr::TypeNullable;

case NullabilityKind::NullableResult:
return attr::TypeNullableResult;

case NullabilityKind::Unspecified:
return attr::TypeNullUnspecified;
}
llvm_unreachable("Unknown nullability kind.");
}

/// Strip off the top-level nullability annotation on the given
/// type, if it's there.
///
Expand All @@ -6207,14 +6197,16 @@ class AttributedType : public Type, public llvm::FoldingSetNode {
static std::optional<NullabilityKind> stripOuterNullability(QualType &T);

void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getAttrKind(), ModifiedType, EquivalentType);
Profile(ID, getAttrKind(), ModifiedType, EquivalentType, Attribute);
}

static void Profile(llvm::FoldingSetNodeID &ID, Kind attrKind,
QualType modified, QualType equivalent) {
QualType modified, QualType equivalent,
const Attr *attr) {
ID.AddInteger(attrKind);
ID.AddPointer(modified.getAsOpaquePtr());
ID.AddPointer(equivalent.getAsOpaquePtr());
ID.AddPointer(attr);
}

static bool classof(const Type *T) {
Expand Down
8 changes: 6 additions & 2 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -668,12 +668,16 @@ let Class = AttributedType in {
def : Property<"equivalentType", QualType> {
let Read = [{ node->getEquivalentType() }];
}
def : Property<"attribute", AttrKind> {
def : Property<"attrKind", AttrKind> {
let Read = [{ node->getAttrKind() }];
}
def : Property<"attribute", Attr> {
let Read = [{ node->getAttr() }];
}

def : Creator<[{
return ctx.getAttributedType(attribute, modifiedType, equivalentType);
return ctx.getAttributedType(attrKind, modifiedType,
equivalentType, attribute);
}]>;
}

Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -6750,7 +6750,8 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation,
/// matches 'A(int) {...};' and 'A(unsigned) {...}'.
AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
auto IsInstantiation = decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation())));
functionDecl(isTemplateInstantiation()),
varDecl(isTemplateInstantiation())));
return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
}

Expand All @@ -6769,9 +6770,9 @@ AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) {
/// will NOT match j += 42; as it's shared between the template definition and
/// instantiation.
AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) {
return stmt(
hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation())))));
return stmt(hasAncestor(decl(anyOf(cxxRecordDecl(isTemplateInstantiation()),
functionDecl(isTemplateInstantiation()),
varDecl(isTemplateInstantiation())))));
}

/// Matches explicit template specializations of function, class, or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ struct UncheckedOptionalAccessModelOptions {
/// can't identify when their results are used safely (across calls),
/// resulting in false positives in all such cases. Note: this option does not
/// cover access through `operator[]`.
/// FIXME: we currently cache and equate the result of const accessors
/// returning pointers, so cover the case of operator-> followed by
/// operator->, which covers the common case of smart pointers. We also cover
/// some limited cases of returning references (if return type is an optional
/// type), so cover some cases of operator* followed by operator*. We don't
/// cover mixing operator-> and operator*. Once we are confident in this const
/// accessor caching, we shouldn't need the IgnoreSmartPointerDereference
/// option anymore.
bool IgnoreSmartPointerDereference = false;
};

Expand Down
11 changes: 1 addition & 10 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,6 @@ def SYCL : LangOpt<"SYCLIsDevice">;
def COnly : LangOpt<"", "!LangOpts.CPlusPlus">;
def CPlusPlus : LangOpt<"CPlusPlus">;
def OpenCL : LangOpt<"OpenCL">;
def RenderScript : LangOpt<"RenderScript">;
def ObjC : LangOpt<"ObjC">;
def BlocksSupported : LangOpt<"Blocks">;
def ObjCAutoRefCount : LangOpt<"ObjCAutoRefCount">;
Expand Down Expand Up @@ -1629,14 +1628,6 @@ def OpenCLNoSVM : Attr {
let ASTNode = 0;
}

def RenderScriptKernel : Attr {
let Spellings = [GNU<"kernel">];
let Subjects = SubjectList<[Function]>;
let Documentation = [RenderScriptKernelAttributeDocs];
let LangOpts = [RenderScript];
let SimpleHandler = 1;
}

def Deprecated : InheritableAttr {
let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
CXX11<"","deprecated", 201309>,
Expand Down Expand Up @@ -2847,7 +2838,7 @@ def SwiftAsyncName : InheritableAttr {
let Documentation = [SwiftAsyncNameDocs];
}

def SwiftAttr : InheritableAttr {
def SwiftAttr : DeclOrTypeAttr {
let Spellings = [GNU<"swift_attr">];
let Args = [StringArgument<"Attribute">];
let Documentation = [SwiftAttrDocs];
Expand Down
47 changes: 22 additions & 25 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3702,20 +3702,32 @@ user-declared functions. For example:

.. code-block:: c++

#include <map>
#include <string>

using namespace std::literals;

// Returns m[key] if key is present, or default_value if not.
template<typename T, typename U>
const U &get_or_default(const std::map<T, U> &m [[clang::lifetimebound]],
const T &key, /* note, not lifetimebound */
const U &default_value [[clang::lifetimebound]]);
const U &default_value [[clang::lifetimebound]]) {
if (auto iter = m.find(key); iter != m.end()) return iter->second;
else return default_value;
}

std::map<std::string, std::string> m;
// warning: temporary "bar"s that might be bound to local reference 'val'
// will be destroyed at the end of the full-expression
const std::string &val = get_or_default(m, "foo"s, "bar"s);
int main() {
std::map<std::string, std::string> m;
// warning: temporary bound to local reference 'val1' will be destroyed
// at the end of the full-expression
const std::string &val1 = get_or_default(m, "foo"s, "bar"s);

// No warning in this case.
std::string def_val = "bar"s;
const std::string &val = get_or_default(m, "foo"s, def_val);
// No warning in this case.
std::string def_val = "bar"s;
const std::string &val2 = get_or_default(m, "foo"s, def_val);

return 0;
}

The attribute can be applied to the implicit ``this`` parameter of a member
function by writing the attribute after the function type:
Expand Down Expand Up @@ -4495,8 +4507,8 @@ def SwiftAttrDocs : Documentation {
let Heading = "swift_attr";
let Content = [{
The ``swift_attr`` provides a Swift-specific annotation for the declaration
to which the attribute appertains to. It can be used on any declaration
in Clang. This kind of annotation is ignored by Clang as it doesn't have any
or type to which the attribute appertains to. It can be used on any declaration
or type in Clang. This kind of annotation is ignored by Clang as it doesn't have any
semantic meaning in languages supported by Clang. The Swift compiler can
interpret these annotations according to its own rules when importing C or
Objective-C declarations.
Expand Down Expand Up @@ -5831,21 +5843,6 @@ provided with the regular ``visibility`` attribute.
}];
}

def RenderScriptKernelAttributeDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
``__attribute__((kernel))`` is used to mark a ``kernel`` function in
RenderScript.

In RenderScript, ``kernel`` functions are used to express data-parallel
computations. The RenderScript runtime efficiently parallelizes ``kernel``
functions to run on computational resources such as multi-core CPUs and GPUs.
See the RenderScript_ documentation for more information.

.. _RenderScript: https://developer.android.com/guide/topics/renderscript/compute.html
}];
}

def XRayDocs : Documentation {
let Category = DocCatFunction;
let Heading = "xray_always_instrument, xray_never_instrument, xray_log_args";
Expand Down
6 changes: 6 additions & 0 deletions clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -4871,6 +4871,12 @@ def HLSLRadians : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}

def HLSLSplitDouble: LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_elementwise_splitdouble"];
let Attributes = [NoThrow, Const];
let Prototype = "void(...)";
}

// Builtins for XRay.
def XRayCustomEvent : Builtin {
let Spellings = ["__xray_customevent"];
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/BuiltinsAMDGPU.def
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ TARGET_BUILTIN(__builtin_amdgcn_dot4_f32_bf8_bf8, "fUiUif", "nc", "dot11-insts")
//===----------------------------------------------------------------------===//
TARGET_BUILTIN(__builtin_amdgcn_permlane16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_permlanex16, "UiUiUiUiUiIbIb", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nc", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_mov_dpp8, "UiUiIUi", "nct", "gfx10-insts")
TARGET_BUILTIN(__builtin_amdgcn_s_ttracedata_imm, "vIs", "n", "gfx10-insts")

//===----------------------------------------------------------------------===//
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/BuiltinsBase.td
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def ConstIgnoringExceptions : Attribute<"g">;
// This function requires a specific header or an explicit declaration.
def RequireDeclaration : Attribute<"h">;

// FIXME: Why is this not simply the min_vector_width attribute?
// Vector has to be at least N bits wide.
class RequiredVectorWidth<int N> : IndexedAttribute<"V", N>;

class PrintfFormat<int I> : IndexedAttribute<"p", I>;
class VPrintfFormat<int I> : IndexedAttribute<"P", I>;
class ScanfFormat<int I> : IndexedAttribute<"s", I>;
Expand Down
130 changes: 4 additions & 126 deletions clang/include/clang/Basic/BuiltinsX86.def
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,6 @@
# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS)
#endif

// Undefined Values
//
TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "ncV:128:", "")
TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "ncV:256:", "")
TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "ncV:512:", "")

// FLAGS
//
TARGET_BUILTIN(__builtin_ia32_readeflags_u32, "Ui", "n", "")
TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "")

// MMX
//
// All MMX instructions will be generated via builtins. Any MMX vector
Expand All @@ -46,113 +35,8 @@ TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "")
// argument and our prior approach of using a #define to the current built-in
// doesn't work in the presence of re-declaration of _mm_prefetch for windows.
TARGET_BUILTIN(_mm_prefetch, "vcC*i", "nc", "mmx")
TARGET_BUILTIN(__builtin_ia32_emms, "v", "n", "mmx")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "sV4sIi", "ncV:64:", "sse")
TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4ssIi", "ncV:64:", "sse")

// SSE intrinsics.
TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "ncV:128:", "sse")

TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "ncV:128:", "sse2")

TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "sse")
TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "sse")

TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pavgb128, "V16cV16cV16c", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pavgw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "OiV2OiIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "ncV:128:", "sse2")
TARGET_BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssIi", "ncV:128:", "sse2")

TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "ncV:128:", "sse3")
TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "ncV:128:", "sse3")
TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "ncV:128:", "sse3")
TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "ncV:128:", "sse3")
TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "ncV:128:", "sse3")
TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "ncV:128:", "sse3")
TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "ncV:128:", "ssse3")
TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "ncV:128:", "ssse3")

TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "n", "sse")
TARGET_HEADER_BUILTIN(_mm_setcsr, "vUi", "nh",XMMINTRIN_H, ALL_LANGUAGES, "sse")
Expand Down Expand Up @@ -316,16 +200,6 @@ TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4OiV4OiV4OiIc", "ncV:256:", "vpclm
TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8OiV8OiV8OiIc", "ncV:512:", "avx512f,evex512,vpclmulqdq")

// AVX
TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2Oi", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "ncV:256:", "avx")
TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4Oi", "ncV:256:", "avx")
Expand Down Expand Up @@ -2179,6 +2053,10 @@ TARGET_BUILTIN(__builtin_ia32_vsm4key4256, "V8UiV8UiV8Ui", "nV:256:", "sm4")
TARGET_BUILTIN(__builtin_ia32_vsm4rnds4128, "V4UiV4UiV4Ui", "nV:128:", "sm4")
TARGET_BUILTIN(__builtin_ia32_vsm4rnds4256, "V8UiV8UiV8Ui", "nV:256:", "sm4")

// SM4_EVEX
TARGET_BUILTIN(__builtin_ia32_vsm4key4512, "V16UiV16UiV16Ui", "nV:512:", "avx10.2-512,sm4")
TARGET_BUILTIN(__builtin_ia32_vsm4rnds4512, "V16UiV16UiV16Ui", "nV:512:", "avx10.2-512,sm4")

// AVX10 MINMAX
TARGET_BUILTIN(__builtin_ia32_vminmaxnepbf16128, "V8yV8yV8yIi", "nV:128:", "avx10.2-256")
TARGET_BUILTIN(__builtin_ia32_vminmaxnepbf16256, "V16yV16yV16yIi", "nV:256:", "avx10.2-256")
Expand Down
Loading