39 changes: 5 additions & 34 deletions clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,16 @@ AST_MATCHER_P(NamedDecl, usesHeaderFileExtension, FileExtensionsSet,
DefinitionsInHeadersCheck::DefinitionsInHeadersCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context),
UseHeaderFileExtension(Options.get("UseHeaderFileExtension", true)) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void DefinitionsInHeadersCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "UseHeaderFileExtension", UseHeaderFileExtension);
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void DefinitionsInHeadersCheck::registerMatchers(MatchFinder *Finder) {
auto DefinitionMatcher =
anyOf(functionDecl(isDefinition(), unless(isDeleted())),
varDecl(isDefinition()));
if (UseHeaderFileExtension) {
Finder->addMatcher(namedDecl(DefinitionMatcher,
usesHeaderFileExtension(HeaderFileExtensions))
.bind("name-decl"),
this);
} else {
Finder->addMatcher(
namedDecl(DefinitionMatcher,
anyOf(usesHeaderFileExtension(HeaderFileExtensions),
unless(isExpansionInMainFile())))
.bind("name-decl"),
this);
}
Finder->addMatcher(namedDecl(DefinitionMatcher,
usesHeaderFileExtension(HeaderFileExtensions))
.bind("name-decl"),
this);
}

void DefinitionsInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
Expand Down
9 changes: 0 additions & 9 deletions clang-tools-extra/clang-tidy/misc/DefinitionsInHeadersCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@ namespace clang::tidy::misc {
/// The check supports these options:
/// - `UseHeaderFileExtension`: Whether to use file extension to distinguish
/// header files. True by default.
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/definitions-in-headers.html
Expand All @@ -35,13 +29,10 @@ class DefinitionsInHeadersCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus11;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
const bool UseHeaderFileExtension;
StringRef RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
17 changes: 2 additions & 15 deletions clang-tools-extra/clang-tidy/misc/UnusedUsingDeclsCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,8 @@ static bool shouldCheckDecl(const Decl *TargetDecl) {

UnusedUsingDeclsCheck::UnusedUsingDeclsCheck(StringRef Name,
ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void UnusedUsingDeclsCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(usingDecl(isExpansionInMainFile()).bind("using"), this);
Expand Down
22 changes: 2 additions & 20 deletions clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,8 @@ AST_MATCHER(VarDecl, isStaticDataMember) { return Node.isStaticDataMember(); }

UseAnonymousNamespaceCheck::UseAnonymousNamespaceCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions =
HeaderFileExtensionsOption.value_or(utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(RawStringHeaderFileExtensions,
HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}

void UseAnonymousNamespaceCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void UseAnonymousNamespaceCheck::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
Expand Down
10 changes: 0 additions & 10 deletions clang-tools-extra/clang-tidy/misc/UseAnonymousNamespaceCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ namespace clang::tidy::misc {
/// Warns when using 'static' functions or variables at global scope, and
/// suggests moving them to an anonymous namespace.
///
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
///
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/misc/use-anonymous-namespace.html
class UseAnonymousNamespaceCheck : public ClangTidyCheck {
Expand All @@ -33,12 +25,10 @@ class UseAnonymousNamespaceCheck : public ClangTidyCheck {
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus;
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;

private:
StringRef RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ std::string IdentifierNamingCheck::HungarianNotation::getEnumPrefix(
const auto *ED = cast<EnumDecl>(ECD->getDeclContext());

std::string Name = ED->getName().str();
if (std::string::npos != Name.find("enum")) {
if (StringRef(Name).contains("enum")) {
Name = Name.substr(strlen("enum"), Name.length() - strlen("enum"));
Name = Name.erase(0, Name.find_first_not_of(' '));
}
Expand Down
4 changes: 0 additions & 4 deletions clang-tools-extra/clang-tidy/utils/HeaderGuard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,6 @@ class HeaderGuardPPCallbacks : public PPCallbacks {
};
} // namespace

void HeaderGuardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "HeaderFileExtensions", RawStringHeaderFileExtensions);
}

void HeaderGuardCheck::registerPPCallbacks(const SourceManager &SM,
Preprocessor *PP,
Preprocessor *ModuleExpanderPP) {
Expand Down
27 changes: 3 additions & 24 deletions clang-tools-extra/clang-tidy/utils/HeaderGuard.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,12 @@
namespace clang::tidy::utils {

/// Finds and fixes header guards.
/// The check supports these options:
/// - `HeaderFileExtensions`: a semicolon-separated list of filename
/// extensions of header files (The filename extension should not contain
/// "." prefix). ";h;hh;hpp;hxx" by default.
///
/// For extension-less header files, using an empty string or leaving an
/// empty string between ";" if there are other filename extensions.
class HeaderGuardCheck : public ClangTidyCheck {
public:
HeaderGuardCheck(StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
std::optional<StringRef> HeaderFileExtensionsOption =
Options.get("HeaderFileExtensions");
RawStringHeaderFileExtensions = HeaderFileExtensionsOption.value_or(
utils::defaultHeaderFileExtensions());
if (HeaderFileExtensionsOption) {
if (!utils::parseFileExtensions(
RawStringHeaderFileExtensions, HeaderFileExtensions,
utils::defaultFileExtensionDelimiters())) {
this->configurationDiag("Invalid header file extension: '%0'")
<< RawStringHeaderFileExtensions;
}
} else
HeaderFileExtensions = Context->getHeaderFileExtensions();
}
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
: ClangTidyCheck(Name, Context),
HeaderFileExtensions(Context->getHeaderFileExtensions()) {}

void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP,
Preprocessor *ModuleExpanderPP) override;

Expand All @@ -65,7 +45,6 @@ class HeaderGuardCheck : public ClangTidyCheck {
StringRef OldGuard = StringRef()) = 0;

private:
std::string RawStringHeaderFileExtensions;
FileExtensionsSet HeaderFileExtensions;
};

Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/SemanticHighlighting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ std::optional<HighlightingKind> kindForDecl(const NamedDecl *D,
if (auto *OMD = dyn_cast<ObjCMethodDecl>(D))
return OMD->isClassMethod() ? HighlightingKind::StaticMethod
: HighlightingKind::Method;
if (isa<FieldDecl, ObjCPropertyDecl>(D))
if (isa<FieldDecl, IndirectFieldDecl, ObjCPropertyDecl>(D))
return HighlightingKind::Field;
if (isa<EnumDecl>(D))
return HighlightingKind::Enum;
Expand Down
16 changes: 16 additions & 0 deletions clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,22 @@ sizeof...($TemplateParameter[[Elements]]);
using $Class[[Y]]$Bracket[[<]]0$Bracket[[>]]::$Unknown_dependentName[[xxx]];
};
};
)cpp",
// Heuristically resolved IndirectFieldDecl
R"cpp(
template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]
struct $Class_def[[Base]] {
struct {
int $Field_decl[[waldo]];
};
};
template $Bracket[[<]]typename $TemplateParameter_def[[T]]$Bracket[[>]]
struct $Class_def[[Derived]] : $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]] {
using $Class[[Base]]$Bracket[[<]]$TemplateParameter[[T]]$Bracket[[>]]::$Field_dependentName[[waldo]];
void $Method_def[[foo]]() {
$Field_dependentName[[waldo]];
}
};
)cpp"};
for (const auto &TestCase : TestCases)
// Mask off scope modifiers to keep the tests manageable.
Expand Down
38 changes: 38 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ New check aliases
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^

- Improved :doc:`bugprone-suspicious-include
<clang-tidy/checks/bugprone/suspicious-include>` check by replacing the local
options `HeaderFileExtensions` and `ImplementationFileExtensions` by the
global options of the same name.

- Cleaned up :doc:`cppcoreguidelines-prefer-member-initializer
<clang-tidy/checks/cppcoreguidelines/prefer-member-initializer>`
by removing enforcement of rule `C.48
Expand All @@ -114,6 +119,32 @@ Changes in existing checks
by :doc:`cppcoreguidelines-use-default-member-init
<clang-tidy/checks/cppcoreguidelines/use-default-member-init>`.

- Improved :doc:`google-build-namespaces
<clang-tidy/checks/google/build-namespaces>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`google-global-names-in-headers
<clang-tidy/checks/google/global-names-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`llvm-header-guard
<clang-tidy/checks/llvm/header-guard>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`misc-definitions-in-headers
<clang-tidy/checks/misc/definitions-in-headers>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.
Additionally, the option `UseHeaderFileExtensions` is removed, so that the
check uses the `HeaderFileExtensions` option unconditionally.

- Improved :doc:`misc-unused-using-decls
<clang-tidy/checks/misc/unused-using-decls>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`misc-use-anonymous-namespace
<clang-tidy/checks/misc/use-anonymous-namespace>` check by replacing the local
option `HeaderFileExtensions` by the global option of the same name.

- Improved :doc:`modernize-avoid-c-arrays
<clang-tidy/checks/modernize/avoid-c-arrays>` check by introducing the new
`AllowStringArrays` option, enabling the exclusion of array types with deduced
Expand All @@ -122,9 +153,16 @@ Changes in existing checks
Removed checks
^^^^^^^^^^^^^^

Miscellaneous
^^^^^^^^^^^^^

- Removed `cert-dcl21-cpp`, which was deprecated since :program:`clang-tidy` 17,
since the rule DCL21-CPP has been removed from the CERT guidelines.

- Fixed incorrect formatting in ``clang-apply-repalcements`` when no ``--format``
option is specified. Now ``clang-apply-replacements`` applies formatting only with
the option.

Improvements to include-fixer
-----------------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,3 @@ Examples:
#include "Pterodactyl.h" // OK, .h files tend not to have definitions.
#include "Velociraptor.cpp" // Warning, filename is suspicious.
#include_next <stdio.c> // Warning, filename is suspicious.

Options
-------
.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

Default value: ``";h;hh;hpp;hxx"``
A semicolon-separated list of filename extensions of header files (the
filename extensions should not contain a "." prefix). For extension-less
header files, use an empty string or leave an empty string between ";"
if there are other filename extensions.

.. option:: ImplementationFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`ImplementationFileExtensions`.

Default value: ``"c;cc;cpp;cxx"``
Likewise, a semicolon-separated list of filename extensions of
implementation files.
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,3 @@ Finds anonymous namespaces in headers.
https://google.github.io/styleguide/cppguide.html#Namespaces

Corresponding cpplint.py check name: `build/namespaces`.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,3 @@ Flag global namespace pollution in header files. Right now it only triggers on

The relevant style guide section is
https://google.github.io/styleguide/cppguide.html#Namespaces.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not contain "." prefix). Default is "h".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).
15 changes: 0 additions & 15 deletions clang-tools-extra/docs/clang-tidy/checks/llvm/header-guard.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,3 @@ llvm-header-guard
=================

Finds and fixes header guards that do not adhere to LLVM style.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).
Original file line number Diff line number Diff line change
Expand Up @@ -92,27 +92,3 @@ When :program:`clang-tidy` is invoked with the `--fix-notes` option, this check
provides fixes that automatically add the ``inline`` keyword to discovered
functions. Please note that the addition of the ``inline`` keyword to variables
is not currently supported by this check.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A comma-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For header files without an extension, use an empty string (if there are no
other desired extensions) or leave an empty element in the list. E.g.,
"h,hh,hpp,hxx," (note the trailing comma).

