184 changes: 92 additions & 92 deletions clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,102 +34,102 @@ UnusedReturnValueCheck::UnusedReturnValueCheck(llvm::StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
CheckedFunctions(utils::options::parseStringList(
Options.get("CheckedFunctions", "::std::async;"
"::std::launder;"
"::std::remove;"
"::std::remove_if;"
"::std::unique;"
"::std::unique_ptr::release;"
"::std::basic_string::empty;"
"::std::vector::empty;"
"::std::back_inserter;"
"::std::distance;"
"::std::find;"
"::std::find_if;"
"::std::inserter;"
"::std::lower_bound;"
"::std::make_pair;"
"::std::map::count;"
"::std::map::find;"
"::std::map::lower_bound;"
"::std::multimap::equal_range;"
"::std::multimap::upper_bound;"
"::std::set::count;"
"::std::set::find;"
"::std::setfill;"
"::std::setprecision;"
"::std::setw;"
"::std::upper_bound;"
"::std::vector::at;"
Options.get("CheckedFunctions", "::std::async$;"
"::std::launder$;"
"::std::remove$;"
"::std::remove_if$;"
"::std::unique$;"
"::std::unique_ptr::release$;"
"::std::basic_string::empty$;"
"::std::vector::empty$;"
"::std::back_inserter$;"
"::std::distance$;"
"::std::find$;"
"::std::find_if$;"
"::std::inserter$;"
"::std::lower_bound$;"
"::std::make_pair$;"
"::std::map::count$;"
"::std::map::find$;"
"::std::map::lower_bound$;"
"::std::multimap::equal_range$;"
"::std::multimap::upper_bound$;"
"::std::set::count$;"
"::std::set::find$;"
"::std::setfill$;"
"::std::setprecision$;"
"::std::setw$;"
"::std::upper_bound$;"
"::std::vector::at$;"
// C standard library
"::bsearch;"
"::ferror;"
"::feof;"
"::isalnum;"
"::isalpha;"
"::isblank;"
"::iscntrl;"
"::isdigit;"
"::isgraph;"
"::islower;"
"::isprint;"
"::ispunct;"
"::isspace;"
"::isupper;"
"::iswalnum;"
"::iswprint;"
"::iswspace;"
"::isxdigit;"
"::memchr;"
"::memcmp;"
"::strcmp;"
"::strcoll;"
"::strncmp;"
"::strpbrk;"
"::strrchr;"
"::strspn;"
"::strstr;"
"::wcscmp;"
"::bsearch$;"
"::ferror$;"
"::feof$;"
"::isalnum$;"
"::isalpha$;"
"::isblank$;"
"::iscntrl$;"
"::isdigit$;"
"::isgraph$;"
"::islower$;"
"::isprint$;"
"::ispunct$;"
"::isspace$;"
"::isupper$;"
"::iswalnum$;"
"::iswprint$;"
"::iswspace$;"
"::isxdigit$;"
"::memchr$;"
"::memcmp$;"
"::strcmp$;"
"::strcoll$;"
"::strncmp$;"
"::strpbrk$;"
"::strrchr$;"
"::strspn$;"
"::strstr$;"
"::wcscmp$;"
// POSIX
"::access;"
"::bind;"
"::connect;"
"::difftime;"
"::dlsym;"
"::fnmatch;"
"::getaddrinfo;"
"::getopt;"
"::htonl;"
"::htons;"
"::iconv_open;"
"::inet_addr;"
"::isascii;"
"::isatty;"
"::mmap;"
"::newlocale;"
"::openat;"
"::pathconf;"
"::pthread_equal;"
"::pthread_getspecific;"
"::pthread_mutex_trylock;"
"::readdir;"
"::readlink;"
"::recvmsg;"
"::regexec;"
"::scandir;"
"::semget;"
"::setjmp;"
"::shm_open;"
"::shmget;"
"::sigismember;"
"::strcasecmp;"
"::strsignal;"
"::access$;"
"::bind$;"
"::connect$;"
"::difftime$;"
"::dlsym$;"
"::fnmatch$;"
"::getaddrinfo$;"
"::getopt$;"
"::htonl$;"
"::htons$;"
"::iconv_open$;"
"::inet_addr$;"
"::isascii$;"
"::isatty$;"
"::mmap$;"
"::newlocale$;"
"::openat$;"
"::pathconf$;"
"::pthread_equal$;"
"::pthread_getspecific$;"
"::pthread_mutex_trylock$;"
"::readdir$;"
"::readlink$;"
"::recvmsg$;"
"::regexec$;"
"::scandir$;"
"::semget$;"
"::setjmp$;"
"::shm_open$;"
"::shmget$;"
"::sigismember$;"
"::strcasecmp$;"
"::strsignal$;"
"::ttyname"))),
CheckedReturnTypes(utils::options::parseStringList(
Options.get("CheckedReturnTypes", "::std::error_code;"
"::std::error_condition;"
"::std::errc;"
"::std::expected;"
Options.get("CheckedReturnTypes", "::std::error_code$;"
"::std::error_condition$;"
"::std::errc$;"
"::std::expected$;"
"::boost::system::error_code"))),
AllowCastToVoid(Options.get("AllowCastToVoid", false)) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -888,8 +888,14 @@ bool IdentifierNamingCheck::matchesStyle(
return false;
if (IdentifierNamingCheck::HungarianPrefixType::HPT_Off != Style.HPType) {
std::string HNPrefix = HungarianNotation.getPrefix(Decl, HNOption);
if (!Name.consume_front(HNPrefix))
return false;
if (!HNPrefix.empty()) {
if (!Name.consume_front(HNPrefix))
return false;
if (Style.HPType ==
IdentifierNamingCheck::HungarianPrefixType::HPT_LowerCase &&
!Name.consume_front("_"))
return false;
}
}

// Ensure the name doesn't have any extra underscores beyond those specified
Expand Down
9 changes: 5 additions & 4 deletions clang-tools-extra/clang-tidy/utils/DeclRefExprUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,15 +155,16 @@ AST_MATCHER_P(DeclRefExpr, doesNotMutateObject, int, Indirections) {
if (const auto *const Member = dyn_cast<MemberExpr>(P)) {
if (const auto *const Method =
dyn_cast<CXXMethodDecl>(Member->getMemberDecl())) {
if (!Method->isConst()) {
// The method can mutate our variable.
return false;
if (Method->isConst() || Method->isStatic()) {
// The method call cannot mutate our variable.
continue;
}
continue;
return false;
}
Stack.emplace_back(Member, 0);
continue;
}

if (const auto *const Op = dyn_cast<UnaryOperator>(P)) {
switch (Op->getOpcode()) {
case UO_AddrOf:
Expand Down
7 changes: 5 additions & 2 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ Changes in existing checks

- Improved :doc:`bugprone-unused-return-value
<clang-tidy/checks/bugprone/unused-return-value>` check by updating the
parameter `CheckedFunctions` to support regexp.
parameter `CheckedFunctions` to support regexp and avoiding false postive for
function with the same prefix as the default argument, e.g. ``std::unique_ptr``
and ``std::unique``.

- Improved :doc:`bugprone-use-after-move
<clang-tidy/checks/bugprone/use-after-move>` check to also handle
Expand Down Expand Up @@ -233,7 +235,8 @@ Changes in existing checks

- Improved :doc:`readability-identifier-naming
<clang-tidy/checks/readability/identifier-naming>` check in `GetConfigPerFile`
mode by resolving symbolic links to header files.
mode by resolving symbolic links to header files. Fixed handling of Hungarian
Prefix when configured to `LowerCase`.

Removed checks
^^^^^^^^^^^^^^
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,23 @@ Options
This parameter supports regexp. The function is checked if the name
and scope matches, with any arguments.
By default the following functions are checked:
``std::async, std::launder, std::remove, std::remove_if, std::unique,
std::unique_ptr::release, std::basic_string::empty, std::vector::empty,
std::back_inserter, std::distance, std::find, std::find_if, std::inserter,
std::lower_bound, std::make_pair, std::map::count, std::map::find,
std::map::lower_bound, std::multimap::equal_range,
std::multimap::upper_bound, std::set::count, std::set::find, std::setfill,
std::setprecision, std::setw, std::upper_bound, std::vector::at,
bsearch, ferror, feof, isalnum, isalpha, isblank, iscntrl, isdigit, isgraph,
islower, isprint, ispunct, isspace, isupper, iswalnum, iswprint, iswspace,
isxdigit, memchr, memcmp, strcmp, strcoll, strncmp, strpbrk, strrchr,
strspn, strstr, wcscmp, access, bind, connect, difftime, dlsym, fnmatch,
getaddrinfo, getopt, htonl, htons, iconv_open, inet_addr, isascii, isatty,
mmap, newlocale, openat, pathconf, pthread_equal, pthread_getspecific,
pthread_mutex_trylock, readdir, readlink, recvmsg, regexec, scandir,
semget, setjmp, shm_open, shmget, sigismember, strcasecmp, strsignal,
ttyname``
``::std::async$, ::std::launder$, ::std::remove$, ::std::remove_if$, ::std::unique$,
::std::unique_ptr::release$, ::std::basic_string::empty$, ::std::vector::empty$,
::std::back_inserter$, ::std::distance$, ::std::find$, ::std::find_if$, ::std::inserter$,
::std::lower_bound$, ::std::make_pair$, ::std::map::count$, ::std::map::find$,
::std::map::lower_bound$, ::std::multimap::equal_range$, ::std::multimap::upper_bound$,
::std::set::count$, ::std::set::find$, ::std::setfill$, ::std::setprecision$,
::std::setw$, ::std::upper_bound$, ::std::vector::at$, ::bsearch$, ::ferror$,
::feof$, ::isalnum$, ::isalpha$, ::isblank$, ::iscntrl$, ::isdigit$, ::isgraph$,
::islower$, ::isprint$, ::ispunct$, ::isspace$, ::isupper$, ::iswalnum$, ::iswprint$,
::iswspace$, ::isxdigit$, ::memchr$, ::memcmp$, ::strcmp$, ::strcoll$, ::strncmp$,
::strpbrk$, ::strrchr$, ::strspn$, ::strstr$, ::wcscmp$, ::access$, ::bind$,
::connect$, ::difftime$, ::dlsym$, ::fnmatch$, ::getaddrinfo$, ::getopt$,
::htonl$, ::htons$, ::iconv_open$, ::inet_addr$, isascii$, isatty$, ::mmap$,
::newlocale$, ::openat$, ::pathconf$, ::pthread_equal$, ::pthread_getspecific$,
::pthread_mutex_trylock$, ::readdir$, ::readlink$, ::recvmsg$, ::regexec$, ::scandir$,
::semget$, ::setjmp$, ::shm_open$, ::shmget$, ::sigismember$, ::strcasecmp$, ::strsignal$,
::ttyname$``

- ``std::async()``. Not using the return value makes the call synchronous.
- ``std::launder()``. Not using the return value usually means that the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ another if a mismatch is detected

Casing types include:

- ``lower_case``,
- ``UPPER_CASE``,
- ``camelBack``,
- ``CamelCase``,
- ``camel_Snake_Back``,
- ``Camel_Snake_Case``,
- ``aNy_CasE``,
- ``Leading_upper_snake_case``.
- ``lower_case``
- ``UPPER_CASE``
- ``camelBack``
- ``CamelCase``
- ``camel_Snake_Back``
- ``Camel_Snake_Case``
- ``aNy_CasE``
- ``Leading_upper_snake_case``

It also supports a fixed prefix and suffix that will be prepended or appended
to the identifiers, regardless of the casing.
Expand All @@ -32,8 +32,16 @@ but not where they are overridden, as it can't be fixed locally there.
This also applies for pseudo-override patterns like CRTP.

``Leading_upper_snake_case`` is a naming convention where the first word is capitalized
followed by lower case word(s) seperated by underscore(s) '_'. Examples include:
Cap_snake_case, Cobra_case, Foo_bar_baz, and Master_copy_8gb.
followed by lower case word(s) separated by underscore(s) '_'. Examples include:
`Cap_snake_case`, `Cobra_case`, `Foo_bar_baz`, and `Master_copy_8gb`.

Hungarian notation can be customized using different *HungarianPrefix* settings.
The options and their corresponding values are:

- ``Off`` - the default setting
- ``On`` - example: ``int iVariable``
- ``LowerCase`` - example: ``int i_Variable``
- ``CamelCase`` - example: ``int IVariable``

Options
-------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ struct default_delete;

template <typename T, typename Deleter = std::default_delete<T>>
struct unique_ptr {
unique_ptr();
unique_ptr(unique_ptr const&);
unique_ptr(unique_ptr &&);
unique_ptr& operator=(unique_ptr const&);
unique_ptr& operator=(unique_ptr &&);
T *release() noexcept;
};

Expand Down Expand Up @@ -254,3 +259,12 @@ void noWarning() {
({ std::async(increment, 42); });
auto StmtExprRetval = ({ std::async(increment, 42); });
}

namespace gh84314 {

extern std::unique_ptr<int> alloc();
void f1(std::unique_ptr<int> &foo) {
foo = alloc();
}

} // namespace gh84314
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Checks: readability-identifier-naming
CheckOptions:
readability-identifier-naming.AbstractClassCase: CamelCase
readability-identifier-naming.StructCase: CamelCase
readability-identifier-naming.UnionCase: camelBack
readability-identifier-naming.ClassCase: CamelCase
readability-identifier-naming.ClassConstantCase: CamelCase
readability-identifier-naming.ClassMemberCase: CamelCase
readability-identifier-naming.ConstantCase: CamelCase
readability-identifier-naming.ConstantMemberCase: CamelCase
readability-identifier-naming.ConstantParameterCase: CamelCase
readability-identifier-naming.ConstantPointerParameterCase: CamelCase
readability-identifier-naming.ConstexprVariableCase: CamelCase
readability-identifier-naming.EnumConstantCase: CamelCase
readability-identifier-naming.GlobalConstantCase: CamelCase
readability-identifier-naming.GlobalConstantPointerCase: CamelCase
readability-identifier-naming.GlobalPointerCase: CamelCase
readability-identifier-naming.GlobalVariableCase: CamelCase
readability-identifier-naming.LocalConstantCase: CamelCase
readability-identifier-naming.LocalConstantPointerCase: CamelCase
readability-identifier-naming.LocalPointerCase: CamelCase
readability-identifier-naming.LocalVariableCase: CamelCase
readability-identifier-naming.MemberCase: CamelCase
readability-identifier-naming.ParameterCase: CamelCase
readability-identifier-naming.PointerParameterCase: CamelCase
readability-identifier-naming.PrivateMemberCase: CamelCase
readability-identifier-naming.ProtectedMemberCase: CamelCase
readability-identifier-naming.PublicMemberCase: CamelCase
readability-identifier-naming.ScopedEnumConstantCase: CamelCase
readability-identifier-naming.StaticConstantCase: CamelCase
readability-identifier-naming.StaticVariableCase: CamelCase
readability-identifier-naming.VariableCase: CamelCase
readability-identifier-naming.AbstractClassHungarianPrefix: LowerCase
readability-identifier-naming.ClassHungarianPrefix: LowerCase
readability-identifier-naming.ClassConstantHungarianPrefix: LowerCase
readability-identifier-naming.ClassMemberHungarianPrefix: LowerCase
readability-identifier-naming.ConstantHungarianPrefix: LowerCase
readability-identifier-naming.ConstantMemberHungarianPrefix: LowerCase
readability-identifier-naming.ConstantParameterHungarianPrefix: LowerCase
readability-identifier-naming.ConstantPointerParameterHungarianPrefix: LowerCase
readability-identifier-naming.ConstexprVariableHungarianPrefix: LowerCase
readability-identifier-naming.EnumConstantHungarianPrefix: LowerCase
readability-identifier-naming.GlobalConstantHungarianPrefix: LowerCase
readability-identifier-naming.GlobalConstantPointerHungarianPrefix: LowerCase
readability-identifier-naming.GlobalPointerHungarianPrefix: LowerCase
readability-identifier-naming.GlobalVariableHungarianPrefix: LowerCase
readability-identifier-naming.LocalConstantHungarianPrefix: LowerCase
readability-identifier-naming.LocalConstantPointerHungarianPrefix: LowerCase
readability-identifier-naming.LocalPointerHungarianPrefix: LowerCase
readability-identifier-naming.LocalVariableHungarianPrefix: LowerCase
readability-identifier-naming.MemberHungarianPrefix: LowerCase
readability-identifier-naming.ParameterHungarianPrefix: LowerCase
readability-identifier-naming.PointerParameterHungarianPrefix: LowerCase
readability-identifier-naming.PrivateMemberHungarianPrefix: LowerCase
readability-identifier-naming.ProtectedMemberHungarianPrefix: LowerCase
readability-identifier-naming.PublicMemberHungarianPrefix: LowerCase
readability-identifier-naming.ScopedEnumConstantHungarianPrefix: LowerCase
readability-identifier-naming.StaticConstantHungarianPrefix: LowerCase
readability-identifier-naming.StaticVariableHungarianPrefix: LowerCase
readability-identifier-naming.VariableHungarianPrefix: LowerCase

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ template <int Indirections> void RunTest(StringRef Snippet) {
void constMethod() const;
void nonConstMethod();
static void staticMethod();
void operator()(ConstTag) const;
void operator()(NonConstTag);
Expand Down Expand Up @@ -109,10 +111,12 @@ TEST(ConstReferenceDeclRefExprsTest, ConstValueVar) {
useConstPtr(&/*const*/target);
useConstPtrConstRef(&/*const*/target);
/*const*/target.constMethod();
/*const*/target.staticMethod();
/*const*/target(ConstTag{});
/*const*/target[42];
useConstRef((/*const*/target));
(/*const*/target).constMethod();
/*const*/target.staticMethod();
(void)(/*const*/target == /*const*/target);
(void)/*const*/target;
(void)&/*const*/target;
Expand Down Expand Up @@ -140,6 +144,7 @@ TEST(ConstReferenceDeclRefExprsTest, ConstRefVar) {
useConstPtr(&/*const*/target);
useConstPtrConstRef(&/*const*/target);
/*const*/target.constMethod();
/*const*/target.staticMethod();
/*const*/target(ConstTag{});
/*const*/target[42];
useConstRef((/*const*/target));
Expand Down Expand Up @@ -179,6 +184,7 @@ TEST(ConstReferenceDeclRefExprsTest, ValueVar) {
useConstPtr(&/*const*/target);
useConstPtrConstRef(&/*const*/target);
/*const*/target.constMethod();
/*const*/target.staticMethod();
target.nonConstMethod();
/*const*/target(ConstTag{});
target[42];
Expand Down Expand Up @@ -218,6 +224,7 @@ TEST(ConstReferenceDeclRefExprsTest, RefVar) {
useConstPtr(&/*const*/target);
useConstPtrConstRef(&/*const*/target);
/*const*/target.constMethod();
/*const*/target.staticMethod();
target.nonConstMethod();
/*const*/target(ConstTag{});
target[42];
Expand Down Expand Up @@ -256,6 +263,7 @@ TEST(ConstReferenceDeclRefExprsTest, PtrVar) {
useConstPtrConstRef(/*const*/target);
usePtrConstPtr(&target);
/*const*/target->constMethod();
/*const*/target->staticMethod();
target->nonConstMethod();
(*/*const*/target)(ConstTag{});
(*target)[42];
Expand Down Expand Up @@ -292,6 +300,7 @@ TEST(ConstReferenceDeclRefExprsTest, ConstPtrVar) {
useConstPtrConstPtr(&/*const*/target);
useConstPtrConstRef(/*const*/target);
/*const*/target->constMethod();
/*const*/target->staticMethod();
(*/*const*/target)(ConstTag{});
(*/*const*/target)[42];
/*const*/target->operator[](42);
Expand Down
22 changes: 22 additions & 0 deletions clang/docs/DataFlowSanitizer.rst
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,28 @@ labels of just ``v1`` and ``v2``.
or, and can be accessed using
``dfsan_label dfsan_get_labels_in_signal_conditional();``.

* ``-dfsan-reaches-function-callbacks`` -- An experimental feature that inserts
callbacks for data entering a function.

In addition to this compilation flag, a callback handler must be registered
using ``dfsan_set_reaches_function_callback(my_callback);``, where my_callback is
a function with a signature matching
``void my_callback(dfsan_label label, dfsan_origin origin, const char *file, unsigned int line, const char *function);``
This signature is the same when origin tracking is disabled - in this case
the dfsan_origin passed in it will always be 0.

The callback will be called when a tained value reach stack/registers
in the context of a function. Tainted values can reach a function:
* via the arguments of the function
* via the return value of a call that occurs in the function
* via the loaded value of a load that occurs in the function

The callback will be skipped for conditional expressions inside signal
handlers, as this is prone to deadlock. Tainted values reaching functions
inside signal handlers will instead be aggregated via bitwise or, and can
be accessed using
``dfsan_label dfsan_get_labels_in_signal_reaches_function()``.

* ``-dfsan-track-origins`` -- Controls how to track origins. When its value is
0, the runtime does not track origins. When its value is 1, the runtime tracks
origins at memory store operations. When its value is 2, the runtime tracks
Expand Down
1 change: 1 addition & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5378,6 +5378,7 @@ The following builtin intrinsics can be used in constant expressions:
* ``__builtin_popcount``
* ``__builtin_popcountl``
* ``__builtin_popcountll``
* ``__builtin_popcountg``
* ``__builtin_rotateleft8``
* ``__builtin_rotateleft16``
* ``__builtin_rotateleft32``
Expand Down
15 changes: 15 additions & 0 deletions clang/docs/LibASTMatchersReference.html
Original file line number Diff line number Diff line change
Expand Up @@ -3546,6 +3546,21 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isExplicitObjectMemberFunction0')"><a name="isExplicitObjectMemberFunction0Anchor">isExplicitObjectMemberFunction</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isExplicitObjectMemberFunction0"><pre>Matches if the given method declaration declares a member function with an explicit object parameter.

Given
struct A {
int operator-(this A, int);
void fun(this A &&self);
static int operator()(int);
int operator+(int);
};

cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two methods but not the last two.
</pre></td></tr>


<tr><td>Matcher&lt;<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXMethodDecl.html">CXXMethodDecl</a>&gt;</td><td class="name" onclick="toggle('isCopyAssignmentOperator0')"><a name="isCopyAssignmentOperator0Anchor">isCopyAssignmentOperator</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="isCopyAssignmentOperator0"><pre>Matches if the given method declaration declares a copy assignment
operator.
Expand Down
25 changes: 23 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ C++20 Feature Support
current module units.
Fixes `#84002 <https://github.com/llvm/llvm-project/issues/84002>`_.

- Initial support for class template argument deduction (CTAD) for type alias
templates (`P1814R0 <https://wg21.link/p1814r0>`_).
(#GH54051).

C++23 Feature Support
^^^^^^^^^^^^^^^^^^^^^

Expand All @@ -115,6 +119,10 @@ Resolutions to C++ Defect Reports
of two types.
(`CWG1719: Layout compatibility and cv-qualification revisited <https://cplusplus.github.io/CWG/issues/1719.html>`_).

- Alignment of members is now respected when evaluating layout compatibility
of structs.
(`CWG2583: Common initial sequence should consider over-alignment <https://cplusplus.github.io/CWG/issues/2583.html>`_).

- ``[[no_unique_address]]`` is now respected when evaluating layout
compatibility of two types.
(`CWG2759: [[no_unique_address] and common initial sequence <https://cplusplus.github.io/CWG/issues/2759.html>`_).
Expand Down Expand Up @@ -157,6 +165,11 @@ Non-comprehensive list of changes in this release
- ``__builtin_addc``, ``__builtin_subc``, and the other sizes of those
builtins are now constexpr and may be used in constant expressions.

- Added ``__builtin_popcountg`` as a type-generic alternative to
``__builtin_popcount{,l,ll}`` with support for any unsigned integer type. Like
the previous builtins, this new builtin is constexpr and may be used in
constant expressions.

New Compiler Flags
------------------

Expand Down Expand Up @@ -241,6 +254,10 @@ Bug Fixes in This Version
for variables created through copy initialization having side-effects in C++17 and later.
Fixes (#GH64356) (#GH79518).

- Clang now emits errors for explicit specializations/instatiations of lambda call
operator.
Fixes (#GH83267).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -319,8 +336,6 @@ Bug Fixes to C++ Support
our attention by an attempt to fix in (#GH77703). Fixes (#GH83385).
- Fix evaluation of some immediate calls in default arguments.
Fixes (#GH80630)
- Fix a crash when an explicit template argument list is used with a name for which lookup
finds a non-template function and a dependent using declarator.
- Fixed an issue where the ``RequiresExprBody`` was involved in the lambda dependency
calculation. (#GH56556), (#GH82849).
- Fix a bug where overload resolution falsely reported an ambiguity when it was comparing
Expand Down Expand Up @@ -373,6 +388,8 @@ Arm and AArch64 Support
instructions (rdm). The identifier is available on the command line as
a feature modifier for -march and -mcpu as well as via target attributes
like ``target_version`` or ``target_clones``.
- Support has been added for the following processors (-mcpu identifiers in parenthesis):
* Arm Cortex-A78AE (cortex-a78ae).

Android Support
^^^^^^^^^^^^^^^
Expand All @@ -391,6 +408,9 @@ RISC-V Support
CUDA/HIP Language Changes
^^^^^^^^^^^^^^^^^^^^^^^^^

- PTX is no longer included by default when compiling for CUDA. Using
``--cuda-include-ptx=all`` will return the old behavior.

CUDA Support
^^^^^^^^^^^^

Expand Down Expand Up @@ -419,6 +439,7 @@ AST Matchers
------------

- ``isInStdNamespace`` now supports Decl declared with ``extern "C++"``.
- Add ``isExplicitObjectMemberFunction``.

clang-format
------------
Expand Down
19 changes: 19 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Original file line number Diff line number Diff line change
Expand Up @@ -6366,6 +6366,25 @@ AST_MATCHER(CXXMethodDecl, isConst) {
return Node.isConst();
}

/// Matches if the given method declaration declares a member function with an
/// explicit object parameter.
///
/// Given
/// \code
/// struct A {
/// int operator-(this A, int);
/// void fun(this A &&self);
/// static int operator()(int);
/// int operator+(int);
/// };
/// \endcode
///
/// cxxMethodDecl(isExplicitObjectMemberFunction()) matches the first two
/// methods but not the last two.
AST_MATCHER(CXXMethodDecl, isExplicitObjectMemberFunction) {
return Node.isExplicitObjectMemberFunction();
}

/// Matches if the given method declaration declares a copy assignment
/// operator.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,11 @@ class Environment {
return createObjectInternal(&D, D.getType(), InitExpr);
}

/// Initializes the fields (including synthetic fields) of `Loc` with values,
/// unless values of the field type are not supported or we hit one of the
/// limits at which we stop producing values.
void initializeFieldsWithValues(RecordStorageLocation &Loc);

/// Assigns `Val` as the value of `Loc` in the environment.
void setValue(const StorageLocation &Loc, Value &Val);

Expand Down
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,8 @@ def Availability : InheritableAttr {
.Case("watchos_app_extension", "watchOS (App Extension)")
.Case("maccatalyst", "macCatalyst")
.Case("maccatalyst_app_extension", "macCatalyst (App Extension)")
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOS (App Extension)")
.Case("swift", "Swift")
.Case("shadermodel", "HLSL ShaderModel")
.Case("ohos", "OpenHarmony OS")
Expand All @@ -1000,6 +1002,8 @@ static llvm::StringRef getPlatformNameSourceSpelling(llvm::StringRef Platform) {
.Case("watchos_app_extension", "watchOSApplicationExtension")
.Case("maccatalyst", "macCatalyst")
.Case("maccatalyst_app_extension", "macCatalystApplicationExtension")
.Case("xros", "visionOS")
.Case("xros_app_extension", "visionOSApplicationExtension")
.Case("zos", "z/OS")
.Case("shadermodel", "ShaderModel")
.Default(Platform);
Expand All @@ -1016,6 +1020,10 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) {
.Case("watchOSApplicationExtension", "watchos_app_extension")
.Case("macCatalyst", "maccatalyst")
.Case("macCatalystApplicationExtension", "maccatalyst_app_extension")
.Case("visionOS", "xros")
.Case("visionOSApplicationExtension", "xros_app_extension")
.Case("visionos", "xros")
.Case("visionos_app_extension", "xros_app_extension")
.Case("ShaderModel", "shadermodel")
.Default(Platform);
} }];
Expand Down
102 changes: 0 additions & 102 deletions clang/include/clang/Basic/Builtins.def

This file was deleted.

2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Builtins.td
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ def Popcount : Builtin, BitInt_Long_LongLongTemplate {

def Popcountg : Builtin {
let Spellings = ["__builtin_popcountg"];
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
let Prototype = "int(...)";
}

Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Cuda.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ enum class CudaArch {
LAST,

CudaDefault = CudaArch::SM_52,
HIPDefault = CudaArch::GFX803,
HIPDefault = CudaArch::GFX906,
};

static inline bool IsNVIDIAGpuArch(CudaArch A) {
Expand Down
24 changes: 24 additions & 0 deletions clang/include/clang/Basic/DarwinSDKInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,30 @@ class DarwinSDKInfo {
map(const VersionTuple &Key, const VersionTuple &MinimumValue,
std::optional<VersionTuple> MaximumValue) const;

/// Remap the 'introduced' availability version.
/// If None is returned, the 'unavailable' availability should be used
/// instead.
std::optional<VersionTuple>
mapIntroducedAvailabilityVersion(const VersionTuple &Key) const {
// API_TO_BE_DEPRECATED is 100000.
if (Key.getMajor() == 100000)
return VersionTuple(100000);
// Use None for maximum to force unavailable behavior for
return map(Key, MinimumValue, std::nullopt);
}

/// Remap the 'deprecated' and 'obsoleted' availability version.
/// If None is returned for 'obsoleted', the 'unavailable' availability
/// should be used instead. If None is returned for 'deprecated', the
/// 'deprecated' version should be dropped.
std::optional<VersionTuple>
mapDeprecatedObsoletedAvailabilityVersion(const VersionTuple &Key) const {
// API_TO_BE_DEPRECATED is 100000.
if (Key.getMajor() == 100000)
return VersionTuple(100000);
return map(Key, MinimumValue, MaximumValue);
}

static std::optional<RelatedTargetVersionMapping>
parseJSON(const llvm::json::Object &Obj,
VersionTuple MaximumDeploymentTarget);
Expand Down
12 changes: 10 additions & 2 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -2515,10 +2515,11 @@ def err_deduced_class_template_compound_type : Error<
"cannot %select{form pointer to|form reference to|form array of|"
"form function returning|use parentheses when declaring variable with}0 "
"deduced class template specialization type">;
def err_deduced_non_class_template_specialization_type : Error<
def err_deduced_non_class_or_alias_template_specialization_type : Error<
"%select{<error>|function template|variable template|alias template|"
"template template parameter|concept|template}0 %1 requires template "
"arguments; argument deduction only allowed for class templates">;
"arguments; argument deduction only allowed for class templates or alias "
"templates">;
def err_deduced_class_template_ctor_ambiguous : Error<
"ambiguous deduction for template arguments of %0">;
def err_deduced_class_template_ctor_no_viable : Error<
Expand Down Expand Up @@ -8170,6 +8171,8 @@ let CategoryName = "Lambda Issue" in {
def warn_cxx11_compat_generic_lambda : Warning<
"generic lambdas are incompatible with C++11">,
InGroup<CXXPre14Compat>, DefaultIgnore;
def err_lambda_explicit_spec : Error<
"lambda call operator should not be explicitly specialized or instantiated">;

// C++17 '*this' captures.
def warn_cxx14_compat_star_this_lambda_capture : Warning<
Expand Down Expand Up @@ -8199,6 +8202,11 @@ let CategoryName = "Lambda Issue" in {
def warn_cxx17_compat_lambda_def_ctor_assign : Warning<
"%select{default construction|assignment}0 of lambda is incompatible with "
"C++ standards before C++20">, InGroup<CXXPre20Compat>, DefaultIgnore;

// C++20 class template argument deduction for alias templates.
def warn_cxx17_compat_ctad_for_alias_templates : Warning<
"class template argument deduction for alias templates is incompatible with "
"C++ standards before C++20">, InGroup<CXXPre20Compat>, DefaultIgnore;
}

def err_return_in_captured_stmt : Error<
Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/Basic/arm_sve.td
Original file line number Diff line number Diff line change
Expand Up @@ -2215,6 +2215,15 @@ let TargetGuard = "sve2p1" in {
def SVTBXQ : SInst<"svtbxq[_{d}]", "dddu", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_tbxq">;
// EXTQ
def EXTQ : SInst<"svextq[_{d}]", "dddk", "cUcsUsiUilUlbhfd", MergeNone, "aarch64_sve_extq", [], [ImmCheck<2, ImmCheck0_15>]>;
// DUPQ
def SVDUP_LANEQ_B : SInst<"svdup_laneq[_{d}]", "ddi", "cUc", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_15>]>;
def SVDUP_LANEQ_H : SInst<"svdup_laneq[_{d}]", "ddi", "sUsh", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_7>]>;
def SVDUP_LANEQ_S : SInst<"svdup_laneq[_{d}]", "ddi", "iUif", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_3>]>;
def SVDUP_LANEQ_D : SInst<"svdup_laneq[_{d}]", "ddi", "lUld", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_1>]>;

let TargetGuard = "bf16" in {
def SVDUP_LANEQ_BF16 : SInst<"svdup_laneq[_{d}]", "ddi", "b", MergeNone, "aarch64_sve_dup_laneq", [IsStreamingCompatible], [ImmCheck<1, ImmCheck0_7>]>;
}
// PMOV
// Move to Pred
multiclass PMOV_TO_PRED<string name, string types, string intrinsic, list<FlagType> flags=[], ImmCheckType immCh > {
Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -7414,7 +7414,9 @@ def ast_view : Flag<["-"], "ast-view">,
def emit_module : Flag<["-"], "emit-module">,
HelpText<"Generate pre-compiled module file from a module map">;
def emit_module_interface : Flag<["-"], "emit-module-interface">,
HelpText<"Generate pre-compiled module file from a C++ module interface">;
HelpText<"Generate pre-compiled module file from a standard C++ module interface unit">;
def emit_reduced_module_interface : Flag<["-"], "emit-reduced-module-interface">,
HelpText<"Generate reduced prebuilt module interface from a standard C++ module interface unit">;
def emit_header_unit : Flag<["-"], "emit-header-unit">,
HelpText<"Generate C++20 header units from header files">;
def emit_pch : Flag<["-"], "emit-pch">,
Expand Down
15 changes: 14 additions & 1 deletion clang/include/clang/Frontend/FrontendActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,9 @@ class GenerateModuleAction : public ASTFrontendAction {
CreateOutputFile(CompilerInstance &CI, StringRef InFile) = 0;

protected:
std::vector<std::unique_ptr<ASTConsumer>>
CreateMultiplexConsumer(CompilerInstance &CI, StringRef InFile);

std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;

Expand Down Expand Up @@ -147,8 +150,10 @@ class GenerateModuleFromModuleMapAction : public GenerateModuleAction {
CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};

/// Generates full BMI (which contains full information to generate the object
/// files) for C++20 Named Modules.
class GenerateModuleInterfaceAction : public GenerateModuleAction {
private:
protected:
bool BeginSourceFileAction(CompilerInstance &CI) override;

std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
Expand All @@ -158,6 +163,14 @@ class GenerateModuleInterfaceAction : public GenerateModuleAction {
CreateOutputFile(CompilerInstance &CI, StringRef InFile) override;
};

/// Only generates the reduced BMI. This action is mainly used by tests.
class GenerateReducedModuleInterfaceAction
: public GenerateModuleInterfaceAction {
private:
std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) override;
};

class GenerateHeaderUnitAction : public GenerateModuleAction {

private:
Expand Down
6 changes: 5 additions & 1 deletion clang/include/clang/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,13 @@ enum ActionKind {
/// Generate pre-compiled module from a module map.
GenerateModule,

/// Generate pre-compiled module from a C++ module interface file.
/// Generate pre-compiled module from a standard C++ module interface unit.
GenerateModuleInterface,

/// Generate reduced module interface for a standard C++ module interface
/// unit.
GenerateReducedModuleInterface,

/// Generate a C++20 header unit module from a header file.
GenerateHeaderUnit,

Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/InstallAPI/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ class FrontendRecordsSlice : public llvm::MachO::RecordsSlice {
/// \param D The pointer to the declaration from traversing AST.
/// \param Access The intended access level of symbol.
/// \param Flags The flags that describe attributes of the symbol.
/// \param Inlined Whether declaration is inlined, only applicable to
/// functions.
/// \return The non-owning pointer to added record in slice.
GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage,
GlobalRecord::Kind GV,
const clang::AvailabilityInfo Avail, const Decl *D,
const HeaderType Access,
SymbolFlags Flags = SymbolFlags::None);
SymbolFlags Flags = SymbolFlags::None,
bool Inlined = false);

/// Add ObjC Class record with attributes from AST.
///
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/InstallAPI/Visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class InstallAPIVisitor final : public ASTConsumer,
/// Collect global variables.
bool VisitVarDecl(const VarDecl *D);

/// Collect global functions.
bool VisitFunctionDecl(const FunctionDecl *D);

/// Collect Objective-C Interface declarations.
/// Every Objective-C class has an interface declaration that lists all the
/// ivars, properties, and methods of the class.
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/Interpreter/Interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class IncrementalCompilerBuilder {
UserArgs = Args;
}

void SetTargetTriple(std::string TT) { TargetTriple = TT; }

// General C++
llvm::Expected<std::unique_ptr<CompilerInstance>> CreateCpp();

Expand All @@ -62,11 +64,12 @@ class IncrementalCompilerBuilder {

private:
static llvm::Expected<std::unique_ptr<CompilerInstance>>
create(std::vector<const char *> &ClangArgv);
create(std::string TT, std::vector<const char *> &ClangArgv);

llvm::Expected<std::unique_ptr<CompilerInstance>> createCuda(bool device);

std::vector<const char *> UserArgs;
std::optional<std::string> TargetTriple;

llvm::StringRef OffloadArch;
llvm::StringRef CudaSDKPath;
Expand Down
39 changes: 30 additions & 9 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -6752,10 +6752,18 @@ class Sema final {
SourceLocation RParenLoc);

//// ActOnCXXThis - Parse 'this' pointer.
ExprResult ActOnCXXThis(SourceLocation loc);
///
/// \param ThisRefersToClosureObject Whether to skip the 'this' check for a
/// lambda because 'this' refers to the closure object.
ExprResult ActOnCXXThis(SourceLocation loc,
bool ThisRefersToClosureObject = false);

/// Build a CXXThisExpr and mark it referenced in the current context.
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit);
///
/// \param ThisRefersToClosureObject Whether to skip the 'this' check for a
/// lambda because 'this' refers to the closure object.
Expr *BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit,
bool ThisRefersToClosureObject = false);
void MarkThisReferenced(CXXThisExpr *This);

/// Try to retrieve the type of the 'this' pointer.
Expand Down Expand Up @@ -9827,6 +9835,12 @@ class Sema final {
ArrayRef<TemplateArgument> TemplateArgs,
sema::TemplateDeductionInfo &Info);

TemplateDeductionResult DeduceTemplateArguments(
TemplateParameterList *TemplateParams, ArrayRef<TemplateArgument> Ps,
ArrayRef<TemplateArgument> As, sema::TemplateDeductionInfo &Info,
SmallVectorImpl<DeducedTemplateArgument> &Deduced,
bool NumberOfArgumentsMustMatch);

TemplateDeductionResult SubstituteExplicitTemplateArguments(
FunctionTemplateDecl *FunctionTemplate,
TemplateArgumentListInfo &ExplicitTemplateArgs,
Expand Down Expand Up @@ -10378,6 +10392,9 @@ class Sema final {
InstantiatingTemplate &operator=(const InstantiatingTemplate &) = delete;
};

bool SubstTemplateArgument(const TemplateArgumentLoc &Input,
const MultiLevelTemplateArgumentList &TemplateArgs,
TemplateArgumentLoc &Output);
bool
SubstTemplateArguments(ArrayRef<TemplateArgumentLoc> Args,
const MultiLevelTemplateArgumentList &TemplateArgs,
Expand Down Expand Up @@ -10862,9 +10879,11 @@ class Sema final {
ParmVarDecl *Param);
void InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
FunctionDecl *Function);
FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD,
const TemplateArgumentList *Args,
SourceLocation Loc);
FunctionDecl *InstantiateFunctionDeclaration(
FunctionTemplateDecl *FTD, const TemplateArgumentList *Args,
SourceLocation Loc,
CodeSynthesisContext::SynthesisKind CSC =
CodeSynthesisContext::ExplicitTemplateArgumentSubstitution);
void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function,
bool Recursive = false,
Expand Down Expand Up @@ -11607,12 +11626,14 @@ class Sema final {
LocalInstantiationScope &Scope,
const MultiLevelTemplateArgumentList &TemplateArgs);

/// used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
/// Used by SetupConstraintCheckingTemplateArgumentsAndScope to recursively(in
/// the case of lambdas) set up the LocalInstantiationScope of the current
/// function.
bool SetupConstraintScope(
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope);
bool
SetupConstraintScope(FunctionDecl *FD,
std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
const MultiLevelTemplateArgumentList &MLTAL,
LocalInstantiationScope &Scope);

/// Used during constraint checking, sets up the constraint template argument
/// lists, and calls SetupConstraintScope to set up the
Expand Down
32 changes: 30 additions & 2 deletions clang/include/clang/Serialization/ASTWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ class ASTWriter : public ASTDeserializationListener,
/// Indicates that the AST contained compiler errors.
bool ASTHasCompilerErrors = false;

/// Indicates that we're going to generate the reduced BMI for C++20
/// named modules.
bool GeneratingReducedBMI = false;

/// Mapping from input file entries to the index into the
/// offset table where information about that input file is stored.
llvm::DenseMap<const FileEntry *, uint32_t> InputFileIDs;
Expand Down Expand Up @@ -596,7 +600,8 @@ class ASTWriter : public ASTDeserializationListener,
ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer,
InMemoryModuleCache &ModuleCache,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool IncludeTimestamps = true, bool BuildingImplicitModule = false);
bool IncludeTimestamps = true, bool BuildingImplicitModule = false,
bool GeneratingReducedBMI = false);
~ASTWriter() override;

ASTContext &getASTContext() const {
Expand Down Expand Up @@ -856,14 +861,22 @@ class PCHGenerator : public SemaConsumer {
const ASTWriter &getWriter() const { return Writer; }
SmallVectorImpl<char> &getPCH() const { return Buffer->Data; }

bool isComplete() const { return Buffer->IsComplete; }
PCHBuffer *getBufferPtr() { return Buffer.get(); }
StringRef getOutputFile() const { return OutputFile; }
DiagnosticsEngine &getDiagnostics() const {
return SemaPtr->getDiagnostics();
}

public:
PCHGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
StringRef OutputFile, StringRef isysroot,
std::shared_ptr<PCHBuffer> Buffer,
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
bool AllowASTWithErrors = false, bool IncludeTimestamps = true,
bool BuildingImplicitModule = false,
bool ShouldCacheASTInMemory = false);
bool ShouldCacheASTInMemory = false,
bool GeneratingReducedBMI = false);
~PCHGenerator() override;

void InitializeSema(Sema &S) override { SemaPtr = &S; }
Expand All @@ -873,6 +886,21 @@ class PCHGenerator : public SemaConsumer {
bool hasEmittedPCH() const { return Buffer->IsComplete; }
};

class ReducedBMIGenerator : public PCHGenerator {
public:
ReducedBMIGenerator(const Preprocessor &PP, InMemoryModuleCache &ModuleCache,
StringRef OutputFile, std::shared_ptr<PCHBuffer> Buffer,
bool IncludeTimestamps);

void HandleTranslationUnit(ASTContext &Ctx) override;
};

/// If we can elide the definition of \param D in reduced BMI.
///
/// Generally, we can elide the definition of a declaration if it won't affect
/// the ABI. e.g., the non-inline function bodies.
bool CanElideDeclDef(const Decl *D);

/// A simple helper class to pack several bits in order into (a) 32 bit
/// integer(s).
class BitsPacker {
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Testing/CommandLineArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ enum TestLanguage {
Lang_CXX14,
Lang_CXX17,
Lang_CXX20,
Lang_CXX23,
Lang_OpenCL,
Lang_OBJC,
Lang_OBJCXX
Expand Down
16 changes: 11 additions & 5 deletions clang/include/clang/Testing/TestClangConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,30 @@ struct TestClangConfig {
bool isCXX() const {
return Language == Lang_CXX03 || Language == Lang_CXX11 ||
Language == Lang_CXX14 || Language == Lang_CXX17 ||
Language == Lang_CXX20;
Language == Lang_CXX20 || Language == Lang_CXX23;
}

bool isCXX11OrLater() const {
return Language == Lang_CXX11 || Language == Lang_CXX14 ||
Language == Lang_CXX17 || Language == Lang_CXX20;
Language == Lang_CXX17 || Language == Lang_CXX20 ||
Language == Lang_CXX23;
}

bool isCXX14OrLater() const {
return Language == Lang_CXX14 || Language == Lang_CXX17 ||
Language == Lang_CXX20;
Language == Lang_CXX20 || Language == Lang_CXX23;
}

bool isCXX17OrLater() const {
return Language == Lang_CXX17 || Language == Lang_CXX20;
return Language == Lang_CXX17 || Language == Lang_CXX20 ||
Language == Lang_CXX23;
}

bool isCXX20OrLater() const { return Language == Lang_CXX20; }
bool isCXX20OrLater() const {
return Language == Lang_CXX20 || Language == Lang_CXX23;
}

bool isCXX23OrLater() const { return Language == Lang_CXX23; }

bool supportsCXXDynamicExceptionSpecification() const {
return Language == Lang_CXX03 || Language == Lang_CXX11 ||
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12483,6 +12483,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
case Builtin::BI__builtin_popcount:
case Builtin::BI__builtin_popcountl:
case Builtin::BI__builtin_popcountll:
case Builtin::BI__builtin_popcountg:
case Builtin::BI__popcnt16: // Microsoft variants of popcount
case Builtin::BI__popcnt:
case Builtin::BI__popcnt64: {
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,8 @@ bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) {
if (!this->visit(SubExpr))
return false;
this->emitSetLocal(*SubExprT, *LocalIndex, E);
if (!this->emitSetLocal(*SubExprT, *LocalIndex, E))
return false;
return this->emitGetPtrLocal(*LocalIndex, E);
}
} else {
Expand Down
1 change: 0 additions & 1 deletion clang/lib/AST/Interp/Program.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ class VarDecl;

namespace interp {
class Context;
class Record;

/// The program contains and links the bytecode for all functions.
class Program final {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/ASTMatchers/Dynamic/Registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isExpansionInMainFile);
REGISTER_MATCHER(isExpansionInSystemHeader);
REGISTER_MATCHER(isExplicit);
REGISTER_MATCHER(isExplicitObjectMemberFunction);
REGISTER_MATCHER(isExplicitTemplateSpecialization);
REGISTER_MATCHER(isExpr);
REGISTER_MATCHER(isExternC);
Expand Down
21 changes: 19 additions & 2 deletions clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,15 @@ void Environment::initialize() {
}
} else if (MethodDecl->isImplicitObjectMemberFunction()) {
QualType ThisPointeeType = MethodDecl->getFunctionObjectParameterType();
setThisPointeeStorageLocation(
cast<RecordStorageLocation>(createObject(ThisPointeeType)));
auto &ThisLoc =
cast<RecordStorageLocation>(createStorageLocation(ThisPointeeType));
setThisPointeeStorageLocation(ThisLoc);
refreshRecordValue(ThisLoc, *this);
// Initialize fields of `*this` with values, but only if we're not
// analyzing a constructor; after all, it's the constructor's job to do
// this (and we want to be able to test that).
if (!isa<CXXConstructorDecl>(MethodDecl))
initializeFieldsWithValues(ThisLoc);
}
}
}
Expand Down Expand Up @@ -819,6 +826,16 @@ PointerValue &Environment::getOrCreateNullPointerValue(QualType PointeeType) {
return DACtx->getOrCreateNullPointerValue(PointeeType);
}

void Environment::initializeFieldsWithValues(RecordStorageLocation &Loc) {
llvm::DenseSet<QualType> Visited;
int CreatedValuesCount = 0;
initializeFieldsWithValues(Loc, Visited, 0, CreatedValuesCount);
if (CreatedValuesCount > MaxCompositeValueSize) {
llvm::errs() << "Attempting to initialize a huge value of type: "
<< Loc.getType() << '\n';
}
}

void Environment::setValue(const StorageLocation &Loc, Value &Val) {
assert(!isa<RecordValue>(&Val) || &cast<RecordValue>(&Val)->getLoc() == &Loc);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,6 @@ builtinTransferInitializer(const CFGInitializer &Elt,
}
}
assert(Member != nullptr);
assert(MemberLoc != nullptr);

// FIXME: Instead of these case distinctions, we would ideally want to be able
// to simply use `Environment::createObject()` here, the same way that we do
Expand All @@ -422,6 +421,7 @@ builtinTransferInitializer(const CFGInitializer &Elt,

ParentLoc->setChild(*Member, InitExprLoc);
} else if (auto *InitExprVal = Env.getValue(*InitExpr)) {
assert(MemberLoc != nullptr);
if (Member->getType()->isRecordType()) {
auto *InitValStruct = cast<RecordValue>(InitExprVal);
// FIXME: Rather than performing a copy here, we should really be
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ void CodeGenModule::Release() {
llvm::ConstantArray::get(ATy, UsedArray), "__clang_gpu_used_external");
addCompilerUsedGlobal(GV);
}
if (LangOpts.HIP) {
if (LangOpts.HIP && !getLangOpts().OffloadingNewDriver) {
// Emit a unique ID so that host and device binaries from the same
// compilation unit can be associated.
auto *GV = new llvm::GlobalVariable(
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3373,7 +3373,7 @@ class OffloadingActionBuilder final {
const Driver::InputList &Inputs)
: CudaActionBuilderBase(C, Args, Inputs, Action::OFK_HIP) {

DefaultCudaArch = CudaArch::GFX906;
DefaultCudaArch = CudaArch::HIPDefault;

if (Args.hasArg(options::OPT_fhip_emit_relocatable,
options::OPT_fno_hip_emit_relocatable)) {
Expand Down Expand Up @@ -4625,7 +4625,15 @@ Action *Driver::BuildOffloadingActions(Compilation &C,
DDeps.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);
OffloadAction::DeviceDependences DDep;
DDep.add(*A, *TCAndArch->first, TCAndArch->second.data(), Kind);

// Compiling CUDA in non-RDC mode uses the PTX output if available.
for (Action *Input : A->getInputs())
if (Kind == Action::OFK_Cuda && A->getType() == types::TY_Object &&
!Args.hasFlag(options::OPT_fgpu_rdc, options::OPT_fno_gpu_rdc,
false))
DDep.add(*Input, *TCAndArch->first, TCAndArch->second.data(), Kind);
OffloadActions.push_back(C.MakeAction<OffloadAction>(DDep, A->getType()));

++TCAndArch;
}
}
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8895,6 +8895,10 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA,
for (const char *LinkArg : LinkCommand->getArguments())
CmdArgs.push_back(LinkArg);

if (Args.hasFlag(options::OPT_offload_compress,
options::OPT_no_offload_compress, false))
CmdArgs.push_back("--compress");

const char *Exec =
Args.MakeArgString(getToolChain().GetProgramPath("clang-linker-wrapper"));

Expand Down
22 changes: 12 additions & 10 deletions clang/lib/Driver/ToolChains/Cuda.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -503,18 +503,20 @@ void NVPTX::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
Exec, CmdArgs, Inputs, Output));
}

static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) {
bool includePTX = true;
for (Arg *A : Args) {
if (!(A->getOption().matches(options::OPT_cuda_include_ptx_EQ) ||
A->getOption().matches(options::OPT_no_cuda_include_ptx_EQ)))
continue;
static bool shouldIncludePTX(const ArgList &Args, StringRef InputArch) {
// The new driver does not include PTX by default to avoid overhead.
bool includePTX = !Args.hasFlag(options::OPT_offload_new_driver,
options::OPT_no_offload_new_driver, false);
for (Arg *A : Args.filtered(options::OPT_cuda_include_ptx_EQ,
options::OPT_no_cuda_include_ptx_EQ)) {
A->claim();
const StringRef ArchStr = A->getValue();
if (ArchStr == "all" || ArchStr == gpu_arch) {
includePTX = A->getOption().matches(options::OPT_cuda_include_ptx_EQ);
continue;
}
if (A->getOption().matches(options::OPT_cuda_include_ptx_EQ) &&
(ArchStr == "all" || ArchStr == InputArch))
includePTX = true;
else if (A->getOption().matches(options::OPT_no_cuda_include_ptx_EQ) &&
(ArchStr == "all" || ArchStr == InputArch))
includePTX = false;
}
return includePTX;
}
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2556,6 +2556,8 @@ static const auto &getFrontendActionTable() {

{frontend::GenerateModule, OPT_emit_module},
{frontend::GenerateModuleInterface, OPT_emit_module_interface},
{frontend::GenerateReducedModuleInterface,
OPT_emit_reduced_module_interface},
{frontend::GenerateHeaderUnit, OPT_emit_header_unit},
{frontend::GeneratePCH, OPT_emit_pch},
{frontend::GenerateInterfaceStubs, OPT_emit_interface_stubs},
Expand Down Expand Up @@ -4280,6 +4282,7 @@ static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
case frontend::FixIt:
case frontend::GenerateModule:
case frontend::GenerateModuleInterface:
case frontend::GenerateReducedModuleInterface:
case frontend::GenerateHeaderUnit:
case frontend::GeneratePCH:
case frontend::GenerateInterfaceStubs:
Expand Down
37 changes: 31 additions & 6 deletions clang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,12 @@ bool GeneratePCHAction::BeginSourceFileAction(CompilerInstance &CI) {
return true;
}

std::unique_ptr<ASTConsumer>
GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
std::vector<std::unique_ptr<ASTConsumer>>
GenerateModuleAction::CreateMultiplexConsumer(CompilerInstance &CI,
StringRef InFile) {
std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile);
if (!OS)
return nullptr;
return {};

std::string OutputFile = CI.getFrontendOpts().OutputFile;
std::string Sysroot;
Expand All @@ -210,6 +210,17 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
+CI.getFrontendOpts().BuildingImplicitModule));
Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
CI, std::string(InFile), OutputFile, std::move(OS), Buffer));
return Consumers;
}

std::unique_ptr<ASTConsumer>
GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
std::vector<std::unique_ptr<ASTConsumer>> Consumers =
CreateMultiplexConsumer(CI, InFile);
if (Consumers.empty())
return nullptr;

return std::make_unique<MultiplexConsumer>(std::move(Consumers));
}

Expand Down Expand Up @@ -265,7 +276,12 @@ GenerateModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
CI.getHeaderSearchOpts().ModulesSkipHeaderSearchPaths = true;
CI.getHeaderSearchOpts().ModulesSkipPragmaDiagnosticMappings = true;

return GenerateModuleAction::CreateASTConsumer(CI, InFile);
std::vector<std::unique_ptr<ASTConsumer>> Consumers =
CreateMultiplexConsumer(CI, InFile);
if (Consumers.empty())
return nullptr;

return std::make_unique<MultiplexConsumer>(std::move(Consumers));
}

std::unique_ptr<raw_pwrite_stream>
Expand All @@ -274,6 +290,16 @@ GenerateModuleInterfaceAction::CreateOutputFile(CompilerInstance &CI,
return CI.createDefaultOutputFile(/*Binary=*/true, InFile, "pcm");
}

std::unique_ptr<ASTConsumer>
GenerateReducedModuleInterfaceAction::CreateASTConsumer(CompilerInstance &CI,
StringRef InFile) {
auto Buffer = std::make_shared<PCHBuffer>();
return std::make_unique<ReducedBMIGenerator>(
CI.getPreprocessor(), CI.getModuleCache(),
CI.getFrontendOpts().OutputFile, Buffer,
/*IncludeTimestamps=*/+CI.getFrontendOpts().IncludeTimestamps);
}

bool GenerateHeaderUnitAction::BeginSourceFileAction(CompilerInstance &CI) {
if (!CI.getLangOpts().CPlusPlusModules) {
CI.getDiagnostics().Report(diag::err_module_interface_requires_cpp_modules);
Expand Down Expand Up @@ -839,7 +865,6 @@ void DumpModuleInfoAction::ExecuteAction() {

const LangOptions &LO = getCurrentASTUnit().getLangOpts();
if (LO.CPlusPlusModules && !LO.CurrentModule.empty()) {

ASTReader *R = getCurrentASTUnit().getASTReader().get();
unsigned SubModuleCount = R->getTotalNumSubmodules();
serialization::ModuleFile &MF = R->getModuleManager().getPrimaryModule();
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ CreateFrontendBaseAction(CompilerInstance &CI) {
return std::make_unique<GenerateModuleFromModuleMapAction>();
case GenerateModuleInterface:
return std::make_unique<GenerateModuleInterfaceAction>();
case GenerateReducedModuleInterface:
return std::make_unique<GenerateReducedModuleInterfaceAction>();
case GenerateHeaderUnit:
return std::make_unique<GenerateHeaderUnitAction>();
case GeneratePCH: return std::make_unique<GeneratePCHAction>();
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/InstallAPI/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ namespace clang::installapi {
GlobalRecord *FrontendRecordsSlice::addGlobal(
StringRef Name, RecordLinkage Linkage, GlobalRecord::Kind GV,
const clang::AvailabilityInfo Avail, const Decl *D, const HeaderType Access,
SymbolFlags Flags) {
SymbolFlags Flags, bool Inlined) {

auto *GR = llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags);
auto *GR =
llvm::MachO::RecordsSlice::addGlobal(Name, Linkage, GV, Flags, Inlined);
FrontendRecords.insert({GR, FrontendAttrs{Avail, D, Access}});
return GR;
}
Expand Down
78 changes: 78 additions & 0 deletions clang/lib/InstallAPI/Visitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

#include "clang/InstallAPI/Visitor.h"
#include "clang/AST/ParentMapContext.h"
#include "clang/Basic/Linkage.h"
#include "clang/InstallAPI/Frontend.h"
#include "llvm/ADT/SmallString.h"
Expand All @@ -27,6 +28,31 @@ static bool isExported(const NamedDecl *D) {
(LV.getVisibility() == DefaultVisibility);
}

static bool isInlined(const FunctionDecl *D) {
bool HasInlineAttribute = false;
bool NoCXXAttr =
(!D->getASTContext().getLangOpts().CPlusPlus &&
!D->getASTContext().getTargetInfo().getCXXABI().isMicrosoft() &&
!D->hasAttr<DLLExportAttr>());

// Check all redeclarations to find an inline attribute or keyword.
for (const auto *RD : D->redecls()) {
if (!RD->isInlined())
continue;
HasInlineAttribute = true;
if (!(NoCXXAttr || RD->hasAttr<GNUInlineAttr>()))
continue;
if (RD->doesThisDeclarationHaveABody() &&
RD->isInlineDefinitionExternallyVisible())
return false;
}

if (!HasInlineAttribute)
return false;

return true;
}

static SymbolFlags getFlags(bool WeakDef, bool ThreadLocal) {
SymbolFlags Result = SymbolFlags::None;
if (WeakDef)
Expand Down Expand Up @@ -204,4 +230,56 @@ bool InstallAPIVisitor::VisitVarDecl(const VarDecl *D) {
return true;
}

bool InstallAPIVisitor::VisitFunctionDecl(const FunctionDecl *D) {
if (const CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(D)) {
// Skip member function in class templates.
if (M->getParent()->getDescribedClassTemplate() != nullptr)
return true;

// Skip methods in CXX RecordDecls.
for (auto P : D->getASTContext().getParents(*M)) {
if (P.get<CXXRecordDecl>())
return true;
}

// Skip CXX ConstructorDecls and DestructorDecls.
if (isa<CXXConstructorDecl>(M) || isa<CXXDestructorDecl>(M))
return true;
}

// Skip templated functions.
switch (D->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
break;
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:
if (auto *TempInfo = D->getTemplateSpecializationInfo()) {
if (!TempInfo->isExplicitInstantiationOrSpecialization())
return true;
}
break;
case FunctionDecl::TK_FunctionTemplate:
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
return true;
}

auto Access = getAccessForDecl(D);
if (!Access)
return true;
auto Name = getMangledName(D);
const AvailabilityInfo Avail = AvailabilityInfo::createFromDecl(D);
const bool ExplicitInstantiation = D->getTemplateSpecializationKind() ==
TSK_ExplicitInstantiationDeclaration;
const bool WeakDef = ExplicitInstantiation || D->hasAttr<WeakAttr>();
const bool Inlined = isInlined(D);
const RecordLinkage Linkage = (Inlined || !isExported(D))
? RecordLinkage::Internal
: RecordLinkage::Exported;
Ctx.Slice->addGlobal(Name, Linkage, GlobalRecord::Kind::Function, Avail, D,
*Access, getFlags(WeakDef, /*ThreadLocal=*/false),
Inlined);
return true;
}

} // namespace clang::installapi
12 changes: 7 additions & 5 deletions clang/lib/Interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ CreateCI(const llvm::opt::ArgStringList &Argv) {
} // anonymous namespace

llvm::Expected<std::unique_ptr<CompilerInstance>>
IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
IncrementalCompilerBuilder::create(std::string TT,
std::vector<const char *> &ClangArgv) {

// If we don't know ClangArgv0 or the address of main() at this point, try
// to guess it anyway (it's possible on some platforms).
Expand Down Expand Up @@ -162,8 +163,7 @@ IncrementalCompilerBuilder::create(std::vector<const char *> &ClangArgv) {
TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer);

driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0],
llvm::sys::getProcessTriple(), Diags);
driver::Driver Driver(/*MainBinaryName=*/ClangArgv[0], TT, Diags);
Driver.setCheckInputsExist(false); // the input comes from mem buffers
llvm::ArrayRef<const char *> RF = llvm::ArrayRef(ClangArgv);
std::unique_ptr<driver::Compilation> Compilation(Driver.BuildCompilation(RF));
Expand All @@ -185,7 +185,8 @@ IncrementalCompilerBuilder::CreateCpp() {
Argv.push_back("-xc++");
Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());

return IncrementalCompilerBuilder::create(Argv);
std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
return IncrementalCompilerBuilder::create(TT, Argv);
}

llvm::Expected<std::unique_ptr<CompilerInstance>>
Expand Down Expand Up @@ -213,7 +214,8 @@ IncrementalCompilerBuilder::createCuda(bool device) {

Argv.insert(Argv.end(), UserArgs.begin(), UserArgs.end());

return IncrementalCompilerBuilder::create(Argv);
std::string TT = TargetTriple ? *TargetTriple : llvm::sys::getProcessTriple();
return IncrementalCompilerBuilder::create(TT, Argv);
}

llvm::Expected<std::unique_ptr<CompilerInstance>>
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1234,8 +1234,11 @@ void Parser::ParseAvailabilityAttribute(
}
IdentifierLoc *Platform = ParseIdentifierLoc();
if (const IdentifierInfo *const Ident = Platform->Ident) {
// Disallow xrOS for availability attributes.
if (Ident->getName().contains("xrOS") || Ident->getName().contains("xros"))
Diag(Platform->Loc, diag::warn_availability_unknown_platform) << Ident;
// Canonicalize platform name from "macosx" to "macos".
if (Ident->getName() == "macosx")
else if (Ident->getName() == "macosx")
Platform->Ident = PP.getIdentifierInfo("macos");
// Canonicalize platform name from "macosx_app_extension" to
// "macos_app_extension".
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Parse/ParseExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3863,7 +3863,8 @@ std::optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() {
StringRef Platform =
AvailabilityAttr::canonicalizePlatformName(GivenPlatform);

if (AvailabilityAttr::getPrettyPlatformName(Platform).empty()) {
if (AvailabilityAttr::getPrettyPlatformName(Platform).empty() ||
(GivenPlatform.contains("xros") || GivenPlatform.contains("xrOS"))) {
Diag(PlatformIdentifier->Loc,
diag::err_avail_query_unrecognized_platform_name)
<< GivenPlatform;
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaCUDA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,10 @@ bool Sema::CheckCUDACall(SourceLocation Loc, FunctionDecl *Callee) {
if (DiagKind == SemaDiagnosticBuilder::K_Nop) {
// For -fgpu-rdc, keep track of external kernels used by host functions.
if (LangOpts.CUDAIsDevice && LangOpts.GPURelocatableDeviceCode &&
Callee->hasAttr<CUDAGlobalAttr>() && !Callee->isDefined())
Callee->hasAttr<CUDAGlobalAttr>() && !Callee->isDefined() &&
(!Caller || (!Caller->getDescribedFunctionTemplate() &&
getASTContext().GetGVALinkageForFunction(Caller) ==
GVA_StrongExternal)))
getASTContext().CUDAExternalDeviceDeclODRUsedByHost.insert(Callee);
return true;
}
Expand Down
25 changes: 23 additions & 2 deletions clang/lib/Sema/SemaChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19184,8 +19184,24 @@ static bool isLayoutCompatible(ASTContext &C, EnumDecl *ED1, EnumDecl *ED2) {
}

/// Check if two fields are layout-compatible.
/// Can be used on union members, which are exempt from alignment requirement
/// of common initial sequence.
static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
FieldDecl *Field2) {
FieldDecl *Field2,
bool AreUnionMembers = false) {
[[maybe_unused]] const Type *Field1Parent =
Field1->getParent()->getTypeForDecl();
[[maybe_unused]] const Type *Field2Parent =
Field2->getParent()->getTypeForDecl();
assert(((Field1Parent->isStructureOrClassType() &&
Field2Parent->isStructureOrClassType()) ||
(Field1Parent->isUnionType() && Field2Parent->isUnionType())) &&
"Can't evaluate layout compatibility between a struct field and a "
"union field.");
assert(((!AreUnionMembers && Field1Parent->isStructureOrClassType()) ||
(AreUnionMembers && Field1Parent->isUnionType())) &&
"AreUnionMembers should be 'true' for union fields (only).");

if (!isLayoutCompatible(C, Field1->getType(), Field2->getType()))
return false;

Expand All @@ -19204,6 +19220,11 @@ static bool isLayoutCompatible(ASTContext &C, FieldDecl *Field1,
if (Field1->hasAttr<clang::NoUniqueAddressAttr>() ||
Field2->hasAttr<clang::NoUniqueAddressAttr>())
return false;

if (!AreUnionMembers &&
Field1->getMaxAlignment() != Field2->getMaxAlignment())
return false;

return true;
}

Expand Down Expand Up @@ -19265,7 +19286,7 @@ static bool isLayoutCompatibleUnion(ASTContext &C, RecordDecl *RD1,
E = UnmatchedFields.end();

for ( ; I != E; ++I) {
if (isLayoutCompatible(C, Field1, *I)) {
if (isLayoutCompatible(C, Field1, *I, /*IsUnionMember=*/true)) {
bool Result = UnmatchedFields.erase(*I);
(void) Result;
assert(Result);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -586,7 +586,8 @@ bool Sema::addInstantiatedCapturesToScope(

bool Sema::SetupConstraintScope(
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
MultiLevelTemplateArgumentList MLTAL, LocalInstantiationScope &Scope) {
const MultiLevelTemplateArgumentList &MLTAL,
LocalInstantiationScope &Scope) {
if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) {
FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
InstantiatingTemplate Inst(
Expand Down
18 changes: 16 additions & 2 deletions clang/lib/Sema/SemaCoroutine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Overload.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/SmallSet.h"

Expand Down Expand Up @@ -1378,8 +1379,21 @@ bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {
static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc,
SmallVectorImpl<Expr *> &PlacementArgs) {
if (auto *MD = dyn_cast<CXXMethodDecl>(&FD)) {
if (MD->isImplicitObjectMemberFunction() && !isLambdaCallOperator(MD)) {
ExprResult ThisExpr = S.ActOnCXXThis(Loc);
if (MD->isImplicitObjectMemberFunction()) {
ExprResult ThisExpr{};

if (isLambdaCallOperator(MD) && !MD->isStatic()) {
Qualifiers ThisQuals = MD->getMethodQualifiers();
CXXRecordDecl *Record = MD->getParent();

Sema::CXXThisScopeRAII ThisScope(S, Record, ThisQuals,
Record != nullptr);

ThisExpr = S.ActOnCXXThis(Loc, /*ThisRefersToClosureObject=*/true);
} else {
ThisExpr = S.ActOnCXXThis(Loc);
}

if (ThisExpr.isInvalid())
return false;
ThisExpr = S.CreateBuiltinUnaryOp(Loc, UO_Deref, ThisExpr.get());
Expand Down
27 changes: 16 additions & 11 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,9 +1110,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
// unqualified-id followed by a < and name lookup finds either one
// or more functions or finds nothing.
if (!IsFilteredTemplateName)
FilterAcceptableTemplateNames(Result,
/*AllowFunctionTemplates=*/true,
/*AllowDependent=*/true);
FilterAcceptableTemplateNames(Result);

bool IsFunctionTemplate;
bool IsVarTemplate;
Expand All @@ -1122,7 +1120,6 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
Template = Context.getOverloadedTemplateName(Result.begin(),
Result.end());
} else if (!Result.empty()) {
assert(!Result.isUnresolvableResult());
auto *TD = cast<TemplateDecl>(getAsTemplateNameDecl(
*Result.begin(), /*AllowFunctionTemplates=*/true,
/*AllowDependent=*/false));
Expand Down Expand Up @@ -15795,10 +15792,19 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
// captures during transformation of nested lambdas, it is necessary to
// have the LSI properly restored.
if (isGenericLambdaCallOperatorSpecialization(FD)) {
assert(inTemplateInstantiation() &&
"There should be an active template instantiation on the stack "
"when instantiating a generic lambda!");
RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D));
// C++2c 7.5.5.2p17 A member of a closure type shall not be explicitly
// instantiated, explicitly specialized.
if (FD->getTemplateSpecializationInfo()
->isExplicitInstantiationOrSpecialization()) {
Diag(FD->getLocation(), diag::err_lambda_explicit_spec);
FD->setInvalidDecl();
PushFunctionScope();
} else {
assert(inTemplateInstantiation() &&
"There should be an active template instantiation on the stack "
"when instantiating a generic lambda!");
RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D));
}
} else {
// Enter a new function scope
PushFunctionScope();
Expand Down Expand Up @@ -16317,9 +16323,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
}
}

assert(
(FD == getCurFunctionDecl() || getCurLambda()->CallOperator == FD) &&
"Function parsing confused");
assert((FD == getCurFunctionDecl(/*AllowLambdas=*/true)) &&
"Function parsing confused");
} else if (ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(dcl)) {
assert(MD == getCurMethodDecl() && "Method parsing confused");
MD->setBody(Body);
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19218,7 +19218,10 @@ MarkVarDeclODRUsed(ValueDecl *V, SourceLocation Loc, Sema &SemaRef,
// externalize the static device side variable ODR-used by host code.
if (!Var->hasExternalStorage())
SemaRef.getASTContext().CUDADeviceVarODRUsedByHost.insert(Var);
else if (SemaRef.LangOpts.GPURelocatableDeviceCode)
else if (SemaRef.LangOpts.GPURelocatableDeviceCode &&
(!FD || (!FD->getDescribedFunctionTemplate() &&
SemaRef.getASTContext().GetGVALinkageForFunction(FD) ==
GVA_StrongExternal)))
SemaRef.getASTContext().CUDAExternalDeviceDeclODRUsedByHost.insert(Var);
}
}
Expand Down
16 changes: 11 additions & 5 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1414,7 +1414,8 @@ bool Sema::CheckCXXThisCapture(SourceLocation Loc, const bool Explicit,
return false;
}

ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
ExprResult Sema::ActOnCXXThis(SourceLocation Loc,
bool ThisRefersToClosureObject) {
/// C++ 9.3.2: In the body of a non-static member function, the keyword this
/// is a non-lvalue expression whose value is the address of the object for
/// which the function is called.
Expand All @@ -1434,13 +1435,18 @@ ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {
return Diag(Loc, diag::err_invalid_this_use) << 0;
}

return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false);
return BuildCXXThisExpr(Loc, ThisTy, /*IsImplicit=*/false,
ThisRefersToClosureObject);
}

Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type,
bool IsImplicit) {
Expr *Sema::BuildCXXThisExpr(SourceLocation Loc, QualType Type, bool IsImplicit,
bool ThisRefersToClosureObject) {
auto *This = CXXThisExpr::Create(Context, Loc, Type, IsImplicit);
MarkThisReferenced(This);

if (!ThisRefersToClosureObject) {
MarkThisReferenced(This);
}

return This;
}

Expand Down
37 changes: 32 additions & 5 deletions clang/lib/Sema/SemaInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10720,13 +10720,40 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
if (TemplateName.isDependent())
return SubstAutoTypeDependent(TSInfo->getType());

// We can only perform deduction for class templates.
// We can only perform deduction for class templates or alias templates.
auto *Template =
dyn_cast_or_null<ClassTemplateDecl>(TemplateName.getAsTemplateDecl());
TemplateDecl *LookupTemplateDecl = Template;
if (!Template) {
if (auto *AliasTemplate = dyn_cast_or_null<TypeAliasTemplateDecl>(
TemplateName.getAsTemplateDecl())) {
Diag(Kind.getLocation(),
diag::warn_cxx17_compat_ctad_for_alias_templates);
LookupTemplateDecl = AliasTemplate;
auto UnderlyingType = AliasTemplate->getTemplatedDecl()
->getUnderlyingType()
.getCanonicalType();
// C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must be
// of the form
// [typename] [nested-name-specifier] [template] simple-template-id
if (const auto *TST =
UnderlyingType->getAs<TemplateSpecializationType>()) {
Template = dyn_cast_or_null<ClassTemplateDecl>(
TST->getTemplateName().getAsTemplateDecl());
} else if (const auto *RT = UnderlyingType->getAs<RecordType>()) {
// Cases where template arguments in the RHS of the alias are not
// dependent. e.g.
// using AliasFoo = Foo<bool>;
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(
RT->getAsCXXRecordDecl()))
Template = CTSD->getSpecializedTemplate();
}
}
}
if (!Template) {
Diag(Kind.getLocation(),
diag::err_deduced_non_class_template_specialization_type)
<< (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName;
diag::err_deduced_non_class_or_alias_template_specialization_type)
<< (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName;
if (auto *TD = TemplateName.getAsTemplateDecl())
NoteTemplateLocation(*TD);
return QualType();
Expand All @@ -10753,10 +10780,10 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
// template-name, a function template [...]
// - For each deduction-guide, a function or function template [...]
DeclarationNameInfo NameInfo(
Context.DeclarationNames.getCXXDeductionGuideName(Template),
Context.DeclarationNames.getCXXDeductionGuideName(LookupTemplateDecl),
TSInfo->getTypeLoc().getEndLoc());
LookupResult Guides(*this, NameInfo, LookupOrdinaryName);
LookupQualifiedName(Guides, Template->getDeclContext());
LookupQualifiedName(Guides, LookupTemplateDecl->getDeclContext());

// FIXME: Do not diagnose inaccessible deduction guides. The standard isn't
// clear on this, but they're not found by name so access does not apply.
Expand Down
Loading