2 changes: 1 addition & 1 deletion clang-tools-extra/docs/clang-tidy/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ An overview of all the command-line options:
FormatStyle - Same as '--format-style'.
HeaderFileExtensions - File extensions to consider to determine if a
given diagnostic is located in a header file.
HeaderFilterRegex - Same as '--header-filter-regex'.
HeaderFilterRegex - Same as '--header-filter'.
ImplementationFileExtensions - File extensions to consider to determine if a
given diagnostic is located in an
implementation file.
Expand Down
2 changes: 1 addition & 1 deletion clang-tools-extra/include-cleaner/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
set(LLVM_LINK_COMPONENTS Support)

add_clang_library(clangIncludeCleaner
add_clang_library(clangIncludeCleaner STATIC
Analysis.cpp
IncludeSpeller.cpp
FindHeaders.cpp
Expand Down
79 changes: 43 additions & 36 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ the configuration (without a prefix: ``Auto``).
.. _AlignArrayOfStructures:

**AlignArrayOfStructures** (``ArrayInitializerAlignmentStyle``) :versionbadge:`clang-format 13` :ref:`ΒΆ <AlignArrayOfStructures>`
if not ``None``, when using initialization for an array of structs
If not ``None``, when using initialization for an array of structs
aligns the fields into columns.


Expand Down Expand Up @@ -307,11 +307,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -464,11 +465,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -621,11 +623,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -779,11 +782,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1056,11 +1060,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1211,11 +1216,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down Expand Up @@ -1366,11 +1372,12 @@ the configuration (without a prefix: ``Auto``).
Alignment options.

They can also be read as a whole for compatibility. The choices are:
- None
- Consecutive
- AcrossEmptyLines
- AcrossComments
- AcrossEmptyLinesAndComments

* ``None``
* ``Consecutive``
* ``AcrossEmptyLines``
* ``AcrossComments``
* ``AcrossEmptyLinesAndComments``

For example, to align across empty lines and not across comments, either
of these work.
Expand Down
19 changes: 17 additions & 2 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,8 @@ Improvements to Clang's diagnostics

- Clang now emits a diagnostic note at the class declaration when the method definition does not match any declaration (#GH110638).

- Clang now omits warnings for extra parentheses in fold expressions with single expansion (#GH101863).

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

Expand All @@ -393,6 +395,8 @@ Bug Fixes in This Version
- Fixed a crash when trying to transform a dependent address space type. Fixes #GH101685.
- Fixed a crash when diagnosing format strings and encountering an empty
delimited escape sequence (e.g., ``"\o{}"``). #GH102218
- The warning emitted for an unsupported register variable type now points to
the unsupported type instead of the ``register`` keyword (#GH109776).

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -471,8 +475,15 @@ Bug Fixes to C++ Support
- Fixed an issue deducing non-type template arguments of reference type. (#GH73460)
- Fixed an issue in constraint evaluation, where type constraints on the lambda expression
containing outer unexpanded parameters were not correctly expanded. (#GH101754)
- Fixes crashes with function template member specializations, and increases
conformance of explicit instantiation behaviour with MSVC. (#GH111266)
- Fixed a bug in constraint expression comparison where the ``sizeof...`` expression was not handled properly
in certain friend declarations. (#GH93099)
- Clang now instantiates the correct lambda call operator when a lambda's class type is
merged across modules. (#GH110401)
- Clang now uses the correct set of template argument lists when comparing the constraints of
out-of-line definitions and member templates explicitly specialized for a given implicit instantiation of
a class template. (#GH102320)

Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -510,6 +521,10 @@ OpenACC Specific Changes
Target Specific Changes
-----------------------

- Clang now implements the Solaris-specific mangling of ``std::tm`` as
``tm``, same for ``std::div_t``, ``std::ldiv_t``, and
``std::lconv``, for Solaris ABI compatibility. (#GH33114)

AMDGPU Support
^^^^^^^^^^^^^^

Expand Down Expand Up @@ -636,8 +651,8 @@ New features
if class of allocation and deallocation function mismatches.
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-mismatcheddeallocator-c-c>`__.

- Function effects, e.g. the ``nonblocking`` and ``nonallocating`` "performance constraint"
attributes, are now verified. For example, for functions declared with the ``nonblocking``
- Function effects, e.g. the ``nonblocking`` and ``nonallocating`` "performance constraint"
attributes, are now verified. For example, for functions declared with the ``nonblocking``
attribute, the compiler can generate warnings about the use of any language features, or calls to
other functions, which may block.

Expand Down
66 changes: 27 additions & 39 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -781,15 +781,11 @@ class RedeclarableTemplateDecl : public TemplateDecl,
EntryType *Entry, void *InsertPos);

struct CommonBase {
CommonBase() : InstantiatedFromMember(nullptr, false) {}
CommonBase() {}

/// The template from which this was most
/// directly instantiated (or null).
///
/// The boolean value indicates whether this template
/// was explicitly specialized.
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember;
RedeclarableTemplateDecl *InstantiatedFromMember = nullptr;

/// If non-null, points to an array of specializations (including
/// partial specializations) known only by their external declaration IDs.
Expand All @@ -809,14 +805,19 @@ class RedeclarableTemplateDecl : public TemplateDecl,
};

/// Pointer to the common data shared by all declarations of this
/// template.
mutable CommonBase *Common = nullptr;
/// template, and a flag indicating if the template is a member
/// specialization.
mutable llvm::PointerIntPair<CommonBase *, 1, bool> Common;

CommonBase *getCommonPtrInternal() const { return Common.getPointer(); }

/// Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory
/// for the common pointer.
CommonBase *getCommonPtr() const;

void setCommonPtr(CommonBase *C) const { Common.setPointer(C); }

virtual CommonBase *newCommon(ASTContext &C) const = 0;

// Construct a template decl with name, parameters, and templated element.
Expand Down Expand Up @@ -857,15 +858,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode
bool isMemberSpecialization() const {
return getCommonPtr()->InstantiatedFromMember.getInt();
}
bool isMemberSpecialization() const { return Common.getInt(); }

/// Note that this member template is a specialization.
void setMemberSpecialization() {
assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
getCommonPtr()->InstantiatedFromMember.setInt(true);
assert(!isMemberSpecialization() && "already a member specialization");
Common.setInt(true);
}

/// Retrieve the member template from which this template was
Expand Down Expand Up @@ -905,12 +903,12 @@ class RedeclarableTemplateDecl : public TemplateDecl,
/// void X<T>::f(T, U);
/// \endcode
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const {
return getCommonPtr()->InstantiatedFromMember.getPointer();
return getCommonPtr()->InstantiatedFromMember;
}

void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
assert(!getCommonPtr()->InstantiatedFromMember);
getCommonPtr()->InstantiatedFromMember = TD;
}

/// Retrieve the "injected" template arguments that correspond to the
Expand Down Expand Up @@ -1989,6 +1987,8 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// template arguments have been deduced.
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgumentList *TemplateArgs) {
assert(!isa<ClassTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
Expand All @@ -2000,6 +2000,8 @@ class ClassTemplateSpecializationDecl : public CXXRecordDecl,
/// Note that this class template specialization is an instantiation
/// of the given class template.
void setInstantiationOf(ClassTemplateDecl *TemplDecl) {
assert(!isa<ClassTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Previously set to a class template partial specialization!");
SpecializedTemplate = TemplDecl;
Expand Down Expand Up @@ -2187,18 +2189,11 @@ class ClassTemplatePartialSpecializationDecl
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() const {
const auto *First =
cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
return InstantiatedFromMember.getInt();
}

/// Note that this member template is a specialization.
void setMemberSpecialization() {
auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
}
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }

/// Retrieves the injected specialization type for this partial
/// specialization. This is not the same as the type-decl-type for
Expand Down Expand Up @@ -2268,10 +2263,6 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}

void setCommonPtr(Common *C) {
RedeclarableTemplateDecl::Common = C;
}

public:

friend class ASTDeclReader;
Expand Down Expand Up @@ -2754,6 +2745,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// template arguments have been deduced.
void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
const TemplateArgumentList *TemplateArgs) {
assert(!isa<VarTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Already set to a variable template partial specialization!");
auto *PS = new (getASTContext()) SpecializedPartialSpecialization();
Expand All @@ -2765,6 +2758,8 @@ class VarTemplateSpecializationDecl : public VarDecl,
/// Note that this variable template specialization is an instantiation
/// of the given variable template.
void setInstantiationOf(VarTemplateDecl *TemplDecl) {
assert(!isa<VarTemplatePartialSpecializationDecl>(this) &&
"A partial specialization cannot be instantiated from a template");
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
"Previously set to a variable template partial specialization!");
SpecializedTemplate = TemplDecl;
Expand Down Expand Up @@ -2949,18 +2944,11 @@ class VarTemplatePartialSpecializationDecl
/// U* X<int>::Inner<T*> = (T*)(0) + 1;
/// \endcode
bool isMemberSpecialization() const {
const auto *First =
cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
return InstantiatedFromMember.getInt();
}

/// Note that this member template is a specialization.
void setMemberSpecialization() {
auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
}
void setMemberSpecialization() { return InstantiatedFromMember.setInt(true); }

SourceRange getSourceRange() const override LLVM_READONLY;

Expand Down
9 changes: 9 additions & 0 deletions clang/include/clang/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -2170,11 +2170,13 @@ class SYCLUniqueStableNameExpr final : public Expr {
class ParenExpr : public Expr {
SourceLocation L, R;
Stmt *Val;

public:
ParenExpr(SourceLocation l, SourceLocation r, Expr *val)
: Expr(ParenExprClass, val->getType(), val->getValueKind(),
val->getObjectKind()),
L(l), R(r), Val(val) {
ParenExprBits.ProducedByFoldExpansion = false;
setDependence(computeDependence(this));
}

Expand Down Expand Up @@ -2206,6 +2208,13 @@ class ParenExpr : public Expr {
const_child_range children() const {
return const_child_range(&Val, &Val + 1);
}

bool isProducedByFoldExpansion() const {
return ParenExprBits.ProducedByFoldExpansion != 0;
}
void setIsProducedByFoldExpansion(bool ProducedByFoldExpansion = true) {
ParenExprBits.ProducedByFoldExpansion = ProducedByFoldExpansion;
}
};

/// UnaryOperator - This represents the unary-expression's (except sizeof and
Expand Down
13 changes: 13 additions & 0 deletions clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -719,6 +719,18 @@ class alignas(void *) Stmt {
unsigned Kind : 3;
};

class ParenExprBitfields {
friend class ASTStmtReader;
friend class ASTStmtWriter;
friend class ParenExpr;

LLVM_PREFERRED_TYPE(ExprBitfields)
unsigned : NumExprBits;

LLVM_PREFERRED_TYPE(bool)
unsigned ProducedByFoldExpansion : 1;
};

class StmtExprBitfields {
friend class ASTStmtReader;
friend class StmtExpr;
Expand Down Expand Up @@ -1241,6 +1253,7 @@ class alignas(void *) Stmt {
GenericSelectionExprBitfields GenericSelectionExprBits;
PseudoObjectExprBitfields PseudoObjectExprBits;
SourceLocExprBitfields SourceLocExprBits;
ParenExprBitfields ParenExprBits;

// GNU Extensions.
StmtExprBitfields StmtExprBits;
Expand Down
11 changes: 4 additions & 7 deletions clang/include/clang/Basic/PlistSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,10 @@ using FIDMap = llvm::DenseMap<FileID, unsigned>;

inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
FileID FID) {
FIDMap::iterator I = FIDs.find(FID);
if (I != FIDs.end())
return I->second;
unsigned NewValue = V.size();
FIDs[FID] = NewValue;
V.push_back(FID);
return NewValue;
auto [I, Inserted] = FIDs.try_emplace(FID, V.size());
if (Inserted)
V.push_back(FID);
return I->second;
}

inline unsigned AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Basic/riscv_vector.td
Original file line number Diff line number Diff line change
Expand Up @@ -2564,7 +2564,7 @@ let HasMasked = false, HasVL = false, IRName = "" in {

return Builder.CreateIntrinsic(Intrinsic::riscv_tuple_extract,
{ResultType, Ops[0]->getType()},
{Ops[0], Builder.CreateZExt(Ops[1],
{Ops[0], Builder.CreateTrunc(Ops[1],
Builder.getInt32Ty())});
}
}] in {
Expand Down Expand Up @@ -2606,7 +2606,7 @@ let HasMasked = false, HasVL = false, IRName = "" in {
return Builder.CreateIntrinsic(Intrinsic::riscv_tuple_insert,
{ResultType, Ops[2]->getType()},
{Ops[0], Ops[2],
Builder.CreateZExt(Ops[1],Builder.getInt32Ty())});
Builder.CreateTrunc(Ops[1],Builder.getInt32Ty())});
}
}] in {
foreach dst_lmul = ["(LFixedLog2LMUL:1)", "(LFixedLog2LMUL:2)", "(LFixedLog2LMUL:3)"] in {
Expand Down
62 changes: 62 additions & 0 deletions clang/include/clang/CIR/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
InheritParentConfig: true
Checks: >
-misc-const-correctness,
-llvm-header-guard,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-suspicious-semicolon,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-unused-raii,
bugprone-unused-return-value,
misc-redundant-expression,
misc-static-assert,
misc-unused-using-decls,
modernize-use-bool-literals,
modernize-loop-convert,
modernize-make-unique,
modernize-raw-string-literal,
modernize-use-equals-default,
modernize-use-default-member-init,
modernize-use-emplace,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-no-automatic-move,
performance-trivially-destructible,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-identifier-naming,
readability-inconsistent-declaration-parameter-name,
readability-misleading-indentation,
readability-redundant-control-flow,
readability-redundant-smartptr-get,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-use-anyofallof
CheckOptions:
- key: readability-identifier-naming.MemberCase
value: camelBack
- key: readability-identifier-naming.ParameterCase
value: camelBack
- key: readability-identifier-naming.VariableCase
value: camelBack
53 changes: 53 additions & 0 deletions clang/include/clang/CIRFrontendAction/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
InheritParentConfig: true
Checks: >
-misc-const-correctness,
-llvm-header-guard,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-suspicious-semicolon,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-unused-raii,
bugprone-unused-return-value,
misc-redundant-expression,
misc-static-assert,
misc-unused-using-decls,
modernize-use-bool-literals,
modernize-loop-convert,
modernize-make-unique,
modernize-raw-string-literal,
modernize-use-equals-default,
modernize-use-default-member-init,
modernize-use-emplace,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-no-automatic-move,
performance-trivially-destructible,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-identifier-naming,
readability-inconsistent-declaration-parameter-name,
readability-misleading-indentation,
readability-redundant-control-flow,
readability-redundant-smartptr-get,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-use-anyofallof
13 changes: 7 additions & 6 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ struct FormatStyle {
/// Don't align array initializer columns.
AIAS_None
};
/// if not ``None``, when using initialization for an array of structs
/// If not ``None``, when using initialization for an array of structs
/// aligns the fields into columns.
///
/// \note
Expand All @@ -145,11 +145,12 @@ struct FormatStyle {
/// Alignment options.
///
/// They can also be read as a whole for compatibility. The choices are:
/// - None
/// - Consecutive
/// - AcrossEmptyLines
/// - AcrossComments
/// - AcrossEmptyLinesAndComments
///
/// * ``None``
/// * ``Consecutive``
/// * ``AcrossEmptyLines``
/// * ``AcrossComments``
/// * ``AcrossEmptyLinesAndComments``
///
/// For example, to align across empty lines and not across comments, either
/// of these work.
Expand Down
25 changes: 6 additions & 19 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -11325,9 +11325,9 @@ class Sema final : public SemaBase {
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists,
SkipBodyInfo *SkipBody = nullptr);
SourceLocation FriendLoc,
ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr);

/// Translates template arguments as provided by the parser
/// into template arguments used by semantic analysis.
Expand Down Expand Up @@ -11366,7 +11366,8 @@ class Sema final : public SemaBase {
DeclResult ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization);
StorageClass SC, bool IsPartialSpecialization,
bool IsMemberSpecialization);

/// Get the specialization of the given variable template corresponding to
/// the specified argument list, or a null-but-valid result if the arguments
Expand Down Expand Up @@ -13017,28 +13018,14 @@ class Sema final : public SemaBase {
/// dealing with a specialization. This is only relevant for function
/// template specializations.
///
/// \param Pattern If non-NULL, indicates the pattern from which we will be
/// instantiating the definition of the given declaration, \p ND. This is
/// used to determine the proper set of template instantiation arguments for
/// friend function template specializations.
///
/// \param ForConstraintInstantiation when collecting arguments,
/// ForConstraintInstantiation indicates we should continue looking when
/// encountering a lambda generic call operator, and continue looking for
/// arguments on an enclosing class template.
///
/// \param SkipForSpecialization when specified, any template specializations
/// in a traversal would be ignored.
/// \param ForDefaultArgumentSubstitution indicates we should continue looking
/// when encountering a specialized member function template, rather than
/// returning immediately.
MultiLevelTemplateArgumentList getTemplateInstantiationArgs(
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
bool ForConstraintInstantiation = false,
bool SkipForSpecialization = false,
bool ForDefaultArgumentSubstitution = false);
bool RelativeToPrimary = false, bool ForConstraintInstantiation = false);

/// RAII object to handle the state changes required to synthesize
/// a function body.
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14325,9 +14325,17 @@ void ASTContext::getFunctionFeatureMap(llvm::StringMap<bool> &FeatureMap,
Target->initFeatureMap(FeatureMap, getDiagnostics(), TargetCPU, Features);
}
} else if (const auto *TV = FD->getAttr<TargetVersionAttr>()) {
llvm::SmallVector<StringRef, 8> Feats;
TV->getFeatures(Feats);
std::vector<std::string> Features = getFMVBackendFeaturesFor(Feats);
std::vector<std::string> Features;
if (Target->getTriple().isRISCV()) {
ParsedTargetAttr ParsedAttr = Target->parseTargetAttr(TV->getName());
Features.insert(Features.begin(), ParsedAttr.Features.begin(),
ParsedAttr.Features.end());
} else {
assert(Target->getTriple().isAArch64());
llvm::SmallVector<StringRef, 8> Feats;
TV->getFeatures(Feats);
Features = getFMVBackendFeaturesFor(Feats);
}
Features.insert(Features.begin(),
Target->getTargetOpts().FeaturesAsWritten.begin(),
Target->getTargetOpts().FeaturesAsWritten.end());
Expand Down
10 changes: 7 additions & 3 deletions clang/lib/AST/ByteCode/InterpBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1184,6 +1184,10 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
QualType CallType = Call->getType();
if (!CallType->isIntegerType())
return false;

PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));

Expand All @@ -1197,7 +1201,7 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
if (Index < BitWidth)
Val.clearHighBits(BitWidth - Index);

pushInteger(S, Val, Call->getType());
pushInteger(S, Val, CallType);
return true;
}

Expand All @@ -1210,7 +1214,7 @@ static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
return false;

APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
pushInteger(S, Val.countLeadingZeros(), Call->getType());
pushInteger(S, Val.countLeadingZeros(), CallType);
return true;
}

Expand All @@ -1223,7 +1227,7 @@ static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
return false;

APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
pushInteger(S, Val.countTrailingZeros(), Call->getType());
pushInteger(S, Val.countTrailingZeros(), CallType);
return true;
}

Expand Down
49 changes: 30 additions & 19 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2696,21 +2696,27 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {
if (isTemplateInstantiation(VDTemplSpec->getTemplateSpecializationKind())) {
auto From = VDTemplSpec->getInstantiatedFrom();
if (auto *VTD = From.dyn_cast<VarTemplateDecl *>()) {
while (!VTD->isMemberSpecialization()) {
auto *NewVTD = VTD->getInstantiatedFromMemberTemplate();
if (!NewVTD)
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
break;
VTD = NewVTD;
}
return getDefinitionOrSelf(VTD->getTemplatedDecl());
}
if (auto *VTPSD =
From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {
while (!VTPSD->isMemberSpecialization()) {
auto *NewVTPSD = VTPSD->getInstantiatedFromMember();
if (!NewVTPSD)
while (true) {
VTPSD = VTPSD->getMostRecentDecl();
if (VTPSD->isMemberSpecialization())
break;
if (auto *NewVTPSD = VTPSD->getInstantiatedFromMember())
VTPSD = NewVTPSD;
else
break;
VTPSD = NewVTPSD;
}
return getDefinitionOrSelf<VarDecl>(VTPSD);
}
Expand All @@ -2719,15 +2725,17 @@ VarDecl *VarDecl::getTemplateInstantiationPattern() const {

// If this is the pattern of a variable template, find where it was
// instantiated from. FIXME: Is this necessary?
if (VarTemplateDecl *VarTemplate = VD->getDescribedVarTemplate()) {
while (!VarTemplate->isMemberSpecialization()) {
auto *NewVT = VarTemplate->getInstantiatedFromMemberTemplate();
if (!NewVT)
if (VarTemplateDecl *VTD = VD->getDescribedVarTemplate()) {
while (true) {
VTD = VTD->getMostRecentDecl();
if (VTD->isMemberSpecialization())
break;
if (auto *NewVTD = VTD->getInstantiatedFromMemberTemplate())
VTD = NewVTD;
else
break;
VarTemplate = NewVT;
}

return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());
return getDefinitionOrSelf(VTD->getTemplatedDecl());
}

if (VD == this)
Expand Down Expand Up @@ -4142,11 +4150,14 @@ FunctionDecl::getTemplateInstantiationPattern(bool ForDefinition) const {
if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {
// If we hit a point where the user provided a specialization of this
// template, we're done looking.
while (!ForDefinition || !Primary->isMemberSpecialization()) {
auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate();
if (!NewPrimary)
while (true) {
Primary = Primary->getMostRecentDecl();
if (ForDefinition && Primary->isMemberSpecialization())
break;
if (auto *NewPrimary = Primary->getInstantiatedFromMemberTemplate())
Primary = NewPrimary;
else
break;
Primary = NewPrimary;
}

return getDefinitionOrSelf(Primary->getTemplatedDecl());
Expand Down
55 changes: 46 additions & 9 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1631,13 +1631,42 @@ static bool allLookupResultsAreTheSame(const DeclContext::lookup_result &R) {
static NamedDecl* getLambdaCallOperatorHelper(const CXXRecordDecl &RD) {
if (!RD.isLambda()) return nullptr;
DeclarationName Name =
RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
DeclContext::lookup_result Calls = RD.lookup(Name);
RD.getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);

DeclContext::lookup_result Calls = RD.lookup(Name);
assert(!Calls.empty() && "Missing lambda call operator!");
assert(allLookupResultsAreTheSame(Calls) &&
"More than one lambda call operator!");
return Calls.front();

// FIXME: If we have multiple call operators, we might be in a situation
// where we merged this lambda with one from another module; in that
// case, return our method (instead of that of the other lambda).
//
// This avoids situations where, given two modules A and B, if we
// try to instantiate A's call operator in a function in B, anything
// in the call operator that relies on local decls in the surrounding
// function will crash because it tries to find A's decls, but we only
// instantiated B's:
//
// template <typename>
// void f() {
// using T = int; // We only instantiate B's version of this.
// auto L = [](T) { }; // But A's call operator would want A's here.
// }
//
// Walk the call operator’s redecl chain to find the one that belongs
// to this module.
//
// TODO: We need to fix this properly (see
// https://github.com/llvm/llvm-project/issues/90154).
Module *M = RD.getOwningModule();
for (Decl *D : Calls.front()->redecls()) {
auto *MD = cast<NamedDecl>(D);
if (MD->getOwningModule() == M)
return MD;
}

llvm_unreachable("Couldn't find our call operator!");
}

FunctionTemplateDecl* CXXRecordDecl::getDependentLambdaCallOperator() const {
Expand Down Expand Up @@ -1994,19 +2023,27 @@ const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {
if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
auto From = TD->getInstantiatedFrom();
if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
if (NewCTD->isMemberSpecialization())
while (true) {
CTD = CTD->getMostRecentDecl();
if (CTD->isMemberSpecialization())
break;
if (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate())
CTD = NewCTD;
else
break;
CTD = NewCTD;
}
return GetDefinitionOrSelf(CTD->getTemplatedDecl());
}
if (auto *CTPSD =
From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
if (NewCTPSD->isMemberSpecialization())
while (true) {
CTPSD = CTPSD->getMostRecentDecl();
if (CTPSD->isMemberSpecialization())
break;
if (auto *NewCTPSD = CTPSD->getInstantiatedFromMemberTemplate())
CTPSD = NewCTPSD;
else
break;
CTPSD = NewCTPSD;
}
return GetDefinitionOrSelf(CTPSD);
}
Expand Down
30 changes: 14 additions & 16 deletions clang/lib/AST/DeclTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,35 +309,35 @@ bool TemplateDecl::isTypeAlias() const {
void RedeclarableTemplateDecl::anchor() {}

RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const {
if (Common)
return Common;
if (CommonBase *C = getCommonPtrInternal())
return C;

// Walk the previous-declaration chain until we either find a declaration
// with a common pointer or we run out of previous declarations.
SmallVector<const RedeclarableTemplateDecl *, 2> PrevDecls;
for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev;
Prev = Prev->getPreviousDecl()) {
if (Prev->Common) {
Common = Prev->Common;
if (CommonBase *C = Prev->getCommonPtrInternal()) {
setCommonPtr(C);
break;
}

PrevDecls.push_back(Prev);
}

// If we never found a common pointer, allocate one now.
if (!Common) {
if (!getCommonPtrInternal()) {
// FIXME: If any of the declarations is from an AST file, we probably
// need an update record to add the common data.

Common = newCommon(getASTContext());
setCommonPtr(newCommon(getASTContext()));
}

// Update any previous declarations we saw with the common pointer.
for (const RedeclarableTemplateDecl *Prev : PrevDecls)
Prev->Common = Common;
Prev->setCommonPtr(getCommonPtrInternal());

return Common;
return getCommonPtrInternal();
}

void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const {
Expand Down Expand Up @@ -463,19 +463,17 @@ void FunctionTemplateDecl::addSpecialization(
}

void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
using Base = RedeclarableTemplateDecl;

// If we haven't created a common pointer yet, then it can just be created
// with the usual method.
if (!Base::Common)
if (!getCommonPtrInternal())
return;

Common *ThisCommon = static_cast<Common *>(Base::Common);
Common *ThisCommon = static_cast<Common *>(getCommonPtrInternal());
Common *PrevCommon = nullptr;
SmallVector<FunctionTemplateDecl *, 8> PreviousDecls;
for (; Prev; Prev = Prev->getPreviousDecl()) {
if (Prev->Base::Common) {
PrevCommon = static_cast<Common *>(Prev->Base::Common);
if (CommonBase *C = Prev->getCommonPtrInternal()) {
PrevCommon = static_cast<Common *>(C);
break;
}
PreviousDecls.push_back(Prev);
Expand All @@ -485,15 +483,15 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) {
// use this common pointer.
if (!PrevCommon) {
for (auto *D : PreviousDecls)
D->Base::Common = ThisCommon;
D->setCommonPtr(ThisCommon);
return;
}

// Ensure we don't leak any important state.
assert(ThisCommon->Specializations.size() == 0 &&
"Can't merge incompatible declarations!");

Base::Common = PrevCommon;
setCommonPtr(PrevCommon);
}

//===----------------------------------------------------------------------===//
Expand Down
19 changes: 18 additions & 1 deletion clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,8 +1164,25 @@ void CXXNameMangler::mangleUnscopedName(GlobalDecl GD, const DeclContext *DC,
// ::= St <unqualified-name> # ::std::

assert(!isa<LinkageSpecDecl>(DC) && "unskipped LinkageSpecDecl");
if (isStdNamespace(DC))
if (isStdNamespace(DC)) {
if (getASTContext().getTargetInfo().getTriple().isOSSolaris()) {
const NamedDecl *ND = cast<NamedDecl>(GD.getDecl());
if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND)) {
// Issue #33114: Need non-standard mangling of std::tm etc. for
// Solaris ABI compatibility.
//
// <substitution> ::= tm # ::std::tm, same for the others
if (const IdentifierInfo *II = RD->getIdentifier()) {
StringRef type = II->getName();
if (llvm::is_contained({"div_t", "ldiv_t", "lconv", "tm"}, type)) {
Out << type.size() << type;
return;
}
}
}
}
Out << "St";
}

mangleUnqualifiedName(GD, DC, AdditionalAbiTags);
}
Expand Down
62 changes: 62 additions & 0 deletions clang/lib/CIR/.clang-tidy
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
InheritParentConfig: true
Checks: >
-misc-const-correctness,
-llvm-header-guard,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-suspicious-semicolon,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-unused-raii,
bugprone-unused-return-value,
misc-redundant-expression,
misc-static-assert,
misc-unused-using-decls,
modernize-use-bool-literals,
modernize-loop-convert,
modernize-make-unique,
modernize-raw-string-literal,
modernize-use-equals-default,
modernize-use-default-member-init,
modernize-use-emplace,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-no-automatic-move,
performance-trivially-destructible,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-identifier-naming,
readability-inconsistent-declaration-parameter-name,
readability-misleading-indentation,
readability-redundant-control-flow,
readability-redundant-smartptr-get,
readability-simplify-boolean-expr,
readability-simplify-subscript-expr,
readability-use-anyofallof
CheckOptions:
- key: readability-identifier-naming.MemberCase
value: camelBack
- key: readability-identifier-naming.ParameterCase
value: camelBack
- key: readability-identifier-naming.VariableCase
value: camelBack
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1096,7 +1096,7 @@ class StructAccessBase
}
const Expr *VisitCastExpr(const CastExpr *E) {
if (E->getCastKind() == CK_LValueToRValue)
return E;
return IsExpectedRecordDecl(E) ? E : nullptr;
return Visit(E->getSubExpr());
}
const Expr *VisitParenExpr(const ParenExpr *E) {
Expand Down
7 changes: 6 additions & 1 deletion clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4287,8 +4287,13 @@ void CodeGenModule::emitMultiVersionFunctions() {
} else if (const auto *TVA = CurFD->getAttr<TargetVersionAttr>()) {
if (TVA->isDefaultVersion() && IsDefined)
ShouldEmitResolver = true;
TVA->getFeatures(Feats);
llvm::Function *Func = createFunction(CurFD);
if (getTarget().getTriple().isRISCV()) {
Feats.push_back(TVA->getName());
} else {
assert(getTarget().getTriple().isAArch64());
TVA->getFeatures(Feats);
}
Options.emplace_back(Func, /*Architecture*/ "", Feats);
} else if (const auto *TC = CurFD->getAttr<TargetClonesAttr>()) {
if (IsDefined)
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/Driver/MultilibBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,11 @@ bool MultilibBuilder::isValid() const {
llvm::StringMap<int> FlagSet;
for (unsigned I = 0, N = Flags.size(); I != N; ++I) {
StringRef Flag(Flags[I]);
llvm::StringMap<int>::iterator SI = FlagSet.find(Flag.substr(1));
auto [SI, Inserted] = FlagSet.try_emplace(Flag.substr(1), I);

assert(StringRef(Flag).front() == '-' || StringRef(Flag).front() == '!');

if (SI == FlagSet.end())
FlagSet[Flag.substr(1)] = I;
else if (Flags[I] != Flags[SI->getValue()])
if (!Inserted && Flags[I] != Flags[SI->getValue()])
return false;
}
return true;
Expand Down
20 changes: 5 additions & 15 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,38 +50,33 @@ template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLines",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossComments",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLinesAndComments",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));

// For backward compatibility.
IO.enumCase(Value, "true",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
/*PadOperators=*/true}));
/*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle({}));
}

Expand Down Expand Up @@ -1445,11 +1440,6 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.AlignAfterOpenBracket = FormatStyle::BAS_Align;
LLVMStyle.AlignArrayOfStructures = FormatStyle::AIAS_None;
LLVMStyle.AlignConsecutiveAssignments = {};
LLVMStyle.AlignConsecutiveAssignments.AcrossComments = false;
LLVMStyle.AlignConsecutiveAssignments.AcrossEmptyLines = false;
LLVMStyle.AlignConsecutiveAssignments.AlignCompound = false;
LLVMStyle.AlignConsecutiveAssignments.AlignFunctionPointers = false;
LLVMStyle.AlignConsecutiveAssignments.Enabled = false;
LLVMStyle.AlignConsecutiveAssignments.PadOperators = true;
LLVMStyle.AlignConsecutiveBitFields = {};
LLVMStyle.AlignConsecutiveDeclarations = {};
Expand Down
26 changes: 14 additions & 12 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4910,6 +4910,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(tok::star) && Right.is(tok::comment))
return true;

const auto *BeforeLeft = Left.Previous;

if (IsCpp) {
if (Left.is(TT_OverloadedOperator) &&
Right.isOneOf(TT_TemplateOpener, TT_TemplateCloser)) {
Expand Down Expand Up @@ -4962,7 +4964,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.Tok.getIdentifierInfo() && Right.Tok.isLiteral())
return true;
} else if (Style.isProto()) {
if (Right.is(tok::period) &&
if (Right.is(tok::period) && !(BeforeLeft && BeforeLeft->is(tok::period)) &&
Left.isOneOf(Keywords.kw_optional, Keywords.kw_required,
Keywords.kw_repeated, Keywords.kw_extend)) {
return true;
Expand Down Expand Up @@ -5070,8 +5072,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
if (Left.is(TT_FatArrow))
return true;
// for await ( ...
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && Left.Previous &&
Left.Previous->is(tok::kw_for)) {
if (Right.is(tok::l_paren) && Left.is(Keywords.kw_await) && BeforeLeft &&
BeforeLeft->is(tok::kw_for)) {
return true;
}
if (Left.is(Keywords.kw_async) && Right.is(tok::l_paren) &&
Expand Down Expand Up @@ -5108,7 +5110,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
// Valid JS method names can include keywords, e.g. `foo.delete()` or
// `bar.instanceof()`. Recognize call positions by preceding period.
if (Left.Previous && Left.Previous->is(tok::period) &&
if (BeforeLeft && BeforeLeft->is(tok::period) &&
Left.Tok.getIdentifierInfo()) {
return false;
}
Expand All @@ -5126,22 +5128,22 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
// "of" is only a keyword if it appears after another identifier
// (e.g. as "const x of y" in a for loop), or after a destructuring
// operation (const [x, y] of z, const {a, b} of c).
(Left.is(Keywords.kw_of) && Left.Previous &&
(Left.Previous->is(tok::identifier) ||
Left.Previous->isOneOf(tok::r_square, tok::r_brace)))) &&
(!Left.Previous || Left.Previous->isNot(tok::period))) {
(Left.is(Keywords.kw_of) && BeforeLeft &&
(BeforeLeft->is(tok::identifier) ||
BeforeLeft->isOneOf(tok::r_square, tok::r_brace)))) &&
(!BeforeLeft || BeforeLeft->isNot(tok::period))) {
return true;
}
if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && Left.Previous &&
Left.Previous->is(tok::period) && Right.is(tok::l_paren)) {
if (Left.isOneOf(tok::kw_for, Keywords.kw_as) && BeforeLeft &&
BeforeLeft->is(tok::period) && Right.is(tok::l_paren)) {
return false;
}
if (Left.is(Keywords.kw_as) &&
Right.isOneOf(tok::l_square, tok::l_brace, tok::l_paren)) {
return true;
}
if (Left.is(tok::kw_default) && Left.Previous &&
Left.Previous->is(tok::kw_export)) {
if (Left.is(tok::kw_default) && BeforeLeft &&
BeforeLeft->is(tok::kw_export)) {
return true;
}
if (Left.is(Keywords.kw_is) && Right.is(tok::l_brace))
Expand Down
36 changes: 22 additions & 14 deletions clang/lib/Headers/avx512fintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,21 @@ typedef enum
__attribute__((__always_inline__, __nodebug__, \
__target__("avx512f,no-evex512")))

#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#define __DEFAULT_FN_ATTRS512_CONSTEXPR __DEFAULT_FN_ATTRS512 constexpr
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS128 constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS128
#define __DEFAULT_FN_ATTRS512_CONSTEXPR __DEFAULT_FN_ATTRS512
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS
#endif

/* Create vectors with repeated elements */

static __inline __m512i __DEFAULT_FN_ATTRS512
_mm512_setzero_si512(void)
{
return __extension__ (__m512i)(__v8di){ 0, 0, 0, 0, 0, 0, 0, 0 };
static __inline __m512i __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_setzero_si512(void) {
return __extension__(__m512i)(__v8di){0, 0, 0, 0, 0, 0, 0, 0};
}

#define _mm512_setzero_epi32 _mm512_setzero_si512
Expand Down Expand Up @@ -256,20 +265,16 @@ _mm512_maskz_broadcastq_epi64 (__mmask8 __M, __m128i __A)
(__v8di) _mm512_setzero_si512());
}


static __inline __m512 __DEFAULT_FN_ATTRS512
_mm512_setzero_ps(void)
{
return __extension__ (__m512){ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
static __inline __m512 __DEFAULT_FN_ATTRS512_CONSTEXPR _mm512_setzero_ps(void) {
return __extension__(__m512){0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
}

#define _mm512_setzero _mm512_setzero_ps

static __inline __m512d __DEFAULT_FN_ATTRS512
_mm512_setzero_pd(void)
{
return __extension__ (__m512d){ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
static __inline __m512d __DEFAULT_FN_ATTRS512_CONSTEXPR
_mm512_setzero_pd(void) {
return __extension__(__m512d){0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
}

static __inline __m512 __DEFAULT_FN_ATTRS512
Expand Down Expand Up @@ -9775,5 +9780,8 @@ _mm512_cvtsi512_si32(__m512i __A) {
#undef __DEFAULT_FN_ATTRS512
#undef __DEFAULT_FN_ATTRS128
#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS512_CONSTEXPR
#undef __DEFAULT_FN_ATTRS128_CONSTEXPR
#undef __DEFAULT_FN_ATTRS_CONSTEXPR

#endif /* __AVX512FINTRIN_H */
25 changes: 15 additions & 10 deletions clang/lib/Headers/avxintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ typedef __bf16 __m256bh __attribute__((__vector_size__(32), __aligned__(32)));
__min_vector_width__(128)))
#endif

#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS128 constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS128
#define __DEFAULT_FN_ATTRS128_CONSTEXPR __DEFAULT_FN_ATTRS
#endif

/* Arithmetic */
/// Adds two 256-bit vectors of [4 x double].
///
Expand Down Expand Up @@ -4331,10 +4339,8 @@ _mm256_set1_epi64x(long long __q)
/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
///
/// \returns A 256-bit vector of [4 x double] with all elements set to zero.
static __inline __m256d __DEFAULT_FN_ATTRS
_mm256_setzero_pd(void)
{
return __extension__ (__m256d){ 0.0, 0.0, 0.0, 0.0 };
static __inline __m256d __DEFAULT_FN_ATTRS_CONSTEXPR _mm256_setzero_pd(void) {
return __extension__(__m256d){0.0, 0.0, 0.0, 0.0};
}

/// Constructs a 256-bit floating-point vector of [8 x float] with all
Expand All @@ -4345,9 +4351,7 @@ _mm256_setzero_pd(void)
/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
///
/// \returns A 256-bit vector of [8 x float] with all elements set to zero.
static __inline __m256 __DEFAULT_FN_ATTRS
_mm256_setzero_ps(void)
{
static __inline __m256 __DEFAULT_FN_ATTRS_CONSTEXPR _mm256_setzero_ps(void) {
return __extension__ (__m256){ 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
}

Expand All @@ -4358,9 +4362,8 @@ _mm256_setzero_ps(void)
/// This intrinsic corresponds to the <c> VXORPS </c> instruction.
///
/// \returns A 256-bit integer vector initialized to zero.
static __inline __m256i __DEFAULT_FN_ATTRS
_mm256_setzero_si256(void)
{
static __inline __m256i __DEFAULT_FN_ATTRS_CONSTEXPR
_mm256_setzero_si256(void) {
return __extension__ (__m256i)(__v4di){ 0, 0, 0, 0 };
}

Expand Down Expand Up @@ -5130,6 +5133,8 @@ _mm256_storeu2_m128i(__m128i_u *__addr_hi, __m128i_u *__addr_lo, __m256i __a)
}

#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR
#undef __DEFAULT_FN_ATTRS128
#undef __DEFAULT_FN_ATTRS128_CONSTEXPR

#endif /* __AVXINTRIN_H */
11 changes: 9 additions & 2 deletions clang/lib/Headers/emmintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ typedef __bf16 __m128bh __attribute__((__vector_size__(16), __aligned__(16)));
__min_vector_width__(128)))
#endif

#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
#endif

#define __trunc64(x) \
(__m64) __builtin_shufflevector((__v2di)(x), __extension__(__v2di){}, 0)
#define __anyext128(x) \
Expand Down Expand Up @@ -1863,7 +1869,7 @@ static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_setr_pd(double __w,
///
/// \returns An initialized 128-bit floating-point vector of [2 x double] with
/// all elements set to zero.
static __inline__ __m128d __DEFAULT_FN_ATTRS _mm_setzero_pd(void) {
static __inline__ __m128d __DEFAULT_FN_ATTRS_CONSTEXPR _mm_setzero_pd(void) {
return __extension__(__m128d){0.0, 0.0};
}

Expand Down Expand Up @@ -3862,7 +3868,7 @@ _mm_setr_epi8(char __b0, char __b1, char __b2, char __b3, char __b4, char __b5,
///
/// \returns An initialized 128-bit integer vector with all elements set to
/// zero.
static __inline__ __m128i __DEFAULT_FN_ATTRS _mm_setzero_si128(void) {
static __inline__ __m128i __DEFAULT_FN_ATTRS_CONSTEXPR _mm_setzero_si128(void) {
return __extension__(__m128i)(__v2di){0LL, 0LL};
}

Expand Down Expand Up @@ -4900,6 +4906,7 @@ void _mm_pause(void);
#undef __anyext128
#undef __trunc64
#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR

#define _MM_SHUFFLE2(x, y) (((x) << 1) | (y))

Expand Down
13 changes: 10 additions & 3 deletions clang/lib/Headers/pmmintrin.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
__min_vector_width__(128)))
#endif

#if defined(__cplusplus) && (__cplusplus >= 201103L)
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS constexpr
#else
#define __DEFAULT_FN_ATTRS_CONSTEXPR __DEFAULT_FN_ATTRS
#endif

/// Loads data from an unaligned memory location to elements in a 128-bit
/// vector.
///
Expand Down Expand Up @@ -128,7 +134,7 @@ _mm_hsub_ps(__m128 __a, __m128 __b)
/// destination.
/// \returns A 128-bit vector of [4 x float] containing the moved and duplicated
/// values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_movehdup_ps(__m128 __a)
{
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 1, 1, 3, 3);
Expand All @@ -149,7 +155,7 @@ _mm_movehdup_ps(__m128 __a)
/// destination.
/// \returns A 128-bit vector of [4 x float] containing the moved and duplicated
/// values.
static __inline__ __m128 __DEFAULT_FN_ATTRS
static __inline__ __m128 __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_moveldup_ps(__m128 __a)
{
return __builtin_shufflevector((__v4sf)__a, (__v4sf)__a, 0, 0, 2, 2);
Expand Down Expand Up @@ -250,7 +256,7 @@ _mm_hsub_pd(__m128d __a, __m128d __b)
/// [127:64] and [63:0] of the destination.
/// \returns A 128-bit vector of [2 x double] containing the moved and
/// duplicated values.
static __inline__ __m128d __DEFAULT_FN_ATTRS
static __inline__ __m128d __DEFAULT_FN_ATTRS_CONSTEXPR
_mm_movedup_pd(__m128d __a)
{
return __builtin_shufflevector((__v2df)__a, (__v2df)__a, 0, 0);
Expand Down Expand Up @@ -303,5 +309,6 @@ _mm_mwait(unsigned __extensions, unsigned __hints)
}

#undef __DEFAULT_FN_ATTRS
#undef __DEFAULT_FN_ATTRS_CONSTEXPR

#endif /* __PMMINTRIN_H */
6 changes: 4 additions & 2 deletions clang/lib/Lex/PPMacroExpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1604,10 +1604,12 @@ static bool isTargetVariantEnvironment(const TargetInfo &TI,
return false;
}

#if defined(__sun__) && defined(__svr4__)
#if defined(__sun__) && defined(__svr4__) && defined(__clang__) && \
__clang__ < 20
// GCC mangles std::tm as tm for binary compatibility on Solaris (Issue
// #33114). We need to match this to allow the std::put_time calls to link
// (PR #99075).
// (PR #99075). clang 20 contains a fix, but the workaround is still needed
// with older versions.
asm("_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"
"RSt8ios_basecPKSt2tmPKcSB_ = "
"_ZNKSt8time_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE3putES3_"
Expand Down
10 changes: 2 additions & 8 deletions clang/lib/Sema/SemaARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,23 +567,17 @@ static bool checkArmStreamingBuiltin(Sema &S, CallExpr *TheCall,
// * When compiling for SVE only, the caller must be in non-streaming mode.
// * When compiling for both SVE and SME, the caller can be in either mode.
if (BuiltinType == SemaARM::VerifyRuntimeMode) {
auto DisableFeatures = [](llvm::StringMap<bool> &Map, StringRef S) {
for (StringRef K : Map.keys())
if (K.starts_with(S))
Map[K] = false;
};

llvm::StringMap<bool> CallerFeatureMapWithoutSVE;
S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSVE, FD);
DisableFeatures(CallerFeatureMapWithoutSVE, "sve");
CallerFeatureMapWithoutSVE["sve"] = false;

// Avoid emitting diagnostics for a function that can never compile.
if (FnType == SemaARM::ArmStreaming && !CallerFeatureMapWithoutSVE["sme"])
return false;

llvm::StringMap<bool> CallerFeatureMapWithoutSME;
S.Context.getFunctionFeatureMap(CallerFeatureMapWithoutSME, FD);
DisableFeatures(CallerFeatureMapWithoutSME, "sme");
CallerFeatureMapWithoutSME["sme"] = false;

// We know the builtin requires either some combination of SVE flags, or
// some combination of SME flags, but we need to figure out which part
Expand Down
29 changes: 12 additions & 17 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -585,8 +585,8 @@ static bool CheckConstraintSatisfaction(

ArrayRef<TemplateArgument> TemplateArgs =
TemplateArgsLists.getNumSubstitutedLevels() > 0
? TemplateArgsLists.getOutermost()
: ArrayRef<TemplateArgument> {};
? TemplateArgsLists.getInnermost()
: ArrayRef<TemplateArgument>{};
Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Sema::InstantiatingTemplate::ConstraintsCheck{},
const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
Expand Down Expand Up @@ -834,7 +834,6 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
return std::nullopt;
Expand Down Expand Up @@ -910,15 +909,13 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
// Figure out the to-translation-unit depth for this function declaration for
// the purpose of seeing if they differ by constraints. This isn't the same as
// getTemplateDepth, because it includes already instantiated parents.
static unsigned
CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
bool SkipForSpecialization = false) {
static unsigned CalculateTemplateDepthForConstraints(Sema &S,
const NamedDecl *ND) {
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
ND, ND->getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true, SkipForSpecialization);
/*ForConstraintInstantiation=*/true);
return MLTAL.getNumLevels();
}

Expand Down Expand Up @@ -957,8 +954,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false,
/*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
/*SkipForSpecialization*/ false);
/*ForConstraintInstantiation=*/true);

if (MLTAL.getNumSubstitutedLevels() == 0)
return ConstrExpr;
Expand Down Expand Up @@ -1068,16 +1064,16 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
assert(FD->getFriendObjectKind() && "Must be a friend!");

FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate();
// The logic for non-templates is handled in ASTContext::isSameEntity, so we
// don't have to bother checking 'DependsOnEnclosingTemplate' for a
// non-function-template.
assert(FD->getDescribedFunctionTemplate() &&
"Non-function templates don't need to be checked");
assert(FTD && "Non-function templates don't need to be checked");

SmallVector<const Expr *, 3> ACs;
FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
FTD->getAssociatedConstraints(ACs);

unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth();
for (const Expr *Constraint : ACs)
if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
Constraint))
Expand Down Expand Up @@ -1524,7 +1520,6 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(),
/*Final=*/false, CSE->getTemplateArguments(),
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);

return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL,
Expand Down Expand Up @@ -1805,8 +1800,8 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1,
return false;
}

unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1);
unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2);

for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
if (Depth2 > Depth1) {
Expand Down
54 changes: 32 additions & 22 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4510,10 +4510,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
adjustDeclContextForDeclaratorDecl(New, Old);

// Ensure the template parameters are compatible.
if (NewTemplate &&
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
if (NewTemplate && !TemplateParameterListsAreEqual(
NewTemplate, NewTemplate->getTemplateParameters(),
OldTemplate, OldTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
return New->setInvalidDecl();

// C++ [class.mem]p1:
Expand Down Expand Up @@ -7663,7 +7663,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
: SourceLocation();
DeclResult Res = ActOnVarTemplateSpecialization(
S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC,
IsPartialSpecialization);
IsPartialSpecialization, IsMemberSpecialization);
if (Res.isInvalid())
return nullptr;
NewVD = cast<VarDecl>(Res.get());
Expand All @@ -7682,6 +7682,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name,
TemplateParams, NewVD);
NewVD->setDescribedVarTemplate(NewTemplate);
// If we are providing an explicit specialization of a static variable
// template, make a note of that.
if (IsMemberSpecialization)
NewTemplate->setMemberSpecialization();
}

// If this decl has an auto type in need of deduction, make a note of the
Expand Down Expand Up @@ -7957,7 +7961,8 @@ NamedDecl *Sema::ActOnVariableDeclarator(
}

if (!R->isIntegralType(Context) && !R->isPointerType()) {
Diag(D.getBeginLoc(), diag::err_asm_bad_register_type);
Diag(TInfo->getTypeLoc().getBeginLoc(), diag::err_asm_bad_register_type)
<< TInfo->getTypeLoc().getSourceRange();
NewVD->setInvalidDecl(true);
}
}
Expand Down Expand Up @@ -8057,12 +8062,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
? TPC_ClassTemplateMember
: TPC_VarTemplate))
NewVD->setInvalidDecl();

// If we are providing an explicit specialization of a static variable
// template, make a note of that.
if (PrevVarTemplate &&
PrevVarTemplate->getInstantiatedFromMemberTemplate())
PrevVarTemplate->setMemberSpecialization();
}
}

Expand Down Expand Up @@ -9869,6 +9868,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
NewFD);
FunctionTemplate->setLexicalDeclContext(CurContext);
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
if (isMemberSpecialization)
FunctionTemplate->setMemberSpecialization();

// For source fidelity, store the other template param lists.
if (TemplateParamLists.size() > 1) {
Expand Down Expand Up @@ -10329,7 +10330,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Handle attributes.
ProcessDeclAttributes(S, NewFD, D);
const auto *NewTVA = NewFD->getAttr<TargetVersionAttr>();
if (NewTVA && !NewTVA->isDefaultVersion() &&
if (Context.getTargetInfo().getTriple().isAArch64() && NewTVA &&
!NewTVA->isDefaultVersion() &&
!Context.getTargetInfo().hasFeature("fmv")) {
// Don't add to scope fmv functions declarations if fmv disabled
AddToScope = false;
Expand Down Expand Up @@ -11038,7 +11040,16 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {

if (TVA) {
llvm::SmallVector<StringRef, 8> Feats;
TVA->getFeatures(Feats);
ParsedTargetAttr ParseInfo;
if (S.getASTContext().getTargetInfo().getTriple().isRISCV()) {
ParseInfo =
S.getASTContext().getTargetInfo().parseTargetAttr(TVA->getName());
for (auto &Feat : ParseInfo.Features)
Feats.push_back(StringRef{Feat}.substr(1));
} else {
assert(S.getASTContext().getTargetInfo().getTriple().isAArch64());
TVA->getFeatures(Feats);
}
for (const auto &Feat : Feats) {
if (!TargetInfo.validateCpuSupports(Feat)) {
S.Diag(FD->getLocation(), diag::err_bad_multiversion_option)
Expand Down Expand Up @@ -11324,7 +11335,8 @@ static bool PreviousDeclsHaveMultiVersionAttribute(const FunctionDecl *FD) {
}

static void patchDefaultTargetVersion(FunctionDecl *From, FunctionDecl *To) {
if (!From->getASTContext().getTargetInfo().getTriple().isAArch64())
if (!From->getASTContext().getTargetInfo().getTriple().isAArch64() &&
!From->getASTContext().getTargetInfo().getTriple().isRISCV())
return;

MultiVersionKind MVKindFrom = From->getMultiVersionKind();
Expand Down Expand Up @@ -12015,10 +12027,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,

// If this is an explicit specialization of a member that is a function
// template, mark it as a member specialization.
if (IsMemberSpecialization &&
NewTemplateDecl->getInstantiatedFromMemberTemplate()) {
NewTemplateDecl->setMemberSpecialization();
assert(OldTemplateDecl->isMemberSpecialization());
if (IsMemberSpecialization) {
// Explicit specializations of a member template do not inherit deleted
// status from the parent member template that they are specializing.
if (OldFD->isDeleted()) {
Expand Down Expand Up @@ -15511,7 +15520,8 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
FD->setInvalidDecl();
}
if (const auto *Attr = FD->getAttr<TargetVersionAttr>()) {
if (!Context.getTargetInfo().hasFeature("fmv") &&
if (Context.getTargetInfo().getTriple().isAArch64() &&
!Context.getTargetInfo().hasFeature("fmv") &&
!Attr->isDefaultVersion()) {
// If function multi versioning disabled skip parsing function body
// defined with non-default target_version attribute
Expand Down Expand Up @@ -17079,8 +17089,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
DeclResult Result = CheckClassTemplate(
S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams,
AS, ModulePrivateLoc,
/*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1,
TemplateParameterLists.data(), SkipBody);
/*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(),
isMemberSpecialization, SkipBody);
return Result.get();
} else {
// The "template<>" header is extraneous.
Expand Down
48 changes: 48 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3040,6 +3040,54 @@ bool Sema::checkTargetVersionAttr(SourceLocation LiteralLoc, Decl *D,
enum SecondParam { None };
enum ThirdParam { Target, TargetClones, TargetVersion };
llvm::SmallVector<StringRef, 8> Features;
if (Context.getTargetInfo().getTriple().isRISCV()) {
llvm::SmallVector<StringRef, 8> AttrStrs;
AttrStr.split(AttrStrs, ';');

bool HasArch = false;
bool HasPriority = false;
bool HasDefault = false;
bool DuplicateAttr = false;
for (auto &AttrStr : AttrStrs) {
// Only support arch=+ext,... syntax.
if (AttrStr.starts_with("arch=+")) {
if (HasArch)
DuplicateAttr = true;
HasArch = true;
ParsedTargetAttr TargetAttr =
Context.getTargetInfo().parseTargetAttr(AttrStr);

if (TargetAttr.Features.empty() ||
llvm::any_of(TargetAttr.Features, [&](const StringRef Ext) {
return !RISCV().isValidFMVExtension(Ext);
}))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;
} else if (AttrStr.starts_with("default")) {
if (HasDefault)
DuplicateAttr = true;
HasDefault = true;
} else if (AttrStr.consume_front("priority=")) {
if (HasPriority)
DuplicateAttr = true;
HasPriority = true;
int Digit;
if (AttrStr.getAsInteger(0, Digit))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;
} else {
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;
}
}

if (((HasPriority || HasArch) && HasDefault) || DuplicateAttr ||
(HasPriority && !HasArch))
return Diag(LiteralLoc, diag::warn_unsupported_target_attribute)
<< Unsupported << None << AttrStr << TargetVersion;

return false;
}
AttrStr.split(Features, "+");
for (auto &CurFeature : Features) {
CurFeature = CurFeature.trim();
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17416,8 +17416,8 @@ DeclResult Sema::ActOnTemplatedFriendTag(
return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS,
Name, NameLoc, Attr, TemplateParams, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
FriendLoc, TempParamLists.size() - 1,
TempParamLists.data())
FriendLoc, TempParamLists.drop_back(),
IsMemberSpecialization)
.get();
} else {
// The "template<>" header is extraneous.
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20223,6 +20223,8 @@ void Sema::DiagnoseEqualityWithExtraParens(ParenExpr *ParenE) {
return;

Expr *E = ParenE->IgnoreParens();
if (ParenE->isProducedByFoldExpansion() && ParenE->getSubExpr() == E)
return;

if (BinaryOperator *opE = dyn_cast<BinaryOperator>(E))
if (opE->getOpcode() == BO_EQ &&
Expand Down
11 changes: 5 additions & 6 deletions clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1048,15 +1048,14 @@ class Analyzer {
}

void checkIndirectCall(CallExpr *Call, QualType CalleeType) {
auto *FPT =
CalleeType->getAs<FunctionProtoType>(); // Null if FunctionType.
FunctionEffectKindSet CalleeEffects;
if (FPT)
CalleeEffects.insert(FPT->getFunctionEffects());
if (FunctionEffectsRef Effects = FunctionEffectsRef::get(CalleeType);
!Effects.empty())
CalleeEffects.insert(Effects);

auto Check1Effect = [&](FunctionEffect Effect, bool Inferring) {
if (FPT == nullptr || Effect.shouldDiagnoseFunctionCall(
/*direct=*/false, CalleeEffects))
if (Effect.shouldDiagnoseFunctionCall(
/*direct=*/false, CalleeEffects))
addViolation(Inferring, Effect, ViolationID::CallsExprWithoutEffect,
Call->getBeginLoc());
};
Expand Down
179 changes: 85 additions & 94 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1795,8 +1795,9 @@ DeclResult Sema::CheckClassTemplate(
CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc,
const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams,
AccessSpecifier AS, SourceLocation ModulePrivateLoc,
SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists,
TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) {
SourceLocation FriendLoc,
ArrayRef<TemplateParameterList *> OuterTemplateParamLists,
bool IsMemberSpecialization, SkipBodyInfo *SkipBody) {
assert(TemplateParams && TemplateParams->size() > 0 &&
"No template parameters");
assert(TUK != TagUseKind::Reference &&
Expand Down Expand Up @@ -1984,19 +1985,6 @@ DeclResult Sema::CheckClassTemplate(
}

if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
// could be dependent.
if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) &&
!TemplateParameterListsAreEqual(
TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext
: CurContext,
CurContext, KWLoc),
TemplateParams, PrevClassTemplate,
PrevClassTemplate->getTemplateParameters(), /*Complain=*/true,
TPL_TemplateMatch))
return true;

// C++ [temp.class]p4:
// In a redeclaration, partial specialization, explicit
// specialization or explicit instantiation of a class template,
Expand All @@ -2011,30 +1999,6 @@ DeclResult Sema::CheckClassTemplate(
Diag(PrevRecordDecl->getLocation(), diag::note_previous_use);
Kind = PrevRecordDecl->getTagKind();
}

// Check for redefinition of this class template.
if (TUK == TagUseKind::Definition) {
if (TagDecl *Def = PrevRecordDecl->getDefinition()) {
// If we have a prior definition that is not visible, treat this as
// simply making that previous definition visible.
NamedDecl *Hidden = nullptr;
if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
SkipBody->ShouldSkip = true;
SkipBody->Previous = Def;
auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
assert(Tmpl && "original definition of a class template is not a "
"class template?");
makeMergedDefinitionVisible(Hidden);
makeMergedDefinitionVisible(Tmpl);
} else {
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
// FIXME: Would it make sense to try to "forget" the previous
// definition, as part of error recovery?
return true;
}
}
}
} else if (PrevDecl) {
// C++ [temp]p5:
// A class template shall not have the same name as any other
Expand All @@ -2046,23 +2010,6 @@ DeclResult Sema::CheckClassTemplate(
return true;
}

// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous class
// template declaration. Skip this check for a friend in a dependent
// context, because the template parameter list might be dependent.
if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) &&
CheckTemplateParameterList(
TemplateParams,
PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate)
: nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
? TPC_ClassTemplateMember
: TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
: TPC_ClassTemplate,
SkipBody))
Invalid = true;

if (SS.isSet()) {
// If the name of the template was qualified, we must be defining the
// template out-of-line.
Expand All @@ -2089,10 +2036,8 @@ DeclResult Sema::CheckClassTemplate(
PrevClassTemplate->getTemplatedDecl() : nullptr,
/*DelayTypeCreation=*/true);
SetNestedNameSpecifier(*this, NewClass, SS);
if (NumOuterTemplateParamLists > 0)
NewClass->setTemplateParameterListsInfo(
Context,
llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists));
if (!OuterTemplateParamLists.empty())
NewClass->setTemplateParameterListsInfo(Context, OuterTemplateParamLists);

// Add alignment attributes if necessary; these attributes are checked when
// the ASTContext lays out the structure.
Expand All @@ -2105,7 +2050,10 @@ DeclResult Sema::CheckClassTemplate(
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
NewClass);

// If we are providing an explicit specialization of a member that is a
// class template, make a note of that.
if (IsMemberSpecialization)
NewTemplate->setMemberSpecialization();
if (ShouldAddRedecl)
NewTemplate->setPreviousDecl(PrevClassTemplate);

Expand All @@ -2120,12 +2068,6 @@ DeclResult Sema::CheckClassTemplate(
assert(T->isDependentType() && "Class template type is not dependent?");
(void)T;

// If we are providing an explicit specialization of a member that is a
// class template, make a note of that.
if (PrevClassTemplate &&
PrevClassTemplate->getInstantiatedFromMemberTemplate())
PrevClassTemplate->setMemberSpecialization();

// Set the access specifier.
if (!Invalid && TUK != TagUseKind::Friend &&
NewTemplate->getDeclContext()->isRecord())
Expand All @@ -2135,8 +2077,62 @@ DeclResult Sema::CheckClassTemplate(
NewClass->setLexicalDeclContext(CurContext);
NewTemplate->setLexicalDeclContext(CurContext);

if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
NewClass->startDefinition();
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
// could be dependent.
if (ShouldAddRedecl && PrevClassTemplate &&
!TemplateParameterListsAreEqual(
NewTemplate, TemplateParams, PrevClassTemplate,
PrevClassTemplate->getTemplateParameters(),
/*Complain=*/true, TPL_TemplateMatch))
return true;

// Check the template parameter list of this declaration, possibly
// merging in the template parameter list from the previous class
// template declaration. Skip this check for a friend in a dependent
// context, because the template parameter list might be dependent.
if (ShouldAddRedecl &&
CheckTemplateParameterList(
TemplateParams,
PrevClassTemplate ? PrevClassTemplate->getTemplateParameters()
: nullptr,
(SS.isSet() && SemanticContext && SemanticContext->isRecord() &&
SemanticContext->isDependentContext())
? TPC_ClassTemplateMember
: TUK == TagUseKind::Friend ? TPC_FriendClassTemplate
: TPC_ClassTemplate,
SkipBody))
Invalid = true;

if (TUK == TagUseKind::Definition) {
if (PrevClassTemplate) {
// Check for redefinition of this class template.
if (TagDecl *Def =
PrevClassTemplate->getTemplatedDecl()->getDefinition()) {
// If we have a prior definition that is not visible, treat this as
// simply making that previous definition visible.
NamedDecl *Hidden = nullptr;
if (SkipBody && !hasVisibleDefinition(Def, &Hidden)) {
SkipBody->ShouldSkip = true;
SkipBody->Previous = Def;
auto *Tmpl = cast<CXXRecordDecl>(Hidden)->getDescribedClassTemplate();
assert(Tmpl && "original definition of a class template is not a "
"class template?");
makeMergedDefinitionVisible(Hidden);
makeMergedDefinitionVisible(Tmpl);
} else {
Diag(NameLoc, diag::err_redefinition) << Name;
Diag(Def->getLocation(), diag::note_previous_definition);
// FIXME: Would it make sense to try to "forget" the previous
// definition, as part of error recovery?
return true;
}
}
}

if (!SkipBody || !SkipBody->ShouldSkip)
NewClass->startDefinition();
}

ProcessDeclAttributeList(S, NewClass, Attr);
ProcessAPINotes(NewClass);
Expand Down Expand Up @@ -4133,7 +4129,8 @@ void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) {
DeclResult Sema::ActOnVarTemplateSpecialization(
Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous,
SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams,
StorageClass SC, bool IsPartialSpecialization) {
StorageClass SC, bool IsPartialSpecialization,
bool IsMemberSpecialization) {
// 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 @@ -4251,17 +4248,16 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
Context, VarTemplate->getDeclContext(), TemplateKWLoc,
TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC,
CanonicalConverted);
// If we are providing an explicit specialization of a member variable
// template specialization, make a note of that.
if (IsMemberSpecialization)
Partial->setMemberSpecialization();
Partial->setTemplateArgsAsWritten(TemplateArgs);

if (!PrevPartial)
VarTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;

// If we are providing an explicit specialization of a member variable
// template specialization, make a note of that.
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
PrevPartial->setMemberSpecialization();

CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
Expand Down Expand Up @@ -5779,9 +5775,7 @@ bool Sema::CheckTemplateArgumentList(

MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
Template, NewContext, /*Final=*/false, CanonicalConverted,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConceptInstantiation=*/true);
/*RelativeToPrimary=*/true, /*ForConceptInstantiation=*/true);
if (EnsureTemplateArgumentListConstraints(
Template, MLTAL,
SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) {
Expand Down Expand Up @@ -8452,15 +8446,12 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template)
<< /*class template*/ 0 << (TUK == TagUseKind::Definition)
<< FixItHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc));
return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS,
ClassTemplate->getIdentifier(),
TemplateNameLoc,
Attr,
TemplateParams,
AS_none, /*ModulePrivateLoc=*/SourceLocation(),
/*FriendLoc*/SourceLocation(),
TemplateParameterLists.size() - 1,
TemplateParameterLists.data());
return CheckClassTemplate(
S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(),
TemplateNameLoc, Attr, TemplateParams, AS_none,
/*ModulePrivateLoc=*/SourceLocation(),
/*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(),
isMemberSpecialization);
}

// Create a new class template partial specialization declaration node.
Expand All @@ -8470,6 +8461,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplatePartialSpecializationDecl::Create(
Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
ClassTemplate, CanonicalConverted, CanonType, PrevPartial);

// If we are providing an explicit specialization of a member class
// template specialization, make a note of that.
if (isMemberSpecialization)
Partial->setMemberSpecialization();
Partial->setTemplateArgsAsWritten(TemplateArgs);
SetNestedNameSpecifier(*this, Partial, SS);
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
Expand All @@ -8481,11 +8477,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;

// If we are providing an explicit specialization of a member class
// template specialization, make a note of that.
if (PrevPartial && PrevPartial->getInstantiatedFromMember())
PrevPartial->setMemberSpecialization();

CheckTemplatePartialSpecialization(Partial);
} else {
// Create a new class template specialization declaration node for
Expand Down Expand Up @@ -11284,8 +11275,8 @@ class ExplicitSpecializationVisibilityChecker {

template<typename TemplDecl>
void checkTemplate(TemplDecl *TD) {
if (TD->isMemberSpecialization()) {
if (!CheckMemberSpecialization(TD))
if (TD->getMostRecentDecl()->isMemberSpecialization()) {
if (!CheckMemberSpecialization(TD->getMostRecentDecl()))
diagnose(TD->getMostRecentDecl(), false);
}
}
Expand Down
33 changes: 3 additions & 30 deletions clang/lib/Sema/SemaTemplateDeduction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3197,20 +3197,6 @@ template<>
struct IsPartialSpecialization<VarTemplatePartialSpecializationDecl> {
static constexpr bool value = true;
};
template <typename TemplateDeclT>
static bool DeducedArgsNeedReplacement(TemplateDeclT *Template) {
return false;
}
template <>
bool DeducedArgsNeedReplacement<VarTemplatePartialSpecializationDecl>(
VarTemplatePartialSpecializationDecl *Spec) {
return !Spec->isClassScopeExplicitSpecialization();
}
template <>
bool DeducedArgsNeedReplacement<ClassTemplatePartialSpecializationDecl>(
ClassTemplatePartialSpecializationDecl *Spec) {
return !Spec->isClassScopeExplicitSpecialization();
}

template <typename TemplateDeclT>
static TemplateDeductionResult
Expand All @@ -3221,23 +3207,10 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template,
llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
Template->getAssociatedConstraints(AssociatedConstraints);

std::optional<ArrayRef<TemplateArgument>> Innermost;
// If we don't need to replace the deduced template arguments,
// we can add them immediately as the inner-most argument list.
if (!DeducedArgsNeedReplacement(Template))
Innermost = CanonicalDeducedArgs;

MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
Template, Template->getDeclContext(), /*Final=*/false, Innermost,
/*RelativeToPrimary=*/true, /*Pattern=*/
nullptr, /*ForConstraintInstantiation=*/true);

// getTemplateInstantiationArgs picks up the non-deduced version of the
// template args when this is a variable template partial specialization and
// not class-scope explicit specialization, so replace with Deduced Args
// instead of adding to inner-most.
if (!Innermost)
MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs);
Template, Template->getDeclContext(), /*Final=*/false,
/*Innermost=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);

if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
Info.getLocation(),
Expand Down
45 changes: 16 additions & 29 deletions clang/lib/Sema/SemaTemplateDeductionGuide.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
}
// Template arguments used to transform the template arguments in
// DeducedResults.
SmallVector<TemplateArgument> TemplateArgsForBuildingRC(
SmallVector<TemplateArgument> InnerArgsForBuildingRC(
F->getTemplateParameters()->size());
// Transform the transformed template args
MultiLevelTemplateArgumentList Args;
Expand All @@ -778,33 +778,30 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
NamedDecl *TP = F->getTemplateParameters()->getParam(Index);
MultiLevelTemplateArgumentList Args;
Args.setKind(TemplateSubstitutionKind::Rewrite);
Args.addOuterTemplateArguments(TemplateArgsForBuildingRC);
Args.addOuterTemplateArguments(InnerArgsForBuildingRC);
// Rebuild the template parameter with updated depth and index.
NamedDecl *NewParam =
transformTemplateParameter(SemaRef, F->getDeclContext(), TP, Args,
/*NewIndex=*/FirstUndeducedParamIdx,
getDepthAndIndex(TP).first + AdjustDepth);
FirstUndeducedParamIdx += 1;
assert(TemplateArgsForBuildingRC[Index].isNull());
TemplateArgsForBuildingRC[Index] =
Context.getInjectedTemplateArg(NewParam);
assert(InnerArgsForBuildingRC[Index].isNull());
InnerArgsForBuildingRC[Index] = Context.getInjectedTemplateArg(NewParam);
continue;
}
TemplateArgumentLoc Input =
SemaRef.getTrivialTemplateArgumentLoc(D, QualType(), SourceLocation{});
TemplateArgumentLoc Output;
if (!SemaRef.SubstTemplateArgument(Input, Args, Output)) {
assert(TemplateArgsForBuildingRC[Index].isNull() &&
assert(InnerArgsForBuildingRC[Index].isNull() &&
"InstantiatedArgs must be null before setting");
TemplateArgsForBuildingRC[Index] = Output.getArgument();
InnerArgsForBuildingRC[Index] = Output.getArgument();
}
}

// A list of template arguments for transforming the require-clause of F.
// It must contain the entire set of template argument lists.
MultiLevelTemplateArgumentList ArgsForBuildingRC;
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);
ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC);
// A list of template arguments for transforming the require-clause using
// the transformed template arguments as the template argument list of F.
//
// For 2), if the underlying deduction guide F is nested in a class template,
// we need the entire template argument list, as the constraint AST in the
// require-clause of F remains completely uninstantiated.
Expand All @@ -827,25 +824,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
// - The occurrence of U in the function parameter is [depth:0, index:0]
// - The template parameter of U is [depth:0, index:0]
//
// We add the outer template arguments which is [int] to the multi-level arg
// list to ensure that the occurrence U in `C<U>` will be replaced with int
// during the substitution.
//
// NOTE: The underlying deduction guide F is instantiated -- either from an
// explicitly-written deduction guide member, or from a constructor.
// getInstantiatedFromMemberTemplate() can only handle the former case, so we
// check the DeclContext kind.
if (F->getLexicalDeclContext()->getDeclKind() ==
clang::Decl::ClassTemplateSpecialization) {
auto OuterLevelArgs = SemaRef.getTemplateInstantiationArgs(
F, F->getLexicalDeclContext(),
/*Final=*/false, /*Innermost=*/std::nullopt,
/*RelativeToPrimary=*/true,
/*Pattern=*/nullptr,
/*ForConstraintInstantiation=*/true);
for (auto It : OuterLevelArgs)
ArgsForBuildingRC.addOuterTemplateArguments(It.Args);
}
MultiLevelTemplateArgumentList ArgsForBuildingRC =
SemaRef.getTemplateInstantiationArgs(F, F->getLexicalDeclContext(),
/*Final=*/false,
/*Innermost=*/InnerArgsForBuildingRC,
/*RelativeToPrimary=*/true,
/*ForConstraintInstantiation=*/true);
ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite);

ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
if (E.isInvalid())
Expand Down
Loading