.. option:: UseHeaderFileExtension

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. The check will unconditionally use the global option
`HeaderFileExtensions`.

When `true`, the check will use the file extension to distinguish header
files. Default is `true`.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Finds unused ``using`` declarations.

Unused ``using``` declarations in header files will not be diagnosed since these
using declarations are part of the header's public API. Allowed header file
extensions can be configured via the `HeaderFileExtensions` option (see below).
extensions can be configured via the global option `HeaderFileExtensions`.

Example:

Expand All @@ -16,17 +16,3 @@ Example:
// main.cpp
namespace n { class C; }
using n::C; // Never actually used.

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A semicolon-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is "h,hh,hpp,hxx".
For extension-less header files, use an empty string or leave an
empty string between "," if there are other filename extensions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The following uses of ``static`` will *not* be diagnosed:

* Functions or variables in header files, since anonymous namespaces in headers
is considered an antipattern. Allowed header file extensions can be configured
via the `HeaderFileExtensions` option (see below).
via the global option `HeaderFileExtensions`.
* ``const`` or ``constexpr`` variables, since they already have implicit internal
linkage in C++.

Expand All @@ -33,18 +33,4 @@ Examples:
int x;
} // namespace

Options
-------

.. option:: HeaderFileExtensions

Note: this option is deprecated, it will be removed in :program:`clang-tidy`
version 19. Please use the global configuration option
`HeaderFileExtensions`.

A semicolon-separated list of filename extensions of header files (the filename
extensions should not include "." prefix). Default is ";h;hh;hpp;hxx".
For extension-less header files, using an empty string or leaving an
empty string between ";" if there are other filename extensions.

[1] `Undeprecating static <https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1012>`_
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <string>
// CHECK: #include <string>
// CHECK-NEXT: #include <memory>
// CHECK-NEXT: #include "bar.h"
#include <memory>
#include "foo.h"
#include "bar.h"

void foo() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
MainSourceFile: no.cpp
Diagnostics:
- DiagnosticName: test-header-format
DiagnosticMessage:
Message: Fix
FilePath: $(path)/no.cpp
FileOffset: 36
Replacements:
- FilePath: $(path)/no.cpp
Offset: 36
Length: 17
ReplacementText: ""
...
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <string>
// CHECK: #include "bar.h"
// CHECK-NEXT: #include <memory>
// CHECK-NEXT: #include <string>
#include <memory>
#include "foo.h"
#include "bar.h"

void foo() {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
MainSourceFile: yes.cpp
Diagnostics:
- DiagnosticName: test-header-format
DiagnosticMessage:
Message: Fix
FilePath: $(path)/yes.cpp
FileOffset: 36
Replacements:
- FilePath: $(path)/yes.cpp
Offset: 36
Length: 17
ReplacementText: ""
...
13 changes: 13 additions & 0 deletions clang-tools-extra/test/clang-apply-replacements/format-header.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: mkdir -p %T/Inputs/format_header_yes
// RUN: mkdir -p %T/Inputs/format_header_no
//
//
// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/yes.cpp > %T/Inputs/format_header_yes/yes.cpp
// RUN: grep -Ev "// *[A-Z-]+:" %S/Inputs/format_header/no.cpp > %T/Inputs/format_header_no/no.cpp
// RUN: sed "s#\$(path)#%/T/Inputs/format_header_yes#" %S/Inputs/format_header/yes.yaml > %T/Inputs/format_header_yes/yes.yaml
// RUN: sed "s#\$(path)#%/T/Inputs/format_header_no#" %S/Inputs/format_header/no.yaml > %T/Inputs/format_header_no/no.yaml
// RUN: clang-apply-replacements -format -style="{BasedOnStyle: llvm, SortIncludes: CaseSensitive}" %T/Inputs/format_header_yes
// RUN: clang-apply-replacements %T/Inputs/format_header_no
// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format_header_yes/yes.cpp %S/Inputs/format_header/yes.cpp
// RUN: FileCheck --strict-whitespace -input-file=%T/Inputs/format_header_no/no.cpp %S/Inputs/format_header/no.cpp
//
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64-unknown-unknown -x c++ -fsigned-char

// RUN: %check_clang_tidy -std=c99 %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64-unknown-unknown -x c -funsigned-char
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64-unknown-unknown-x c++ -funsigned-char
// RUN: %check_clang_tidy %s bugprone-implicit-widening-of-multiplication-result %t -- -- -target x86_64 c++ -funsigned-char

long t0(char a, char b) {
return a * b;
Expand Down
30 changes: 28 additions & 2 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1537,8 +1537,10 @@ the configuration (without a prefix: ``Auto``).
Possible values:

* ``RTBS_None`` (in configuration: ``None``)
Break after return type automatically.
``PenaltyReturnTypeOnItsOwnLine`` is taken into account.
This is **deprecated**. See ``Automatic`` below.

* ``RTBS_Automatic`` (in configuration: ``Automatic``)
Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``.

.. code-block:: c++

Expand All @@ -1547,6 +1549,22 @@ the configuration (without a prefix: ``Auto``).
};
int f();
int f() { return 1; }
int
LongName::AnotherLongName();

* ``RTBS_ExceptShortType`` (in configuration: ``ExceptShortType``)
Same as ``Automatic`` above, except that there is no break after short
return types.

.. code-block:: c++

class A {
int f() { return 0; };
};
int f();
int f() { return 1; }
int LongName::
AnotherLongName();

* ``RTBS_All`` (in configuration: ``All``)
Always break after the return type.
Expand All @@ -1565,6 +1583,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();

* ``RTBS_TopLevel`` (in configuration: ``TopLevel``)
Always break after the return types of top-level functions.
Expand All @@ -1580,6 +1600,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();

* ``RTBS_AllDefinitions`` (in configuration: ``AllDefinitions``)
Always break after the return type of function definitions.
Expand All @@ -1597,6 +1619,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();

* ``RTBS_TopLevelDefinitions`` (in configuration: ``TopLevelDefinitions``)
Always break after the return type of top-level definitions.
Expand All @@ -1611,6 +1635,8 @@ the configuration (without a prefix: ``Auto``).
f() {
return 1;
}
int
LongName::AnotherLongName();



Expand Down
1 change: 1 addition & 0 deletions clang/docs/LanguageExtensions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1569,6 +1569,7 @@ The following type trait primitives are supported by Clang. Those traits marked
* ``__is_const`` (C++, Embarcadero)
* ``__is_constructible`` (C++, MSVC 2013)
* ``__is_convertible`` (C++, Embarcadero)
* ``__is_nothrow_convertible`` (C++, GNU)
* ``__is_convertible_to`` (Microsoft):
Synonym for ``__is_convertible``.
* ``__is_destructible`` (C++, MSVC 2013)
Expand Down
13 changes: 13 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ Improvements to Clang's diagnostics
prints.

- Clang now diagnoses member template declarations with multiple declarators.
- Clang now diagnoses use of the ``template`` keyword after declarative nested name specifiers.

Improvements to Clang's time-trace
----------------------------------
Expand All @@ -160,6 +161,9 @@ Bug Fixes in This Version

- Fixed missing warnings when doing bool-like conversions in C23 (`#79435 <https://github.com/llvm/llvm-project/issues/79435>`_).

- Clang now accepts qualified partial/explicit specializations of variable templates that
are not nominable in the lookup context of the specialization.

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

Expand All @@ -186,8 +190,17 @@ Bug Fixes to C++ Support
- Fix for crash when using a erroneous type in a return statement.
Fixes (`#63244 <https://github.com/llvm/llvm-project/issues/63244>`_)
and (`#79745 <https://github.com/llvm/llvm-project/issues/79745>`_)
- Fixed an out-of-bounds error caused by building a recovery expression for ill-formed
function calls while substituting into constraints.
(`#58548 <https://github.com/llvm/llvm-project/issues/58548>`_)
- Fix incorrect code generation caused by the object argument of ``static operator()`` and ``static operator[]`` calls not being evaluated.
Fixes (`#67976 <https://github.com/llvm/llvm-project/issues/67976>`_)
- Fix crash and diagnostic with const qualified member operator new.
Fixes (`#79748 <https://github.com/llvm/llvm-project/issues/79748>`_)
- Fix a crash when specializing an out-of-line member function with a default
parameter where we did an incorrect specialization of the initialization of
the default parameter.
Fixes (`#68490 <https://github.com/llvm/llvm-project/issues/68490>`_)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
5 changes: 4 additions & 1 deletion clang/include/clang/AST/TypeLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,9 @@ class TypeLoc {
/// pointer types, but not through decltype or typedefs.
AutoTypeLoc getContainedAutoTypeLoc() const;

/// Get the SourceLocation of the template keyword (if any).
SourceLocation getTemplateKeywordLoc() const;

/// Initializes this to state that every location in this
/// type is the given location.
///
Expand Down Expand Up @@ -1691,7 +1694,7 @@ class TemplateSpecializationTypeLoc :
}

void initializeLocal(ASTContext &Context, SourceLocation Loc) {
setTemplateKeywordLoc(Loc);
setTemplateKeywordLoc(SourceLocation());
setTemplateNameLoc(Loc);
setLAngleLoc(Loc);
setRAngleLoc(Loc);
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ def err_drv_hipspv_no_hip_path : Error<
"'--hip-path' must be specified when offloading to "
"SPIR-V%select{| unless %1 is given}0.">;

// TODO: Remove when COV6 is fully supported by ROCm.
def warn_drv_amdgpu_cov6: Warning<
"code object v6 is still in development and not ready for production use yet;"
" use at your own risk">;
def err_drv_undetermined_gpu_arch : Error<
"cannot determine %0 architecture: %1; consider passing it via "
"'%2'">;
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -8247,6 +8247,9 @@ def err_invalid_declarator_in_block : Error<
"definition or redeclaration of %0 not allowed inside a block">;
def err_not_tag_in_scope : Error<
"no %select{struct|interface|union|class|enum}0 named %1 in %2">;
def ext_template_after_declarative_nns : ExtWarn<
"'template' cannot be used after a declarative nested name specifier">,
InGroup<DiagGroup<"template-in-declaration-name">>;

def err_no_typeid_with_fno_rtti : Error<
"use of typeid requires -frtti">;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/TokenKinds.def
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,7 @@ TYPE_TRAIT_1(__is_unsigned, IsUnsigned, KEYCXX)
// Embarcadero Binary Type Traits
TYPE_TRAIT_2(__is_same, IsSame, KEYCXX)
TYPE_TRAIT_2(__is_convertible, IsConvertible, KEYCXX)
TYPE_TRAIT_2(__is_nothrow_convertible, IsNothrowConvertible, KEYCXX)
ARRAY_TYPE_TRAIT(__array_rank, ArrayRank, KEYCXX)
ARRAY_TYPE_TRAIT(__array_extent, ArrayExtent, KEYCXX)
// Name for GCC 6 compatibility.
Expand Down
31 changes: 31 additions & 0 deletions clang/include/clang/Basic/riscv_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -1730,12 +1730,28 @@ let ManualCodegen = [{
defm vfwnmacc : RVVFloatingWidenTerBuiltinSetRoundingMode;
defm vfwmsac : RVVFloatingWidenTerBuiltinSetRoundingMode;
defm vfwnmsac : RVVFloatingWidenTerBuiltinSetRoundingMode;

// Vector BF16 widening multiply-accumulate
let Log2LMUL = [-2, -1, 0, 1, 2],
RequiredFeatures = ["Zvfbfwma"],
HasMaskedOffOperand = false in
defm vfwmaccbf16 : RVVOutOp1Op2BuiltinSet<"vfwmaccbf16", "y",
[["vv", "Fw", "FwFwvvu"],
["vf", "Fw", "FwFwevu"]]>;
}
// 13.7. Vector Widening Floating-Point Fused Multiply-Add Instructions
defm vfwmacc : RVVFloatingWidenTerBuiltinSet;
defm vfwnmacc : RVVFloatingWidenTerBuiltinSet;
defm vfwmsac : RVVFloatingWidenTerBuiltinSet;
defm vfwnmsac : RVVFloatingWidenTerBuiltinSet;

// Vector BF16 widening multiply-accumulate
let Log2LMUL = [-2, -1, 0, 1, 2],
RequiredFeatures = ["Zvfbfwma"],
HasMaskedOffOperand = false in
defm vfwmaccbf16 : RVVOutOp1Op2BuiltinSet<"vfwmaccbf16", "y",
[["vv", "Fw", "FwFwvv"],
["vf", "Fw", "FwFwev"]]>;
}

}
Expand Down Expand Up @@ -1883,6 +1899,11 @@ let Log2LMUL = [-3, -2, -1, 0, 1, 2] in {
def vfncvt_rtz_x_f_w : RVVConvToNarrowingSignedBuiltin<"vfncvt_rtz_x">;
def vfncvt_rod_f_f_w : RVVConvBuiltin<"v", "vw", "xf", "vfncvt_rod_f">;
}

// Zvfbfmin - Vector convert BF16 to FP32
let Log2LMUL = [-2, -1, 0, 1, 2] in
def vfwcvtbf16_f_f_v : RVVConvBuiltin<"Fw", "Fwv", "y", "vfwcvtbf16_f">;

let ManualCodegen = [{
{
// LLVM intrinsic
Expand Down Expand Up @@ -1970,6 +1991,11 @@ let ManualCodegen = [{
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vwu"]]>;
}
}

// Zvfbfmin - Vector convert FP32 to BF16
let Log2LMUL = [-2, -1, 0, 1, 2],
OverloadedName = "vfncvtbf16_f" in
defm : RVVConvBuiltinSet<"vfncvtbf16_f_f_w", "y", [["v", "vFwu"]]>;
}

// 13.17. Single-Width Floating-Point/Integer Type-Convert Instructions
Expand Down Expand Up @@ -2015,6 +2041,11 @@ let ManualCodegen = [{
defm : RVVConvBuiltinSet<"vfncvt_f_f_w", "x", [["v", "vw"]]>;
}
}

// Zvfbfmin - Vector convert FP32 to BF16
let Log2LMUL = [-2, -1, 0, 1, 2],
OverloadedName = "vfncvtbf16_f" in
defm : RVVConvBuiltinSet<"vfncvtbf16_f_f_w", "y", [["v", "vFw"]]>;
}
}

Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4801,9 +4801,9 @@ defm amdgpu_ieee : BoolOption<"m", "amdgpu-ieee",
def mcode_object_version_EQ : Joined<["-"], "mcode-object-version=">, Group<m_Group>,
HelpText<"Specify code object ABI version. Defaults to 5. (AMDGPU only)">,
Visibility<[ClangOption, FlangOption, CC1Option, FC1Option]>,
Values<"none,4,5">,
Values<"none,4,5,6">,
NormalizedValuesScope<"llvm::CodeObjectVersionKind">,
NormalizedValues<["COV_None", "COV_4", "COV_5"]>,
NormalizedValues<["COV_None", "COV_4", "COV_5", "COV_6"]>,
MarshallingInfoEnum<TargetOpts<"CodeObjectVersion">, "COV_5">;

defm cumode : SimpleMFlag<"cumode",
Expand Down
29 changes: 26 additions & 3 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -914,16 +914,31 @@ struct FormatStyle {
/// Different ways to break after the function definition or
/// declaration return type.
enum ReturnTypeBreakingStyle : int8_t {
/// Break after return type automatically.
/// ``PenaltyReturnTypeOnItsOwnLine`` is taken into account.
/// This is **deprecated**. See ``Automatic`` below.
RTBS_None,
/// Break after return type based on ``PenaltyReturnTypeOnItsOwnLine``.
/// \code
/// class A {
/// int f() { return 0; };
/// };
/// int f();
/// int f() { return 1; }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_None,
RTBS_Automatic,
/// Same as ``Automatic`` above, except that there is no break after short
/// return types.
/// \code
/// class A {
/// int f() { return 0; };
/// };
/// int f();
/// int f() { return 1; }
/// int LongName::
/// AnotherLongName();
/// \endcode
RTBS_ExceptShortType,
/// Always break after the return type.
/// \code
/// class A {
Expand All @@ -938,6 +953,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_All,
/// Always break after the return types of top-level functions.
Expand All @@ -951,6 +968,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_TopLevel,
/// Always break after the return type of function definitions.
Expand All @@ -966,6 +985,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_AllDefinitions,
/// Always break after the return type of top-level definitions.
Expand All @@ -978,6 +999,8 @@ struct FormatStyle {
/// f() {
/// return 1;
/// }
/// int
/// LongName::AnotherLongName();
/// \endcode
RTBS_TopLevelDefinitions,
};
Expand Down
5 changes: 3 additions & 2 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -2960,7 +2960,8 @@ class Sema final {
bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info);
bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name, SourceLocation Loc,
bool IsTemplateId);
TemplateIdAnnotation *TemplateId,
bool IsMemberSpecialization);
void
diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals,
SourceLocation FallbackLoc,
Expand Down Expand Up @@ -8456,7 +8457,7 @@ class Sema final {
SourceLocation RAngleLoc);

DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI,
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization);

Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Support/RISCVVIntrinsicUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,8 @@ enum RVVRequire : uint32_t {
RVV_REQ_Zvknhb = 1 << 13,
RVV_REQ_Zvksed = 1 << 14,
RVV_REQ_Zvksh = 1 << 15,
RVV_REQ_Experimental = 1 << 16,
RVV_REQ_Zvfbfwma = 1 << 16,
RVV_REQ_Experimental = 1 << 17,

LLVM_MARK_AS_BITMASK_ENUM(RVV_REQ_Experimental)
};
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/AST/TypeLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,3 +738,12 @@ AutoTypeLoc TypeLoc::getContainedAutoTypeLoc() const {
return AutoTypeLoc();
return Res.getAs<AutoTypeLoc>();
}

SourceLocation TypeLoc::getTemplateKeywordLoc() const {
if (const auto TSTL = getAsAdjusted<TemplateSpecializationTypeLoc>())
return TSTL.getTemplateKeywordLoc();
if (const auto DTSTL =
getAsAdjusted<DependentTemplateSpecializationTypeLoc>())
return DTSTL.getTemplateKeywordLoc();
return SourceLocation();
}
6 changes: 3 additions & 3 deletions clang/lib/AST/TypePrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1195,10 +1195,10 @@ void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {

void TypePrinter::printPackIndexingBefore(const PackIndexingType *T,
raw_ostream &OS) {
if (T->isInstantiationDependentType())
OS << T->getPattern() << "...[" << T->getIndexExpr() << "]";
else
if (T->hasSelectedType())
OS << T->getSelectedType();
else
OS << T->getPattern() << "...[" << T->getIndexExpr() << "]";
spaceBeforePlaceHolder(OS);
}

Expand Down
51 changes: 47 additions & 4 deletions clang/lib/Analysis/ReachableCode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
Expand Down Expand Up @@ -453,26 +454,68 @@ bool DeadCodeScan::isDeadCodeRoot(const clang::CFGBlock *Block) {
return isDeadRoot;
}

static bool isValidDeadStmt(const Stmt *S) {
// Check if the given `DeadStmt` is a coroutine statement and is a substmt of
// the coroutine statement. `Block` is the CFGBlock containing the `DeadStmt`.
static bool isInCoroutineStmt(const Stmt *DeadStmt, const CFGBlock *Block) {
// The coroutine statement, co_return, co_await, or co_yield.
const Stmt *CoroStmt = nullptr;
// Find the first coroutine statement after the DeadStmt in the block.
bool AfterDeadStmt = false;
for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I != E;
++I)
if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
const Stmt *S = CS->getStmt();
if (S == DeadStmt)
AfterDeadStmt = true;
if (AfterDeadStmt &&
// For simplicity, we only check simple coroutine statements.
(llvm::isa<CoreturnStmt>(S) || llvm::isa<CoroutineSuspendExpr>(S))) {
CoroStmt = S;
break;
}
}
if (!CoroStmt)
return false;
struct Checker : RecursiveASTVisitor<Checker> {
const Stmt *DeadStmt;
bool CoroutineSubStmt = false;
Checker(const Stmt *S) : DeadStmt(S) {}
bool VisitStmt(const Stmt *S) {
if (S == DeadStmt)
CoroutineSubStmt = true;
return true;
}
// Statements captured in the CFG can be implicit.
bool shouldVisitImplicitCode() const { return true; }
};
Checker checker(DeadStmt);
checker.TraverseStmt(const_cast<Stmt *>(CoroStmt));
return checker.CoroutineSubStmt;
}

static bool isValidDeadStmt(const Stmt *S, const clang::CFGBlock *Block) {
if (S->getBeginLoc().isInvalid())
return false;
if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(S))
return BO->getOpcode() != BO_Comma;
return true;
// Coroutine statements are never considered dead statements, because removing
// them may change the function semantic if it is the only coroutine statement
// of the coroutine.
return !isInCoroutineStmt(S, Block);
}

const Stmt *DeadCodeScan::findDeadCode(const clang::CFGBlock *Block) {
for (CFGBlock::const_iterator I = Block->begin(), E = Block->end(); I!=E; ++I)
if (std::optional<CFGStmt> CS = I->getAs<CFGStmt>()) {
const Stmt *S = CS->getStmt();
if (isValidDeadStmt(S))
if (isValidDeadStmt(S, Block))
return S;
}

CFGTerminator T = Block->getTerminator();
if (T.isStmtBranch()) {
const Stmt *S = T.getStmt();
if (S && isValidDeadStmt(S))
if (S && isValidDeadStmt(S, Block))
return S;
}

Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Basic/Sarif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ static std::string percentEncodeURICharacter(char C) {
// should be written out directly. Otherwise, percent
// encode the character and write that out instead of the
// reserved character.
if (llvm::isAlnum(C) ||
StringRef::npos != StringRef("-._~:@!$&'()*+,;=").find(C))
if (llvm::isAlnum(C) || StringRef("-._~:@!$&'()*+,;=").contains(C))
return std::string(&C, 1);
return "%" + llvm::toHex(StringRef(&C, 1));
}
Expand Down
8 changes: 2 additions & 6 deletions clang/lib/Basic/Targets/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
return true;
}

bool HasLeftParen = false;
if (S.consume_front("{"))
HasLeftParen = true;
bool HasLeftParen = S.consume_front("{");
if (S.empty())
return false;
if (S.front() != 'v' && S.front() != 's' && S.front() != 'a') {
Expand All @@ -196,9 +194,7 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUTargetInfo final : public TargetInfo {
Name = S.data() - 1;
return true;
}
bool HasLeftBracket = false;
if (S.consume_front("["))
HasLeftBracket = true;
bool HasLeftBracket = S.consume_front("[");
unsigned long long N;
if (S.empty() || consumeUnsignedInteger(S, 10, N))
return false;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Basic/Targets/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ bool X86TargetInfo::initFeatureMap(
if (Feature.substr(1, 6) == "avx10.") {
if (Feature[0] == '+') {
HasAVX10 = true;
if (Feature.substr(Feature.size() - 3, 3) == "512")
if (StringRef(Feature).ends_with("512"))
HasAVX10_512 = true;
LastAVX10 = Feature;
} else if (HasAVX10 && Feature == "-avx10.1-256") {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Basic/Targets/X86.h
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,7 @@ class LLVM_LIBRARY_VISIBILITY MCUX86_32TargetInfo : public X86_32TargetInfo {
MCUX86_32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: X86_32TargetInfo(Triple, Opts) {
LongDoubleWidth = 64;
DefaultAlignForAttributeAligned = 32;
LongDoubleFormat = &llvm::APFloat::IEEEdouble();
resetDataLayout("e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:32-"
"f64:32-f128:32-n8:16:32-a:0:32-S32");
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17756,9 +17756,9 @@ Value *EmitAMDGPUImplicitArgPtr(CodeGenFunction &CGF) {
// \p Index is 0, 1, and 2 for x, y, and z dimension, respectively.
/// Emit code based on Code Object ABI version.
/// COV_4 : Emit code to use dispatch ptr
/// COV_5 : Emit code to use implicitarg ptr
/// COV_5+ : Emit code to use implicitarg ptr
/// COV_NONE : Emit code to load a global variable "__oclc_ABI_version"
/// and use its value for COV_4 or COV_5 approach. It is used for
/// and use its value for COV_4 or COV_5+ approach. It is used for
/// compiling device libraries in an ABI-agnostic way.
///
/// Note: "__oclc_ABI_version" is supposed to be emitted and intialized by
Expand Down Expand Up @@ -17801,7 +17801,7 @@ Value *EmitAMDGPUWorkGroupSize(CodeGenFunction &CGF, unsigned Index) {
Address(Result, CGF.Int16Ty, CharUnits::fromQuantity(2)));
} else {
Value *GEP = nullptr;
if (Cov == CodeObjectVersionKind::COV_5) {
if (Cov >= CodeObjectVersionKind::COV_5) {
// Indexing the implicit kernarg segment.
GEP = CGF.Builder.CreateConstGEP1_32(
CGF.Int8Ty, EmitAMDGPUImplicitArgPtr(CGF), 12 + Index * 2);
Expand Down
40 changes: 37 additions & 3 deletions clang/lib/CodeGen/CGCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3216,6 +3216,25 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,
}
}

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
llvm::TypeSize StructSize;
llvm::TypeSize PtrElementSize;
if (ArgI.isDirect() && !ArgI.getCanBeFlattened() && STy &&
STy->getNumElements() > 1) {
StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
PtrElementSize =
CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(Ty));
if (STy->containsHomogeneousScalableVectorTypes()) {
assert(StructSize == PtrElementSize &&
"Only allow non-fractional movement of structure with"
"homogeneous scalable vector type");

ArgVals.push_back(ParamValue::forDirect(AI));
break;
}
}

Address Alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg),
Arg->getName());

Expand All @@ -3224,7 +3243,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,

// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy = dyn_cast<llvm::StructType>(ArgI.getCoerceToType());
if (ArgI.isDirect() && ArgI.getCanBeFlattened() && STy &&
STy->getNumElements() > 1) {
llvm::TypeSize StructSize = CGM.getDataLayout().getTypeAllocSize(STy);
Expand Down Expand Up @@ -5287,6 +5305,24 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
break;
}

llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
llvm::Type *SrcTy = ConvertTypeForMem(I->Ty);
llvm::TypeSize SrcTypeSize;
llvm::TypeSize DstTypeSize;
if (STy && ArgInfo.isDirect() && !ArgInfo.getCanBeFlattened()) {
SrcTypeSize = CGM.getDataLayout().getTypeAllocSize(SrcTy);
DstTypeSize = CGM.getDataLayout().getTypeAllocSize(STy);
if (STy->containsHomogeneousScalableVectorTypes()) {
assert(SrcTypeSize == DstTypeSize &&
"Only allow non-fractional movement of structure with "
"homogeneous scalable vector type");

IRCallArgs[FirstIRArg] = I->getKnownRValue().getScalarVal();
break;
}
}

// FIXME: Avoid the conversion through memory if possible.
Address Src = Address::invalid();
if (!I->isAggregate()) {
Expand All @@ -5302,8 +5338,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,

// Fast-isel and the optimizer generally like scalar values better than
// FCAs, so we flatten them if this is safe to do for this argument.
llvm::StructType *STy =
dyn_cast<llvm::StructType>(ArgInfo.getCoerceToType());
if (STy && ArgInfo.isDirect() && ArgInfo.getCanBeFlattened()) {
llvm::Type *SrcTy = Src.getElementType();
llvm::TypeSize SrcTypeSize =
Expand Down
14 changes: 4 additions & 10 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1044,17 +1044,14 @@ void CodeGenModule::Release() {
llvm::MDString::get(VMContext, "ascii"));
}

llvm::Triple::ArchType Arch = Context.getTargetInfo().getTriple().getArch();
if ( Arch == llvm::Triple::arm
|| Arch == llvm::Triple::armeb
|| Arch == llvm::Triple::thumb
|| Arch == llvm::Triple::thumbeb) {
llvm::Triple T = Context.getTargetInfo().getTriple();
if (T.isARM() || T.isThumb()) {
// The minimum width of an enum in bytes
uint64_t EnumWidth = Context.getLangOpts().ShortEnums ? 1 : 4;
getModule().addModuleFlag(llvm::Module::Error, "min_enum_size", EnumWidth);
}

if (Arch == llvm::Triple::riscv32 || Arch == llvm::Triple::riscv64) {
if (T.isRISCV()) {
StringRef ABIStr = Target.getABI();
llvm::LLVMContext &Ctx = TheModule.getContext();
getModule().addModuleFlag(llvm::Module::Error, "target-abi",
Expand Down Expand Up @@ -1127,10 +1124,7 @@ void CodeGenModule::Release() {
getModule().addModuleFlag(llvm::Module::Override,
"tag-stack-memory-buildattr", 1);

if (Arch == llvm::Triple::thumb || Arch == llvm::Triple::thumbeb ||
Arch == llvm::Triple::arm || Arch == llvm::Triple::armeb ||
Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_32 ||
Arch == llvm::Triple::aarch64_be) {
if (T.isARM() || T.isThumb() || T.isAArch64()) {
if (LangOpts.BranchTargetEnforcement)
getModule().addModuleFlag(llvm::Module::Min, "branch-target-enforcement",
1);
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/ItaniumCXXABI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1347,9 +1347,10 @@ static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {

llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);

// Mark the function as nounwind readonly.
// Mark the function as nounwind willreturn readonly.
llvm::AttrBuilder FuncAttrs(CGF.getLLVMContext());
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
FuncAttrs.addAttribute(llvm::Attribute::WillReturn);
FuncAttrs.addMemoryAttr(llvm::MemoryEffects::readOnly());
llvm::AttributeList Attrs = llvm::AttributeList::get(
CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, FuncAttrs);
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/CodeGen/Targets/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,13 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed,
return getNaturalAlignIndirect(Ty, /*ByVal=*/false);
}

return ABIArgInfo::getDirect();
ABIArgInfo Info = ABIArgInfo::getDirect();

// If it is tuple type, it can't be flattened.
if (llvm::StructType *STy = dyn_cast<llvm::StructType>(CGT.ConvertType(Ty)))
Info.setCanBeFlattened(!STy->containsHomogeneousScalableVectorTypes());

return Info;
}

if (const VectorType *VT = Ty->getAs<VectorType>())
Expand Down
19 changes: 10 additions & 9 deletions clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,15 +1443,16 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
const ToolChain &TC = getToolChain(
*UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));

if (TC.getTriple().isAndroid()) {
llvm::Triple Triple = TC.getTriple();
StringRef TripleVersionName = Triple.getEnvironmentVersionString();

if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "") {
Diags.Report(diag::err_drv_triple_version_invalid)
<< TripleVersionName << TC.getTripleString();
ContainsError = true;
}
// Check if the environment version is valid.
llvm::Triple Triple = TC.getTriple();
StringRef TripleVersionName = Triple.getEnvironmentVersionString();
StringRef TripleObjectFormat =
Triple.getObjectFormatTypeName(Triple.getObjectFormat());
if (Triple.getEnvironmentVersion().empty() && TripleVersionName != "" &&
TripleVersionName != TripleObjectFormat) {
Diags.Report(diag::err_drv_triple_version_invalid)
<< TripleVersionName << TC.getTripleString();
ContainsError = true;
}

// Report warning when arm64EC option is overridden by specified target
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/AMDGPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,12 @@ void AMDGPUToolChain::addClangTargetOptions(
}
}

void AMDGPUToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
// AMDGPU does not support atomic lib call. Treat atomic alignment
// warnings as errors.
CC1Args.push_back("-Werror=atomic-alignment");
}

StringRef
AMDGPUToolChain::getGPUArch(const llvm::opt::ArgList &DriverArgs) const {
return getProcessorFromTargetID(
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/ToolChains/AMDGPU.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ class LLVM_LIBRARY_VISIBILITY AMDGPUToolChain : public Generic_ELF {
/// Get GPU arch from -mcpu without checking.
StringRef getGPUArch(const llvm::opt::ArgList &DriverArgs) const;

/// Common warning options shared by AMDGPU HIP, OpenCL and OpenMP toolchains.
/// Language specific warning options should go to derived classes.
void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const override;
};

class LLVM_LIBRARY_VISIBILITY ROCMToolChain : public AMDGPUToolChain {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs(

void AMDGPUOpenMPToolChain::addClangWarningOptions(
ArgStringList &CC1Args) const {
AMDGPUToolChain::addClangWarningOptions(CC1Args);
HostTC.addClangWarningOptions(CC1Args);
}

Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5781,6 +5781,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
// NVPTX/AMDGPU does not care about the code model and will accept
// whatever works for the host.
Ok = true;
} else if (Triple.isSPARC64()) {
if (CM == "medlow")
CM = "small";
else if (CM == "medmid")
CM = "medium";
else if (CM == "medany")
CM = "large";
Ok = CM == "small" || CM == "medium" || CM == "large";
}
if (Ok) {
CmdArgs.push_back(Args.MakeArgString("-mcmodel=" + CM));
Expand Down
8 changes: 7 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2650,7 +2650,7 @@ getAMDGPUCodeObjectArgument(const Driver &D, const llvm::opt::ArgList &Args) {
void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
const llvm::opt::ArgList &Args) {
const unsigned MinCodeObjVer = 4;
const unsigned MaxCodeObjVer = 5;
const unsigned MaxCodeObjVer = 6;

if (auto *CodeObjArg = getAMDGPUCodeObjectArgument(D, Args)) {
if (CodeObjArg->getOption().getID() ==
Expand All @@ -2661,6 +2661,12 @@ void tools::checkAMDGPUCodeObjectVersion(const Driver &D,
if (Remnant || CodeObjVer < MinCodeObjVer || CodeObjVer > MaxCodeObjVer)
D.Diag(diag::err_drv_invalid_int_value)
<< CodeObjArg->getAsString(Args) << CodeObjArg->getValue();

// COV6 is only supported by LLVM at the time of writing this, and it's
// expected to take some time before all ROCm components fully
// support it. In the meantime, make sure users are aware of this.
if (CodeObjVer == 6)
D.Diag(diag::warn_drv_amdgpu_cov6);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/HIPAMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ Tool *HIPAMDToolChain::buildLinker() const {
}

void HIPAMDToolChain::addClangWarningOptions(ArgStringList &CC1Args) const {
AMDGPUToolChain::addClangWarningOptions(CC1Args);
HostTC.addClangWarningOptions(CC1Args);
}

Expand Down
14 changes: 11 additions & 3 deletions clang/lib/Format/ContinuationIndenter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,9 +328,17 @@ bool ContinuationIndenter::canBreak(const LineState &State) {

// Don't break after very short return types (e.g. "void") as that is often
// unexpected.
if (Current.is(TT_FunctionDeclarationName) && State.Column < 6) {
if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None)
if (Current.is(TT_FunctionDeclarationName)) {
if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_None &&
State.Column < 6) {
return false;
}

if (Style.AlwaysBreakAfterReturnType == FormatStyle::RTBS_ExceptShortType) {
assert(State.Column >= State.FirstIndent);
if (State.Column - State.FirstIndent < 6)
return false;
}
}

// If binary operators are moved to the next line (including commas for some
Expand Down Expand Up @@ -587,7 +595,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
!State.Line->ReturnTypeWrapped &&
// Don't break before a C# function when no break after return type.
(!Style.isCSharp() ||
Style.AlwaysBreakAfterReturnType != FormatStyle::RTBS_None) &&
Style.AlwaysBreakAfterReturnType > FormatStyle::RTBS_ExceptShortType) &&
// Don't always break between a JavaScript `function` and the function
// name.
!Style.isJavaScript() && Previous.isNot(tok::kw_template) &&
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,8 @@ template <>
struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) {
IO.enumCase(Value, "None", FormatStyle::RTBS_None);
IO.enumCase(Value, "Automatic", FormatStyle::RTBS_Automatic);
IO.enumCase(Value, "ExceptShortType", FormatStyle::RTBS_ExceptShortType);
IO.enumCase(Value, "All", FormatStyle::RTBS_All);
IO.enumCase(Value, "TopLevel", FormatStyle::RTBS_TopLevel);
IO.enumCase(Value, "TopLevelDefinitions",
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3434,6 +3434,8 @@ bool TokenAnnotator::mustBreakForReturnType(const AnnotatedLine &Line) const {

switch (Style.AlwaysBreakAfterReturnType) {
case FormatStyle::RTBS_None:
case FormatStyle::RTBS_Automatic:
case FormatStyle::RTBS_ExceptShortType:
return false;
case FormatStyle::RTBS_All:
case FormatStyle::RTBS_TopLevel:
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Frontend/TextDiagnostic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1349,7 +1349,7 @@ void TextDiagnostic::emitSnippetAndCaret(
// Prepare source highlighting information for the lines we're about to
// emit, starting from the first line.
std::unique_ptr<SmallVector<StyleRange>[]> SourceStyles =
highlightLines(BufStart, Lines.first, Lines.second, PP, LangOpts,
highlightLines(BufData, Lines.first, Lines.second, PP, LangOpts,
DiagOpts->ShowColors, FID, SM);

SmallVector<LineRange> LineRanges =
Expand Down
4 changes: 3 additions & 1 deletion clang/lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6663,12 +6663,14 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
}

bool HadScope = D.getCXXScopeSpec().isValid();
SourceLocation TemplateKWLoc;
if (ParseUnqualifiedId(D.getCXXScopeSpec(),
/*ObjectType=*/nullptr,
/*ObjectHadErrors=*/false,
/*EnteringContext=*/true,
/*AllowDestructorName=*/true, AllowConstructorName,
AllowDeductionGuide, nullptr, D.getName()) ||
AllowDeductionGuide, &TemplateKWLoc,
D.getName()) ||
// Once we're past the identifier, if the scope was bad, mark the
// whole declarator bad.
D.getCXXScopeSpec().isInvalid()) {
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Parse/ParseDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1725,6 +1725,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
tok::kw___is_member_pointer,
tok::kw___is_nothrow_assignable,
tok::kw___is_nothrow_constructible,
tok::kw___is_nothrow_convertible,
tok::kw___is_nothrow_destructible,
tok::kw___is_nullptr,
tok::kw___is_object,
Expand Down
60 changes: 45 additions & 15 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6196,13 +6196,17 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC,
///
/// \param Loc The location of the name of the entity being declared.
///
/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus
/// we're declaring an explicit / partial specialization / instantiation.
/// \param IsMemberSpecialization Whether we are declaring a member
/// specialization.
///
/// \param TemplateId The template-id, if any.
///
/// \returns true if we cannot safely recover from this error, false otherwise.
bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
DeclarationName Name,
SourceLocation Loc, bool IsTemplateId) {
SourceLocation Loc,
TemplateIdAnnotation *TemplateId,
bool IsMemberSpecialization) {
DeclContext *Cur = CurContext;
while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur))
Cur = Cur->getParent();
Expand Down Expand Up @@ -6231,7 +6235,7 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
// Check whether the qualifying scope encloses the scope of the original
// declaration. For a template-id, we perform the checks in
// CheckTemplateSpecializationScope.
if (!Cur->Encloses(DC) && !IsTemplateId) {
if (!Cur->Encloses(DC) && !(TemplateId || IsMemberSpecialization)) {
if (Cur->isRecord())
Diag(Loc, diag::err_member_qualification)
<< Name << SS.getRange();
Expand Down Expand Up @@ -6277,12 +6281,32 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
return false;
}

// C++23 [temp.names]p5:
// The keyword template shall not appear immediately after a declarative
// nested-name-specifier.
//
// First check the template-id (if any), and then check each component of the
// nested-name-specifier in reverse order.
//
// FIXME: nested-name-specifiers in friend declarations are declarative,
// but we don't call diagnoseQualifiedDeclaration for them. We should.
if (TemplateId && TemplateId->TemplateKWLoc.isValid())
Diag(Loc, diag::ext_template_after_declarative_nns)
<< FixItHint::CreateRemoval(TemplateId->TemplateKWLoc);

NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
while (SpecLoc.getPrefix()) {
if (SpecLoc.getNestedNameSpecifier()->getKind() ==
NestedNameSpecifier::TypeSpecWithTemplate)
Diag(Loc, diag::ext_template_after_declarative_nns)
<< FixItHint::CreateRemoval(
SpecLoc.getTypeLoc().getTemplateKeywordLoc());

SpecLoc = SpecLoc.getPrefix();
}
// C++11 [dcl.meaning]p1:
// [...] "The nested-name-specifier of the qualified declarator-id shall
// not begin with a decltype-specifer"
NestedNameSpecifierLoc SpecLoc(SS.getScopeRep(), SS.location_data());
while (SpecLoc.getPrefix())
SpecLoc = SpecLoc.getPrefix();
if (isa_and_nonnull<DecltypeType>(
SpecLoc.getNestedNameSpecifier()->getAsType()))
Diag(Loc, diag::err_decltype_in_declarator)
Expand Down Expand Up @@ -6350,9 +6374,13 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
return nullptr;
}
if (!D.getDeclSpec().isFriendSpecified()) {
if (diagnoseQualifiedDeclaration(
D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(),
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) {
TemplateIdAnnotation *TemplateId =
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
: nullptr;
if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC, Name,
D.getIdentifierLoc(), TemplateId,
/*IsMemberSpecialization=*/false)) {
if (DC->isRecord())
return nullptr;

Expand Down Expand Up @@ -7727,7 +7755,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
? TemplateParamLists[0]->getTemplateLoc()
: SourceLocation();
DeclResult Res = ActOnVarTemplateSpecialization(
S, D, TInfo, TemplateKWLoc, TemplateParams, SC,
S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization);
if (Res.isInvalid())
return nullptr;
Expand Down Expand Up @@ -8070,8 +8098,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
} else {
// If this is an explicit specialization of a static data member, check it.
if (IsMemberSpecialization && !NewVD->isInvalidDecl() &&
CheckMemberSpecialization(NewVD, Previous))
if (IsMemberSpecialization && !IsVariableTemplateSpecialization &&
!NewVD->isInvalidDecl() && CheckMemberSpecialization(NewVD, Previous))
NewVD->setInvalidDecl();

// Merge the decl with the existing one if appropriate.
Expand All @@ -8086,15 +8114,16 @@ NamedDecl *Sema::ActOnVariableDeclarator(
Previous.clear();
NewVD->setInvalidDecl();
}
} else if (D.getCXXScopeSpec().isSet()) {
} else if (D.getCXXScopeSpec().isSet() &&
!IsVariableTemplateSpecialization) {
// No previous declaration in the qualifying scope.
Diag(D.getIdentifierLoc(), diag::err_no_member)
<< Name << computeDeclContext(D.getCXXScopeSpec(), true)
<< D.getCXXScopeSpec().getRange();
NewVD->setInvalidDecl();
}

if (!IsVariableTemplateSpecialization && !IsPlaceholderVariable)
if (!IsPlaceholderVariable)
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));

// CheckVariableDeclaration will set NewVD as invalid if something is in
Expand Down Expand Up @@ -17956,6 +17985,7 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
// nested-name-specifier against the current context.
if ((TUK == TUK_Definition || TUK == TUK_Declaration) &&
diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc,
/*TemplateId=*/nullptr,
isMemberSpecialization))
Invalid = true;

Expand Down
14 changes: 9 additions & 5 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3621,14 +3621,18 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
// class X {
// int X::member;
// };
if (DeclContext *DC = computeDeclContext(SS, false))
if (DeclContext *DC = computeDeclContext(SS, false)) {
TemplateIdAnnotation *TemplateId =
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
? D.getName().TemplateId
: nullptr;
diagnoseQualifiedDeclaration(SS, DC, Name, D.getIdentifierLoc(),
D.getName().getKind() ==
UnqualifiedIdKind::IK_TemplateId);
else
TemplateId,
/*IsMemberSpecialization=*/false);
} else {
Diag(D.getIdentifierLoc(), diag::err_member_qualification)
<< Name << SS.getRange();

}
SS.clear();
}

Expand Down
11 changes: 9 additions & 2 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5779,7 +5779,8 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return Self.Context.typesAreCompatible(Lhs, Rhs);
}
case BTT_IsConvertible:
case BTT_IsConvertibleTo: {
case BTT_IsConvertibleTo:
case BTT_IsNothrowConvertible: {
// C++0x [meta.rel]p4:
// Given the following function prototype:
//
Expand Down Expand Up @@ -5840,7 +5841,13 @@ static bool EvaluateBinaryTypeTrait(Sema &Self, TypeTrait BTT, QualType LhsT,
return false;

ExprResult Result = Init.Perform(Self, To, Kind, FromPtr);
return !Result.isInvalid() && !SFINAE.hasErrorOccurred();
if (Result.isInvalid() || SFINAE.hasErrorOccurred())
return false;

if (BTT != BTT_IsNothrowConvertible)
return true;

return Self.canThrow(Result.get()) == CT_Cannot;
}

case BTT_IsAssignable:
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaOverload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7623,7 +7623,8 @@ void Sema::AddTemplateOverloadCandidate(
// functions. In such a case, the candidate functions generated from each
// function template are combined with the set of non-template candidate
// functions.
TemplateDeductionInfo Info(CandidateSet.getLocation());
TemplateDeductionInfo Info(CandidateSet.getLocation(),
FunctionTemplate->getTemplateDepth());
FunctionDecl *Specialization = nullptr;
ConversionSequenceList Conversions;
if (TemplateDeductionResult Result = DeduceTemplateArguments(
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Sema/SemaRISCVVectorLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ void RISCVIntrinsicManagerImpl::ConstructRVVIntrinsics(
{"zvknhb", RVV_REQ_Zvknhb},
{"zvksed", RVV_REQ_Zvksed},
{"zvksh", RVV_REQ_Zvksh},
{"zvfbfwma", RVV_REQ_Zvfbfwma},
{"experimental", RVV_REQ_Experimental}};

// Construction of RVVIntrinsicRecords need to sync with createRVVIntrinsics
Expand Down
38 changes: 23 additions & 15 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1890,8 +1890,12 @@ DeclResult Sema::CheckClassTemplate(
ContextRAII SavedContext(*this, SemanticContext);
if (RebuildTemplateParamsInCurrentInstantiation(TemplateParams))
Invalid = true;
} else if (TUK != TUK_Friend && TUK != TUK_Reference)
diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc, false);
}

if (TUK != TUK_Friend && TUK != TUK_Reference)
diagnoseQualifiedDeclaration(SS, SemanticContext, Name, NameLoc,
/*TemplateId-*/ nullptr,
/*IsMemberSpecialization*/ false);

LookupQualifiedName(Previous, SemanticContext);
} else {
Expand Down Expand Up @@ -4601,9 +4605,9 @@ void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
}

DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, SourceLocation TemplateKWLoc,
TemplateParameterList *TemplateParams, StorageClass SC,
bool IsPartialSpecialization) {
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization) {
// D must be variable template id.
assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId &&
"Variable template specialization is declared with a template id.");
Expand Down Expand Up @@ -4783,17 +4787,12 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// Note that this is an explicit specialization.
Specialization->setSpecializationKind(TSK_ExplicitSpecialization);

if (PrevDecl) {
// Check that this isn't a redefinition of this specialization,
// merging with previous declarations.
LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
forRedeclarationInCurContext());
PrevSpec.addDecl(PrevDecl);
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
} else if (Specialization->isStaticDataMember() &&
Specialization->isOutOfLine()) {
Previous.clear();
if (PrevDecl)
Previous.addDecl(PrevDecl);
else if (Specialization->isStaticDataMember() &&
Specialization->isOutOfLine())
Specialization->setAccess(VarTemplate->getAccess());
}

return Specialization;
}
Expand Down Expand Up @@ -8831,6 +8830,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
bool isMemberSpecialization = false;
bool isPartialSpecialization = false;

if (SS.isSet()) {
if (TUK != TUK_Reference && TUK != TUK_Friend &&
diagnoseQualifiedDeclaration(SS, ClassTemplate->getDeclContext(),
ClassTemplate->getDeclName(),
TemplateNameLoc, &TemplateId,
/*IsMemberSpecialization=*/false))
return true;
}

// Check the validity of the template headers that introduce this
// template.
// FIXME: We probably shouldn't complain about these headers for
Expand Down
14 changes: 12 additions & 2 deletions clang/lib/Sema/SemaTemplateInstantiate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3049,6 +3049,7 @@ bool Sema::SubstDefaultArgument(
// default argument expression appears.
ContextRAII SavedContext(*this, FD);
std::unique_ptr<LocalInstantiationScope> LIS;
MultiLevelTemplateArgumentList NewTemplateArgs = TemplateArgs;

if (ForCallExpr) {
// When instantiating a default argument due to use in a call expression,
Expand All @@ -3061,11 +3062,20 @@ bool Sema::SubstDefaultArgument(
/*ForDefinition*/ false);
if (addInstantiatedParametersToScope(FD, PatternFD, *LIS, TemplateArgs))
return true;
const FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate();
if (PrimaryTemplate && PrimaryTemplate->isOutOfLine()) {
TemplateArgumentList *CurrentTemplateArgumentList =
TemplateArgumentList::CreateCopy(getASTContext(),
TemplateArgs.getInnermost());
NewTemplateArgs = getTemplateInstantiationArgs(
FD, FD->getDeclContext(), /*Final=*/false,
CurrentTemplateArgumentList->asArray(), /*RelativeToPrimary=*/true);
}
}

runWithSufficientStackSpace(Loc, [&] {
Result = SubstInitializer(PatternExpr, TemplateArgs,
/*DirectInit*/false);
Result = SubstInitializer(PatternExpr, NewTemplateArgs,
/*DirectInit*/ false);
});
}
if (Result.isInvalid())
Expand Down
13 changes: 11 additions & 2 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5907,15 +5907,24 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// - the type-id in the default argument of a type-parameter, or
// - the type-id of a template-argument for a type-parameter
//
// C++23 [dcl.fct]p6 (P0847R7)
// ... A member-declarator with an explicit-object-parameter-declaration
// shall not include a ref-qualifier or a cv-qualifier-seq and shall not be
// declared static or virtual ...
//
// FIXME: Checking this here is insufficient. We accept-invalid on:
//
// template<typename T> struct S { void f(T); };
// S<int() const> s;
//
// ... for instance.
if (IsQualifiedFunction &&
!(Kind == Member && !D.isExplicitObjectMemberFunction() &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
// Check for non-static member function and not and
// explicit-object-parameter-declaration
(Kind != Member || D.isExplicitObjectMemberFunction() ||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static ||
(D.getContext() == clang::DeclaratorContext::Member &&
D.isStaticMember())) &&
!IsTypedefName && D.getContext() != DeclaratorContext::TemplateArg &&
D.getContext() != DeclaratorContext::TemplateTypeArg) {
SourceLocation Loc = D.getBeginLoc();
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -4394,7 +4394,8 @@ NestedNameSpecifierLoc TreeTransform<Derived>::TransformNestedNameSpecifierLoc(
SS.Adopt(ETL.getQualifierLoc());
TL = ETL.getNamedTypeLoc();
}
SS.Extend(SemaRef.Context, /*FIXME:*/ SourceLocation(), TL,

SS.Extend(SemaRef.Context, TL.getTemplateKeywordLoc(), TL,
Q.getLocalEndLoc());
break;
}
Expand Down
25 changes: 25 additions & 0 deletions clang/test/AST/ast-dump-pack-indexing-crash.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: not %clang_cc1 -std=c++2c -ast-dump %s | FileCheck %s

namespace InvalidPacksShouldNotCrash {

struct NotAPack;
template <typename T, auto V, template<typename> typename Tp>
void not_pack() {
int i = 0;
i...[0]; // expected-error {{i does not refer to the name of a parameter pack}}
V...[0]; // expected-error {{V does not refer to the name of a parameter pack}}
NotAPack...[0] a; // expected-error{{'NotAPack' does not refer to the name of a parameter pack}}
T...[0] b; // expected-error{{'T' does not refer to the name of a parameter pack}}
Tp...[0] c; // expected-error{{'Tp' does not refer to the name of a parameter pack}}
}

// CHECK: FunctionDecl {{.*}} not_pack 'void ()'
// CHECK: DeclStmt {{.*}}
// CHECK: DeclStmt {{.*}}
// CHECK-NEXT: VarDecl {{.*}} a 'NotAPack...{{.*}}'
// CHECK-NEXT: DeclStmt {{.*}}
// CHECK-NEXT: VarDecl {{.*}} 'T...{{.*}}'
// CHECK-NEXT: DeclStmt {{.*}}
// CHECK-NEXT: VarDecl {{.*}} c 'Tp...{{.*}}'

}
112 changes: 112 additions & 0 deletions clang/test/CXX/dcl.decl/dcl.meaning/dcl.meaning.general/p3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s

namespace N0 {
template<typename T>
void f0();

template<typename T>
int x0 = 0;

template<typename T>
class C0;
}
using namespace N0;

template<>
void f0<int>(); // expected-error {{no function template matches}}

template<>
int x0<int>;

template<>
class C0<int>;

namespace N1 {
namespace N2 {
template<typename T>
void f2();

template<typename T>
int x2 = 0;

template<typename T>
class C2;
}
using namespace N2;
}

template<>
void N1::f2<int>(); // expected-error {{no function template matches}}

template<>
int N1::x2<int>;

template<>
class N1::C2<int>;

namespace N3 {
namespace N4 {
template<typename T>
void f4();

template<typename T>
int x4 = 0;

template<typename T>
class C4;
}
using N4::f4;
using N4::x4;
using N4::C4;
}

template<>
void N3::f4<int>(); // expected-error {{no function template matches}}

template<>
int N3::x4<int>;

template<>
class N3::C4<int>;

inline namespace N5 {
template<typename T>
void f5();

template<typename T>
int x5 = 0;

template<typename T>
class C5;
}

template<>
void f5<int>();

template<>
int x5<int>;

template<>
class C5<int>;

namespace N6 {
inline namespace N7 {
template<typename T>
void f7();

template<typename T>
int x7 = 0;

template<typename T>
class C7;
}
}

template<>
void N6::f7<int>();

template<>
int N6::x7<int>;

template<>
class N6::C7<int>;
4 changes: 2 additions & 2 deletions clang/test/CXX/drs/dr23xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,8 @@ struct Bad2 { int a, b; };
} // namespace dr2386
namespace std {
template <typename T> struct tuple_size;
template <> struct std::tuple_size<dr2386::Bad1> {};
template <> struct std::tuple_size<dr2386::Bad2> {
template <> struct tuple_size<dr2386::Bad1> {};
template <> struct tuple_size<dr2386::Bad2> {
static const int value = 42;
};
} // namespace std
Expand Down
6 changes: 4 additions & 2 deletions clang/test/CXX/drs/dr7xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ namespace dr727 { // dr727: partial
// expected-note@#dr727-N {{explicitly specialized declaration is here}}

template<> struct A::C<double>;
// expected-error@-1 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}}
// expected-error@-1 {{non-friend class member 'C' cannot have a qualified name}}
// expected-error@-2 {{class template specialization of 'C' not in class 'A' or an enclosing namespace}}
// expected-note@#dr727-C {{explicitly specialized declaration is here}}
template<> void A::f<double>();
// expected-error@-1 {{o function template matches function template specialization 'f'}}
Expand All @@ -116,7 +117,8 @@ namespace dr727 { // dr727: partial
// expected-note@#dr727-N {{explicitly specialized declaration is here}}

template<typename T> struct A::C<T***>;
// expected-error@-1 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}}
// expected-error@-1 {{non-friend class member 'C' cannot have a qualified name}}
// expected-error@-2 {{class template partial specialization of 'C' not in class 'A' or an enclosing namespace}}
// expected-note@#dr727-C {{explicitly specialized declaration is here}}
template<typename T> static int A::N<T***>;
// expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct X1 {

template<typename T>
template<typename U>
void X1<T>::template B<U>::f() { }
void X1<T>::template B<U>::f() { } // expected-warning{{'template' cannot be used after a declarative}}

// PR5527
template <template <class> class T>
Expand Down
206 changes: 206 additions & 0 deletions clang/test/CXX/temp/temp.names/p5.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
// RUN: %clang_cc1 -fsyntax-only -pedantic-errors -verify %s

template<typename T> struct A {
template<typename U> struct B {
// FIXME: The standard does not seem to consider non-friend elaborated-type-specifiers that
// declare partial specializations/explicit specializations/explicit instantiations to be
// declarative, see https://lists.isocpp.org/core/2024/01/15325.php
struct C;
template<typename V> struct D;

void f();
template<typename V> void g();

static int x;
template<typename V> static int y;

enum class E;
};
};

template<typename T>
template<typename U>
struct A<T>::template B<U>::C { }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
struct A<int>::template B<bool>::C; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
struct A<int>::template B<bool>::C { }; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
struct A<T>::template B<U>::D<V*>; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
struct A<T>::B<U>::template D<V**>; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
struct A<T>::template B<U>::D { }; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
struct A<T>::template B<U>::D<V*> { }; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
struct A<T>::B<U>::template D<V**> { }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
struct A<int>::template B<bool>::D; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
struct A<int>::template B<bool>::D<short>; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
struct A<int>::B<bool>::template D<long>; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
struct A<int>::template B<bool>::D<V*>; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
struct A<int>::B<bool>::template D<V**>; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
struct A<int>::template B<bool>::D { }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
struct A<int>::template B<bool>::D<short> { }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
struct A<int>::B<bool>::template D<long> { }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
struct A<int>::template B<bool>::D<V*> { }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
struct A<int>::B<bool>::template D<V**> { }; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
void A<T>::template B<U>::f() { } // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
void A<int>::template B<bool>::f() { } // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
void A<T>::template B<U>::g() { } // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
void A<int>::B<bool>::template g<short>() { } // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
void A<int>::template B<bool>::g<long>() { } // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
void A<int>::template B<bool>::g() { } // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
int A<T>::template B<U>::x = 0; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
int A<T>::template B<U>::y = 0; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
int A<T>::template B<U>::y<V*> = 0; // expected-error{{'template' cannot be used after a declarative}}

template<typename T>
template<typename U>
template<typename V>
int A<T>::B<U>::template y<V**> = 0; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
int A<int>::template B<bool>::y = 0; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
int A<int>::template B<bool>::y<short> = 0; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<>
int A<int>::B<bool>::template y<long> = 0; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
int A<int>::template B<bool>::y<V*> = 0; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
template<typename V>
int A<int>::B<bool>::template y<V**> = 0; // expected-error{{'template' cannot be used after a declarative}}
template<typename T>
template<typename U>
enum class A<T>::template B<U>::E { a }; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
enum class A<int>::template B<bool>::E; // expected-error{{'template' cannot be used after a declarative}}

template<>
template<>
enum class A<int>::template B<bool>::E { a }; // expected-error{{'template' cannot be used after a declarative}}

// FIXME: We don't call Sema::diagnoseQualifiedDeclaration for friend declarations right now
template<typename T>
struct F {
// FIXME: f should be assumed to name a template per [temp.names] p3.4
friend void T::f<int>();
// expected-error@-1{{use 'template' keyword to treat 'f' as a dependent template name}}
// expected-error@-2{{no candidate function template was found for}}

// FIXME: We should diagnose the presence of 'template' here
friend void T::template f<int>(); // expected-error{{no candidate function template was found for}}
friend void T::template U<int>::f();

// These should be allowed
friend class T::template U<int>;
friend class T::template U<int>::V;
};
2 changes: 1 addition & 1 deletion clang/test/CXX/temp/temp.spec/part.spec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,4 +478,4 @@ template <typename T> class PCTT6<TestClass::PrivateClass, T> {
};
template <typename T1> template <typename, typename> class PCTT6<TestClass::PrivateClass, T1>::NCT4 final {};
// expected-error@+1 2{{is a private member of}}
template <typename T1> template <typename T2> struct PCTT6<TestClass::PrivateClass, T1>::template NCT3<T2, TestClass::TemplatePrivateClass<TestClass::TemplateProtectedClass<TestClass::PublicClass>>> : PCTT6<TestClass::PrivateClass, T1>::NCT4<T2, TestClass::TemplatePrivateClass<int>> {};
template <typename T1> template <typename T2> struct PCTT6<TestClass::PrivateClass, T1>::NCT3<T2, TestClass::TemplatePrivateClass<TestClass::TemplateProtectedClass<TestClass::PublicClass>>> : PCTT6<TestClass::PrivateClass, T1>::NCT4<T2, TestClass::TemplatePrivateClass<int>> {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 4
// REQUIRES: riscv-registered-target
// RUN: %clang_cc1 -triple riscv64 -target-feature +v \
// RUN: -target-feature +experimental-zvfbfmin -disable-O0-optnone \
// RUN: -emit-llvm %s -o - | opt -S -passes=mem2reg | \
// RUN: FileCheck --check-prefix=CHECK-RV64 %s

#include <riscv_vector.h>

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf4(
// CHECK-RV64-SAME: <vscale x 1 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0:[0-9]+]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv1bf16.nxv1f32.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x float> [[VS2]], i64 7, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vfncvtbf16_f_f_w_bf16mf4(vfloat32mf2_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf4(vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf2(
// CHECK-RV64-SAME: <vscale x 2 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv2bf16.nxv2f32.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x float> [[VS2]], i64 7, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vfncvtbf16_f_f_w_bf16mf2(vfloat32m1_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf2(vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vfncvtbf16_f_f_w_bf16m1(
// CHECK-RV64-SAME: <vscale x 4 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv4bf16.nxv4f32.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x float> [[VS2]], i64 7, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vfncvtbf16_f_f_w_bf16m1(vfloat32m2_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m1(vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vfncvtbf16_f_f_w_bf16m2(
// CHECK-RV64-SAME: <vscale x 8 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv8bf16.nxv8f32.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x float> [[VS2]], i64 7, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vfncvtbf16_f_f_w_bf16m2(vfloat32m4_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m2(vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vfncvtbf16_f_f_w_bf16m4(
// CHECK-RV64-SAME: <vscale x 16 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv16bf16.nxv16f32.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x float> [[VS2]], i64 7, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vfncvtbf16_f_f_w_bf16m4(vfloat32m8_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m4(vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf4_m(
// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv1bf16.nxv1f32.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x float> [[VS2]], <vscale x 1 x i1> [[VM]], i64 7, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vfncvtbf16_f_f_w_bf16mf4_m(vbool64_t vm, vfloat32mf2_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf4_m(vm, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf2_m(
// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv2bf16.nxv2f32.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x float> [[VS2]], <vscale x 2 x i1> [[VM]], i64 7, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vfncvtbf16_f_f_w_bf16mf2_m(vbool32_t vm, vfloat32m1_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf2_m(vm, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vfncvtbf16_f_f_w_bf16m1_m(
// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv4bf16.nxv4f32.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x float> [[VS2]], <vscale x 4 x i1> [[VM]], i64 7, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vfncvtbf16_f_f_w_bf16m1_m(vbool16_t vm, vfloat32m2_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m1_m(vm, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vfncvtbf16_f_f_w_bf16m2_m(
// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv8bf16.nxv8f32.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x float> [[VS2]], <vscale x 8 x i1> [[VM]], i64 7, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vfncvtbf16_f_f_w_bf16m2_m(vbool8_t vm, vfloat32m4_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m2_m(vm, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vfncvtbf16_f_f_w_bf16m4_m(
// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv16bf16.nxv16f32.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x float> [[VS2]], <vscale x 16 x i1> [[VM]], i64 7, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vfncvtbf16_f_f_w_bf16m4_m(vbool4_t vm, vfloat32m8_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m4_m(vm, vs2, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf4_rm(
// CHECK-RV64-SAME: <vscale x 1 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv1bf16.nxv1f32.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x float> [[VS2]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
vbfloat16mf4_t test_vfncvtbf16_f_f_w_bf16mf4_rm(vfloat32mf2_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf4_rm(vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf2_rm(
// CHECK-RV64-SAME: <vscale x 2 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv2bf16.nxv2f32.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x float> [[VS2]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vfncvtbf16_f_f_w_bf16mf2_rm(vfloat32m1_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf2_rm(vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vfncvtbf16_f_f_w_bf16m1_rm(
// CHECK-RV64-SAME: <vscale x 4 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv4bf16.nxv4f32.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x float> [[VS2]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vfncvtbf16_f_f_w_bf16m1_rm(vfloat32m2_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m1_rm(vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vfncvtbf16_f_f_w_bf16m2_rm(
// CHECK-RV64-SAME: <vscale x 8 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv8bf16.nxv8f32.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x float> [[VS2]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vfncvtbf16_f_f_w_bf16m2_rm(vfloat32m4_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m2_rm(vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vfncvtbf16_f_f_w_bf16m4_rm(
// CHECK-RV64-SAME: <vscale x 16 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.nxv16bf16.nxv16f32.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x float> [[VS2]], i64 0, i64 [[VL]])
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vfncvtbf16_f_f_w_bf16m4_rm(vfloat32m8_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m4_rm(vs2, __RISCV_FRM_RNE, vl);
}

vbfloat16mf4_t
// CHECK-RV64-LABEL: define dso_local <vscale x 1 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf4_rm_m(
// CHECK-RV64-SAME: <vscale x 1 x i1> [[VM:%.*]], <vscale x 1 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 1 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv1bf16.nxv1f32.i64(<vscale x 1 x bfloat> poison, <vscale x 1 x float> [[VS2]], <vscale x 1 x i1> [[VM]], i64 0, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 1 x bfloat> [[TMP0]]
//
test_vfncvtbf16_f_f_w_bf16mf4_rm_m(vbool64_t vm, vfloat32mf2_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf4_rm_m(vm, vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 2 x bfloat> @test_vfncvtbf16_f_f_w_bf16mf2_rm_m(
// CHECK-RV64-SAME: <vscale x 2 x i1> [[VM:%.*]], <vscale x 2 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 2 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv2bf16.nxv2f32.i64(<vscale x 2 x bfloat> poison, <vscale x 2 x float> [[VS2]], <vscale x 2 x i1> [[VM]], i64 0, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 2 x bfloat> [[TMP0]]
//
vbfloat16mf2_t test_vfncvtbf16_f_f_w_bf16mf2_rm_m(vbool32_t vm,
vfloat32m1_t vs2, size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16mf2_rm_m(vm, vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 4 x bfloat> @test_vfncvtbf16_f_f_w_bf16m1_rm_m(
// CHECK-RV64-SAME: <vscale x 4 x i1> [[VM:%.*]], <vscale x 4 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 4 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv4bf16.nxv4f32.i64(<vscale x 4 x bfloat> poison, <vscale x 4 x float> [[VS2]], <vscale x 4 x i1> [[VM]], i64 0, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 4 x bfloat> [[TMP0]]
//
vbfloat16m1_t test_vfncvtbf16_f_f_w_bf16m1_rm_m(vbool16_t vm, vfloat32m2_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m1_rm_m(vm, vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 8 x bfloat> @test_vfncvtbf16_f_f_w_bf16m2_rm_m(
// CHECK-RV64-SAME: <vscale x 8 x i1> [[VM:%.*]], <vscale x 8 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 8 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv8bf16.nxv8f32.i64(<vscale x 8 x bfloat> poison, <vscale x 8 x float> [[VS2]], <vscale x 8 x i1> [[VM]], i64 0, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 8 x bfloat> [[TMP0]]
//
vbfloat16m2_t test_vfncvtbf16_f_f_w_bf16m2_rm_m(vbool8_t vm, vfloat32m4_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m2_rm_m(vm, vs2, __RISCV_FRM_RNE, vl);
}

// CHECK-RV64-LABEL: define dso_local <vscale x 16 x bfloat> @test_vfncvtbf16_f_f_w_bf16m4_rm_m(
// CHECK-RV64-SAME: <vscale x 16 x i1> [[VM:%.*]], <vscale x 16 x float> [[VS2:%.*]], i64 noundef [[VL:%.*]]) #[[ATTR0]] {
// CHECK-RV64-NEXT: entry:
// CHECK-RV64-NEXT: [[TMP0:%.*]] = call <vscale x 16 x bfloat> @llvm.riscv.vfncvtbf16.f.f.w.mask.nxv16bf16.nxv16f32.i64(<vscale x 16 x bfloat> poison, <vscale x 16 x float> [[VS2]], <vscale x 16 x i1> [[VM]], i64 0, i64 [[VL]], i64 3)
// CHECK-RV64-NEXT: ret <vscale x 16 x bfloat> [[TMP0]]
//
vbfloat16m4_t test_vfncvtbf16_f_f_w_bf16m4_rm_m(vbool4_t vm, vfloat32m8_t vs2,
size_t vl) {
return __riscv_vfncvtbf16_f_f_w_bf16m4_rm_m(vm, vs2, __RISCV_FRM_RNE, vl);
}
Loading