It caused various breakages; see comments on the PR.
This reverts commit 031b773b01.
This commit is contained in:
parent
099ffad0a7
commit
092f4451ce
70 changed files with 1729 additions and 1624 deletions
|
|
@ -106,7 +106,7 @@ void DefinitionsInHeadersCheck::check(const MatchFinder::MatchResult &Result) {
|
|||
return;
|
||||
diag(FD->getLocation(), "mark the definition as 'inline'",
|
||||
DiagnosticIDs::Note)
|
||||
<< FixItHint::CreateInsertion(FD->getFunctionLocStart(), "inline ");
|
||||
<< FixItHint::CreateInsertion(FD->getInnerLocStart(), "inline ");
|
||||
} else if (const auto *VD = dyn_cast<VarDecl>(ND)) {
|
||||
// C++14 variable templates are allowed.
|
||||
if (VD->getDescribedVarTemplate())
|
||||
|
|
|
|||
|
|
@ -590,28 +590,28 @@ public:
|
|||
|
||||
bool
|
||||
VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) {
|
||||
if (const auto *Info = D->getExplicitInstantiationInfo()) {
|
||||
H.addAngleBracketTokens(Info->TemplateArgsAsWritten->getLAngleLoc(),
|
||||
Info->TemplateArgsAsWritten->getRAngleLoc());
|
||||
} else if (const auto *Info = D->getExplicitSpecializationInfo()) {
|
||||
H.addAngleBracketTokens(Info->TemplateParams->getLAngleLoc(),
|
||||
Info->TemplateParams->getRAngleLoc());
|
||||
H.addAngleBracketTokens(Info->TemplateArgsAsWritten->getLAngleLoc(),
|
||||
Info->TemplateArgsAsWritten->getRAngleLoc());
|
||||
}
|
||||
if (auto *Args = D->getTemplateArgsAsWritten())
|
||||
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitClassTemplatePartialSpecializationDecl(
|
||||
ClassTemplatePartialSpecializationDecl *D) {
|
||||
if (auto *TPL = D->getTemplateParameters())
|
||||
H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
|
||||
if (const auto *Info = D->getExplicitInstantiationInfo()) {
|
||||
H.addAngleBracketTokens(Info->TemplateArgsAsWritten->getLAngleLoc(),
|
||||
Info->TemplateArgsAsWritten->getRAngleLoc());
|
||||
} else if (const auto *Info = D->getExplicitSpecializationInfo()) {
|
||||
H.addAngleBracketTokens(Info->TemplateParams->getLAngleLoc(),
|
||||
Info->TemplateParams->getRAngleLoc());
|
||||
H.addAngleBracketTokens(Info->TemplateArgsAsWritten->getLAngleLoc(),
|
||||
Info->TemplateArgsAsWritten->getRAngleLoc());
|
||||
}
|
||||
if (auto *Args = D->getTemplateArgsAsWritten())
|
||||
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VisitVarTemplatePartialSpecializationDecl(
|
||||
VarTemplatePartialSpecializationDecl *D) {
|
||||
if (auto *TPL = D->getTemplateParameters())
|
||||
H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -625,9 +625,6 @@ public:
|
|||
}
|
||||
|
||||
bool VisitFunctionDecl(FunctionDecl *D) {
|
||||
if (const TemplateParameterList *TPL =
|
||||
D->getTemplateSpecializationParameters())
|
||||
H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
|
||||
if (D->isOverloadedOperator()) {
|
||||
const auto AddOpDeclToken = [&](SourceLocation Loc) {
|
||||
auto &Token = H.addToken(Loc, HighlightingKind::Operator)
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ addInlineIfInHeader(const FunctionDecl *FD) {
|
|||
if (!isHeaderFile(FileName, FD->getASTContext().getLangOpts()))
|
||||
return std::nullopt;
|
||||
|
||||
return tooling::Replacement(SM, FD->getFunctionLocStart(), 0, "inline ");
|
||||
return tooling::Replacement(SM, FD->getInnerLocStart(), 0, "inline ");
|
||||
}
|
||||
|
||||
/// Moves definition of a function/method to its declaration location.
|
||||
|
|
|
|||
|
|
@ -4301,11 +4301,6 @@ bound to ID.
|
|||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('declaresSameEntityAsNode0')"><a name="declaresSameEntityAsNode0Anchor">declaresSameEntityAsNode</a></td><td>const Decl * Other</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="declaresSameEntityAsNode0"><pre>Matches a declaration if it declares the same entity as the node.
|
||||
</pre></td></tr>
|
||||
|
||||
|
||||
<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>></td><td class="name" onclick="toggle('equalsBoundNode1')"><a name="equalsBoundNode1Anchor">equalsBoundNode</a></td><td>std::string ID</td></tr>
|
||||
<tr><td colspan="4" class="doc" id="equalsBoundNode1"><pre>Matches if a node equals a previously bound node.
|
||||
|
||||
|
|
|
|||
|
|
@ -836,7 +836,6 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the
|
|||
- Fixed an alias template CTAD crash.
|
||||
- Correctly diagnose uses of `co_await` / `co_yield` in the default argument of nested function declarations. (#GH98923)
|
||||
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
|
||||
- Fixed clang incorrectly rejecting several cases of out-of-line definitions. (#GH101330)
|
||||
- Clang incorrectly instantiated variable specializations outside of the immediate context. (#GH54439)
|
||||
- Fixed a crash when pack expansions are used as arguments for non-pack parameters of built-in templates. (#GH180307)
|
||||
- Fixed crash instantiating class member specializations.
|
||||
|
|
|
|||
|
|
@ -2131,6 +2131,34 @@ private:
|
|||
/// the DeclaratorDecl base class.
|
||||
DeclarationNameLoc DNLoc;
|
||||
|
||||
/// Specify that this function declaration is actually a function
|
||||
/// template specialization.
|
||||
///
|
||||
/// \param C the ASTContext.
|
||||
///
|
||||
/// \param Template the function template that this function template
|
||||
/// specialization specializes.
|
||||
///
|
||||
/// \param TemplateArgs the template arguments that produced this
|
||||
/// function template specialization from the template.
|
||||
///
|
||||
/// \param InsertPos If non-NULL, the position in the function template
|
||||
/// specialization set where the function template specialization data will
|
||||
/// be inserted.
|
||||
///
|
||||
/// \param TSK the kind of template specialization this is.
|
||||
///
|
||||
/// \param TemplateArgsAsWritten location info of template arguments.
|
||||
///
|
||||
/// \param PointOfInstantiation point at which the function template
|
||||
/// specialization was first instantiated.
|
||||
void setFunctionTemplateSpecialization(
|
||||
ASTContext &C, FunctionTemplateDecl *Template,
|
||||
TemplateArgumentList *TemplateArgs, void *InsertPos,
|
||||
TemplateSpecializationKind TSK,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation PointOfInstantiation);
|
||||
|
||||
/// Specify that this record is an instantiation of the
|
||||
/// member function FD.
|
||||
void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD,
|
||||
|
|
@ -2226,8 +2254,6 @@ public:
|
|||
return SourceLocation();
|
||||
}
|
||||
|
||||
SourceLocation getFunctionLocStart() const;
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
// Function definitions.
|
||||
|
|
@ -3057,14 +3083,9 @@ public:
|
|||
const ASTTemplateArgumentListInfo*
|
||||
getTemplateSpecializationArgsAsWritten() const;
|
||||
|
||||
/// Returns the template parameter list for an explicit specialization.
|
||||
const TemplateParameterList *getTemplateSpecializationParameters() const;
|
||||
|
||||
/// Specify that this function declaration is actually a function
|
||||
/// template specialization.
|
||||
///
|
||||
/// \param C the ASTContext.
|
||||
///
|
||||
/// \param Template the function template that this function template
|
||||
/// specialization specializes.
|
||||
///
|
||||
|
|
@ -3077,30 +3098,25 @@ public:
|
|||
///
|
||||
/// \param TSK the kind of template specialization this is.
|
||||
///
|
||||
/// \param TemplateParams the template parameters if this is an explicit
|
||||
/// specialization.
|
||||
///
|
||||
/// \param TemplateArgsAsWritten location info of template arguments.
|
||||
///
|
||||
/// \param PointOfInstantiation point at which the function template
|
||||
/// specialization was first instantiated.
|
||||
///
|
||||
/// \param AddSpecialization whether to add this specialization to the
|
||||
/// template's specialization set.
|
||||
///
|
||||
void setFunctionTemplateSpecialization(
|
||||
ASTContext &C, FunctionTemplateDecl *Template,
|
||||
TemplateArgumentList *TemplateArgs, void *InsertPos,
|
||||
TemplateSpecializationKind TSK,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation PointOfInstantiation, bool AddSpecialization);
|
||||
FunctionTemplateDecl *Template, TemplateArgumentList *TemplateArgs,
|
||||
void *InsertPos,
|
||||
TemplateSpecializationKind TSK = TSK_ImplicitInstantiation,
|
||||
TemplateArgumentListInfo *TemplateArgsAsWritten = nullptr,
|
||||
SourceLocation PointOfInstantiation = SourceLocation()) {
|
||||
setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs,
|
||||
InsertPos, TSK, TemplateArgsAsWritten,
|
||||
PointOfInstantiation);
|
||||
}
|
||||
|
||||
/// Specifies that this function declaration is actually a
|
||||
/// dependent function template specialization.
|
||||
void setDependentTemplateSpecialization(
|
||||
ASTContext &Context, const UnresolvedSetImpl &Templates,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo *
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ class TemplateParameterList final
|
|||
: private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
|
||||
Expr *> {
|
||||
/// The template argument list of the template parameter list.
|
||||
mutable TemplateArgument *InjectedArgs = nullptr;
|
||||
TemplateArgument *InjectedArgs = nullptr;
|
||||
|
||||
/// The location of the 'template' keyword.
|
||||
SourceLocation TemplateLoc;
|
||||
|
|
@ -200,8 +200,7 @@ public:
|
|||
bool hasAssociatedConstraints() const;
|
||||
|
||||
/// Get the template argument list of the template parameter list.
|
||||
ArrayRef<TemplateArgument>
|
||||
getInjectedTemplateArgs(const ASTContext &Context) const;
|
||||
ArrayRef<TemplateArgument> getInjectedTemplateArgs(const ASTContext &Context);
|
||||
|
||||
SourceLocation getTemplateLoc() const { return TemplateLoc; }
|
||||
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
||||
|
|
@ -476,18 +475,14 @@ class FunctionTemplateSpecializationInfo final
|
|||
/// The function template from which this function template
|
||||
/// specialization was generated.
|
||||
///
|
||||
/// The three bits contain the TemplateSpecializationKind.
|
||||
llvm::PointerIntPair<FunctionTemplateDecl *, 3> Template;
|
||||
/// The two bits contain the top 4 values of TemplateSpecializationKind.
|
||||
llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
|
||||
|
||||
public:
|
||||
/// The template arguments used to produce the function template
|
||||
/// specialization from the function template.
|
||||
TemplateArgumentList *TemplateArguments;
|
||||
|
||||
// The template parameters if this is an explicit specialization.
|
||||
/// FIXME: Normally null; tail-allocate this.
|
||||
const TemplateParameterList *TemplateParameters;
|
||||
|
||||
/// The template arguments as written in the sources, if provided.
|
||||
/// FIXME: Normally null; tail-allocate this.
|
||||
const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
|
||||
|
|
@ -500,14 +495,12 @@ private:
|
|||
FunctionTemplateSpecializationInfo(
|
||||
FunctionDecl *FD, FunctionTemplateDecl *Template,
|
||||
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
|
||||
const TemplateParameterList *TemplateParameters,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation POI, MemberSpecializationInfo *MSInfo)
|
||||
: Function(FD, MSInfo ? true : false), Template(Template, TSK - 1),
|
||||
TemplateArguments(TemplateArgs), TemplateParameters(TemplateParameters),
|
||||
TemplateArguments(TemplateArgs),
|
||||
TemplateArgumentsAsWritten(TemplateArgsAsWritten),
|
||||
PointOfInstantiation(POI) {
|
||||
assert(TemplateParameters == nullptr || TSK == TSK_ExplicitSpecialization);
|
||||
if (MSInfo)
|
||||
getTrailingObjects()[0] = MSInfo;
|
||||
}
|
||||
|
|
@ -520,7 +513,6 @@ public:
|
|||
static FunctionTemplateSpecializationInfo *
|
||||
Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
|
||||
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
|
||||
const TemplateParameterList *TemplateParameters,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation POI, MemberSpecializationInfo *MSInfo);
|
||||
|
||||
|
|
@ -621,8 +613,8 @@ public:
|
|||
/// member class or member enumeration.
|
||||
class MemberSpecializationInfo {
|
||||
// The member declaration from which this member was instantiated, and the
|
||||
// manner in which the instantiation occurred (in the lower three bits).
|
||||
llvm::PointerIntPair<NamedDecl *, 3> MemberAndTSK;
|
||||
// manner in which the instantiation occurred (in the lower two bits).
|
||||
llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK;
|
||||
|
||||
// The point at which this member was first instantiated.
|
||||
SourceLocation PointOfInstantiation;
|
||||
|
|
@ -701,19 +693,14 @@ class DependentFunctionTemplateSpecializationInfo final
|
|||
|
||||
DependentFunctionTemplateSpecializationInfo(
|
||||
const UnresolvedSetImpl &Candidates,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsWritten);
|
||||
|
||||
public:
|
||||
// The template parameters if this is an explicit specialization.
|
||||
const TemplateParameterList *TemplateParameters;
|
||||
|
||||
/// The template arguments as written in the sources, if provided.
|
||||
const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
|
||||
|
||||
static DependentFunctionTemplateSpecializationInfo *
|
||||
Create(ASTContext &Context, const UnresolvedSetImpl &Candidates,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *TemplateArgs);
|
||||
|
||||
/// Returns the candidates for the primary function template.
|
||||
|
|
@ -1018,6 +1005,11 @@ public:
|
|||
return getTemplatedDecl()->isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
bool isCompatibleWithDefinition() const {
|
||||
return getTemplatedDecl()->isInstantiatedFromMemberTemplate() ||
|
||||
isThisDeclarationADefinition();
|
||||
}
|
||||
|
||||
// This bit closely tracks 'RedeclarableTemplateDecl::InstantiatedFromMember',
|
||||
// except this is per declaration, while the redeclarable field is
|
||||
// per chain. This indicates a template redeclaration which
|
||||
|
|
@ -1815,18 +1807,8 @@ struct ExplicitInstantiationInfo {
|
|||
ExplicitInstantiationInfo() = default;
|
||||
};
|
||||
|
||||
struct ExplicitSpecializationInfo {
|
||||
/// The list of template parameters
|
||||
TemplateParameterList *TemplateParams = nullptr;
|
||||
|
||||
/// The template arguments as written.
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten = nullptr;
|
||||
|
||||
ExplicitSpecializationInfo() = default;
|
||||
};
|
||||
|
||||
using SpecializationOrInstantiationInfo =
|
||||
llvm::PointerUnion<ExplicitSpecializationInfo *,
|
||||
llvm::PointerUnion<const ASTTemplateArgumentListInfo *,
|
||||
ExplicitInstantiationInfo *>;
|
||||
|
||||
/// Represents a class template specialization, which refers to
|
||||
|
|
@ -2056,38 +2038,49 @@ public:
|
|||
/// Retrieve the template argument list as written in the sources,
|
||||
/// if any.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
if (const auto *Info = getExplicitSpecializationInfo())
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
return Info->TemplateArgsAsWritten;
|
||||
if (const auto *Info = getExplicitInstantiationInfo())
|
||||
return Info->TemplateArgsAsWritten;
|
||||
return nullptr;
|
||||
return cast<const ASTTemplateArgumentListInfo *>(ExplicitInfo);
|
||||
}
|
||||
|
||||
/// Gets the explicit instantiation info, if present.
|
||||
const ExplicitInstantiationInfo *getExplicitInstantiationInfo() const {
|
||||
return dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
||||
/// Set the template argument list as written in the sources.
|
||||
void
|
||||
setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
Info->TemplateArgsAsWritten = ArgsWritten;
|
||||
else
|
||||
ExplicitInfo = ArgsWritten;
|
||||
}
|
||||
|
||||
/// Sets the explicit instantiation info.
|
||||
void setExplicitInstantiationInfo(
|
||||
SourceLocation ExternKeywordLoc, SourceLocation TemplateKeywordLoc,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten) {
|
||||
auto *Info = new (getASTContext()) ExplicitInstantiationInfo();
|
||||
Info->ExternKeywordLoc = ExternKeywordLoc;
|
||||
Info->TemplateKeywordLoc = TemplateKeywordLoc;
|
||||
Info->TemplateArgsAsWritten = TemplateArgsAsWritten;
|
||||
ExplicitInfo = Info;
|
||||
/// Set the template argument list as written in the sources.
|
||||
void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) {
|
||||
setTemplateArgsAsWritten(
|
||||
ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo));
|
||||
}
|
||||
|
||||
/// Gets the explicit specialization info, if present.
|
||||
const ExplicitSpecializationInfo *getExplicitSpecializationInfo() const {
|
||||
return dyn_cast_if_present<ExplicitSpecializationInfo *>(ExplicitInfo);
|
||||
/// Gets the location of the extern keyword, if present.
|
||||
SourceLocation getExternKeywordLoc() const {
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
return Info->ExternKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the explicit specialization info.
|
||||
void setExplicitSpecializationInfo(
|
||||
TemplateParameterList *TemplateParams,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten);
|
||||
/// Sets the location of the extern keyword.
|
||||
void setExternKeywordLoc(SourceLocation Loc);
|
||||
|
||||
/// Gets the location of the template keyword, if present.
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
return Info->TemplateKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -2112,7 +2105,10 @@ public:
|
|||
};
|
||||
|
||||
class ClassTemplatePartialSpecializationDecl
|
||||
: public ClassTemplateSpecializationDecl {
|
||||
: public ClassTemplateSpecializationDecl {
|
||||
/// The list of template parameters
|
||||
TemplateParameterList *TemplateParams = nullptr;
|
||||
|
||||
/// The class template partial specialization from which this
|
||||
/// class template partial specialization was instantiated.
|
||||
///
|
||||
|
|
@ -2126,7 +2122,6 @@ class ClassTemplatePartialSpecializationDecl
|
|||
ClassTemplatePartialSpecializationDecl(
|
||||
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
|
||||
CanQualType CanonInjectedTST,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl);
|
||||
|
|
@ -2144,9 +2139,7 @@ public:
|
|||
static ClassTemplatePartialSpecializationDecl *
|
||||
Create(ASTContext &Context, TagKind TK, DeclContext *DC,
|
||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||
TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
ClassTemplateDecl *SpecializedTemplate,
|
||||
TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate,
|
||||
ArrayRef<TemplateArgument> Args, CanQualType CanonInjectedTST,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl);
|
||||
|
||||
|
|
@ -2161,10 +2154,7 @@ public:
|
|||
|
||||
/// Get the list of template parameters
|
||||
TemplateParameterList *getTemplateParameters() const {
|
||||
auto *ExplicitSpecInfo = getExplicitSpecializationInfo();
|
||||
assert(ExplicitSpecInfo &&
|
||||
"A partial specialization is always an explicit specialization");
|
||||
return ExplicitSpecInfo->TemplateParams;
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
/// \brief All associated constraints of this partial specialization,
|
||||
|
|
@ -2175,11 +2165,11 @@ public:
|
|||
/// conjunction ("and").
|
||||
void getAssociatedConstraints(
|
||||
llvm::SmallVectorImpl<AssociatedConstraint> &AC) const {
|
||||
getTemplateParameters()->getAssociatedConstraints(AC);
|
||||
TemplateParams->getAssociatedConstraints(AC);
|
||||
}
|
||||
|
||||
bool hasAssociatedConstraints() const {
|
||||
return getTemplateParameters()->hasAssociatedConstraints();
|
||||
return TemplateParams->hasAssociatedConstraints();
|
||||
}
|
||||
|
||||
/// Retrieve the member class template partial specialization from
|
||||
|
|
@ -2816,38 +2806,49 @@ public:
|
|||
/// Retrieve the template argument list as written in the sources,
|
||||
/// if any.
|
||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||
if (const auto *Info = getExplicitSpecializationInfo())
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
return Info->TemplateArgsAsWritten;
|
||||
if (const auto *Info = getExplicitInstantiationInfo())
|
||||
return Info->TemplateArgsAsWritten;
|
||||
return nullptr;
|
||||
return cast<const ASTTemplateArgumentListInfo *>(ExplicitInfo);
|
||||
}
|
||||
|
||||
/// Gets the explicit instantiation info, if present.
|
||||
const ExplicitInstantiationInfo *getExplicitInstantiationInfo() const {
|
||||
return dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
||||
/// Set the template argument list as written in the sources.
|
||||
void
|
||||
setTemplateArgsAsWritten(const ASTTemplateArgumentListInfo *ArgsWritten) {
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
Info->TemplateArgsAsWritten = ArgsWritten;
|
||||
else
|
||||
ExplicitInfo = ArgsWritten;
|
||||
}
|
||||
|
||||
/// Sets the explicit instantiation info.
|
||||
void setExplicitInstantiationInfo(
|
||||
SourceLocation ExternKeywordLoc, SourceLocation TemplateKeywordLoc,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten) {
|
||||
auto *Info = new (getASTContext()) ExplicitInstantiationInfo();
|
||||
Info->ExternKeywordLoc = ExternKeywordLoc;
|
||||
Info->TemplateKeywordLoc = TemplateKeywordLoc;
|
||||
Info->TemplateArgsAsWritten = TemplateArgsAsWritten;
|
||||
ExplicitInfo = Info;
|
||||
/// Set the template argument list as written in the sources.
|
||||
void setTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgsInfo) {
|
||||
setTemplateArgsAsWritten(
|
||||
ASTTemplateArgumentListInfo::Create(getASTContext(), ArgsInfo));
|
||||
}
|
||||
|
||||
/// Gets the explicit specialization info, if present.
|
||||
const ExplicitSpecializationInfo *getExplicitSpecializationInfo() const {
|
||||
return dyn_cast_if_present<ExplicitSpecializationInfo *>(ExplicitInfo);
|
||||
/// Gets the location of the extern keyword, if present.
|
||||
SourceLocation getExternKeywordLoc() const {
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
return Info->ExternKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the explicit specialization info.
|
||||
void setExplicitSpecializationInfo(
|
||||
TemplateParameterList *TemplateParams,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten);
|
||||
/// Sets the location of the extern keyword.
|
||||
void setExternKeywordLoc(SourceLocation Loc);
|
||||
|
||||
/// Gets the location of the template keyword, if present.
|
||||
SourceLocation getTemplateKeywordLoc() const {
|
||||
if (auto *Info =
|
||||
dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo))
|
||||
return Info->TemplateKeywordLoc;
|
||||
return SourceLocation();
|
||||
}
|
||||
|
||||
/// Sets the location of the template keyword.
|
||||
void setTemplateKeywordLoc(SourceLocation Loc);
|
||||
|
||||
SourceRange getSourceRange() const override LLVM_READONLY;
|
||||
|
||||
|
|
@ -2873,6 +2874,9 @@ public:
|
|||
|
||||
class VarTemplatePartialSpecializationDecl
|
||||
: public VarTemplateSpecializationDecl {
|
||||
/// The list of template parameters
|
||||
TemplateParameterList *TemplateParams = nullptr;
|
||||
|
||||
/// The variable template partial specialization from which this
|
||||
/// variable template partial specialization was instantiated.
|
||||
///
|
||||
|
|
@ -2884,7 +2888,6 @@ class VarTemplatePartialSpecializationDecl
|
|||
VarTemplatePartialSpecializationDecl(
|
||||
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, ArrayRef<TemplateArgument> Args);
|
||||
|
||||
|
|
@ -2902,7 +2905,6 @@ public:
|
|||
static VarTemplatePartialSpecializationDecl *
|
||||
Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
VarTemplateDecl *SpecializedTemplate, QualType T,
|
||||
TypeSourceInfo *TInfo, StorageClass S,
|
||||
ArrayRef<TemplateArgument> Args);
|
||||
|
|
@ -2918,10 +2920,7 @@ public:
|
|||
|
||||
/// Get the list of template parameters
|
||||
TemplateParameterList *getTemplateParameters() const {
|
||||
auto *ExplicitSpecInfo = getExplicitSpecializationInfo();
|
||||
assert(ExplicitSpecInfo &&
|
||||
"A partial specialization is always an explicit specialization");
|
||||
return ExplicitSpecInfo->TemplateParams;
|
||||
return TemplateParams;
|
||||
}
|
||||
|
||||
/// Get the template argument list of the template parameter list.
|
||||
|
|
@ -2938,11 +2937,11 @@ public:
|
|||
/// conjunction ("and").
|
||||
void getAssociatedConstraints(
|
||||
llvm::SmallVectorImpl<AssociatedConstraint> &AC) const {
|
||||
getTemplateParameters()->getAssociatedConstraints(AC);
|
||||
TemplateParams->getAssociatedConstraints(AC);
|
||||
}
|
||||
|
||||
bool hasAssociatedConstraints() const {
|
||||
return getTemplateParameters()->hasAssociatedConstraints();
|
||||
return TemplateParams->hasAssociatedConstraints();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the member variable template partial specialization from
|
||||
|
|
|
|||
|
|
@ -417,7 +417,6 @@ class JSONDumper : public ASTNodeTraverser<JSONDumper, JSONNodeDumper> {
|
|||
Visit(Redecl);
|
||||
DumpedAny = true;
|
||||
break;
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitSpecialization:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2002,7 +2002,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
|
|||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_FriendDeclaration:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -2023,7 +2022,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
|
|||
TRY_TO(TraverseDecl(RD));
|
||||
break;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
case TSK_ExplicitSpecialization:
|
||||
|
|
@ -2058,7 +2056,6 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateInstantiations(
|
|||
TRY_TO(TraverseDecl(RD));
|
||||
break;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitSpecialization:
|
||||
break;
|
||||
}
|
||||
|
|
@ -2225,9 +2222,8 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
|
|||
handles traversal of template args and qualifier. \
|
||||
For explicit specializations ("template<> set<int> {...};"), \
|
||||
we traverse template args here since there is no EID. */ \
|
||||
if (const auto *Info = D->getExplicitSpecializationInfo()) { \
|
||||
const auto *ArgsWritten = Info->TemplateArgsAsWritten; \
|
||||
TRY_TO(TraverseTemplateParameterListHelper(Info->TemplateParams)); \
|
||||
if (D->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { \
|
||||
const auto *ArgsWritten = D->getTemplateArgsAsWritten(); \
|
||||
TRY_TO(TraverseTemplateArgumentLocsHelper( \
|
||||
ArgsWritten->getTemplateArgs(), ArgsWritten->NumTemplateArgs)); \
|
||||
} else if (!getDerived().shouldVisitTemplateInstantiations()) { \
|
||||
|
|
|
|||
|
|
@ -5753,11 +5753,6 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) {
|
|||
return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder));
|
||||
}
|
||||
|
||||
/// Matches a declaration if it declares the same entity as the node.
|
||||
AST_MATCHER_P(Decl, declaresSameEntityAsNode, const Decl *, Other) {
|
||||
return clang::declaresSameEntity(&Node, Other);
|
||||
}
|
||||
|
||||
/// Matches if a node equals a previously bound node.
|
||||
///
|
||||
/// Matches a node if it equals the node previously bound to \p ID.
|
||||
|
|
|
|||
|
|
@ -1993,12 +1993,16 @@ getTemplateArgsWritten(const OverloadExpr &OE) {
|
|||
|
||||
inline unsigned
|
||||
getNumTemplateArgsWritten(const ClassTemplateSpecializationDecl &D) {
|
||||
return getTemplateArgsWritten(D).size();
|
||||
if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
|
||||
return Args->getNumTemplateArgs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline unsigned
|
||||
getNumTemplateArgsWritten(const VarTemplateSpecializationDecl &D) {
|
||||
return getTemplateArgsWritten(D).size();
|
||||
if (const ASTTemplateArgumentListInfo *Args = D.getTemplateArgsAsWritten())
|
||||
return Args->getNumTemplateArgs();
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline unsigned getNumTemplateArgsWritten(const FunctionDecl &FD) {
|
||||
|
|
|
|||
|
|
@ -193,8 +193,6 @@ namespace clang {
|
|||
/// This template specialization was implicitly instantiated from a
|
||||
/// template. (C++ [temp.inst]).
|
||||
TSK_ImplicitInstantiation,
|
||||
/// This template is a friend declaration.
|
||||
TSK_FriendDeclaration,
|
||||
/// This template specialization was declared or defined by an
|
||||
/// explicit specialization (C++ [temp.expl.spec]) or partial
|
||||
/// specialization (C++ [temp.class.spec]).
|
||||
|
|
@ -229,7 +227,6 @@ namespace clang {
|
|||
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad template specialization kind");
|
||||
|
|
|
|||
|
|
@ -11748,7 +11748,7 @@ public:
|
|||
TemplateParameterList *MatchTemplateParametersToScopeSpecifier(
|
||||
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
|
||||
const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
|
||||
ArrayRef<TemplateParameterList *> &ParamLists, bool IsFriend,
|
||||
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
|
||||
bool &IsMemberSpecialization, bool &Invalid,
|
||||
bool SuppressDiagnostic = false);
|
||||
|
||||
|
|
@ -11814,7 +11814,8 @@ public:
|
|||
DeclResult CheckVarTemplateId(VarTemplateDecl *Template,
|
||||
SourceLocation TemplateLoc,
|
||||
SourceLocation TemplateNameLoc,
|
||||
const TemplateArgumentListInfo &TemplateArgs);
|
||||
const TemplateArgumentListInfo &TemplateArgs,
|
||||
bool SetWrittenArgs);
|
||||
|
||||
/// Form a reference to the specialization of the given variable template
|
||||
/// corresponding to the specified argument list, or a null-but-valid result
|
||||
|
|
@ -11898,7 +11899,7 @@ public:
|
|||
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
|
||||
SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
|
||||
MultiTemplateParamsArg &TemplateParameterLists,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
SkipBodyInfo *SkipBody = nullptr);
|
||||
|
||||
/// Check the non-type template arguments of a class template
|
||||
|
|
@ -11971,8 +11972,7 @@ public:
|
|||
/// There really isn't any useful analysis we can do here, so we
|
||||
/// just store the information.
|
||||
bool CheckDependentFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous);
|
||||
|
||||
/// Perform semantic analysis for the given function template
|
||||
|
|
@ -11998,9 +11998,8 @@ public:
|
|||
/// declaration with no explicit template argument list that might be
|
||||
/// befriending a function template specialization.
|
||||
bool CheckFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, const TemplateParameterList *TemplateParams,
|
||||
TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous,
|
||||
bool QualifiedFriend = false);
|
||||
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous, bool QualifiedFriend = false);
|
||||
|
||||
/// Perform semantic analysis for the given non-template member
|
||||
/// specialization.
|
||||
|
|
@ -12266,6 +12265,46 @@ public:
|
|||
TPL_TemplateParamsEquivalent,
|
||||
};
|
||||
|
||||
// A struct to represent the 'new' declaration, which is either itself just
|
||||
// the named decl, or the important information we need about it in order to
|
||||
// do constraint comparisons.
|
||||
class TemplateCompareNewDeclInfo {
|
||||
const NamedDecl *ND = nullptr;
|
||||
const DeclContext *DC = nullptr;
|
||||
const DeclContext *LexicalDC = nullptr;
|
||||
SourceLocation Loc;
|
||||
|
||||
public:
|
||||
TemplateCompareNewDeclInfo(const NamedDecl *ND) : ND(ND) {}
|
||||
TemplateCompareNewDeclInfo(const DeclContext *DeclCtx,
|
||||
const DeclContext *LexicalDeclCtx,
|
||||
SourceLocation Loc)
|
||||
|
||||
: DC(DeclCtx), LexicalDC(LexicalDeclCtx), Loc(Loc) {
|
||||
assert(DC && LexicalDC &&
|
||||
"Constructor only for cases where we have the information to put "
|
||||
"in here");
|
||||
}
|
||||
|
||||
// If this was constructed with no information, we cannot do substitution
|
||||
// for constraint comparison, so make sure we can check that.
|
||||
bool isInvalid() const { return !ND && !DC; }
|
||||
|
||||
const NamedDecl *getDecl() const { return ND; }
|
||||
|
||||
bool ContainsDecl(const NamedDecl *ND) const { return this->ND == ND; }
|
||||
|
||||
const DeclContext *getLexicalDeclContext() const {
|
||||
return ND ? ND->getLexicalDeclContext() : LexicalDC;
|
||||
}
|
||||
|
||||
const DeclContext *getDeclContext() const {
|
||||
return ND ? ND->getDeclContext() : DC;
|
||||
}
|
||||
|
||||
SourceLocation getLocation() const { return ND ? ND->getLocation() : Loc; }
|
||||
};
|
||||
|
||||
/// Determine whether the given template parameter lists are
|
||||
/// equivalent.
|
||||
///
|
||||
|
|
@ -12290,11 +12329,19 @@ public:
|
|||
/// \returns True if the template parameter lists are equal, false
|
||||
/// otherwise.
|
||||
bool TemplateParameterListsAreEqual(
|
||||
const Decl *NewInstFrom, TemplateParameterList *New,
|
||||
const Decl *OldInstFrom, TemplateParameterList *Old, bool Complain,
|
||||
const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
|
||||
const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
|
||||
TemplateParameterListEqualKind Kind,
|
||||
SourceLocation TemplateArgLoc = SourceLocation());
|
||||
|
||||
bool TemplateParameterListsAreEqual(
|
||||
TemplateParameterList *New, TemplateParameterList *Old, bool Complain,
|
||||
TemplateParameterListEqualKind Kind,
|
||||
SourceLocation TemplateArgLoc = SourceLocation()) {
|
||||
return TemplateParameterListsAreEqual(nullptr, New, nullptr, Old, Complain,
|
||||
Kind, TemplateArgLoc);
|
||||
}
|
||||
|
||||
/// Check whether a template can be declared within this scope.
|
||||
///
|
||||
/// If the template declaration is valid in this scope, returns
|
||||
|
|
@ -13525,27 +13572,44 @@ public:
|
|||
/// Retrieve the template argument list(s) that should be used to
|
||||
/// instantiate the definition of the given declaration.
|
||||
///
|
||||
/// \param D the declaration for which we are computing template
|
||||
/// \param ND the declaration for which we are computing template
|
||||
/// instantiation arguments.
|
||||
///
|
||||
/// \param Innermost if present, specifies a template argument list for the
|
||||
/// template-like (TemplateDecl or PartialSpec) declaration passed as D.
|
||||
/// \param DC In the event we don't HAVE a declaration yet, we instead provide
|
||||
/// the decl context where it will be created. In this case, the `Innermost`
|
||||
/// should likely be provided. If ND is non-null, this is ignored.
|
||||
///
|
||||
/// \param NumLevels if present, specifies the maximum number of template
|
||||
/// levels of the result. This is useful for instantiating a pattern that has
|
||||
/// already had some levels instantiated. In that case, the Template Depth of
|
||||
/// the pattern can be passed here.
|
||||
/// \param Innermost if non-NULL, specifies a template argument list for the
|
||||
/// template declaration passed as ND.
|
||||
///
|
||||
/// \param SkipInnerNonInstantiated Skips adding template-like levels to the
|
||||
/// result until hitting the first non-template-like level. This is a
|
||||
/// workaround for dealing with the instantiation of the definition of generic
|
||||
/// lambdas, which currently are eagerly substituted.
|
||||
/// \param RelativeToPrimary true if we should get the template
|
||||
/// arguments relative to the primary template, even when we're
|
||||
/// 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 Decl *D,
|
||||
const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false,
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost = std::nullopt,
|
||||
UnsignedOrNone NumLevels = std::nullopt,
|
||||
bool SkipInnerNonInstantiated = false);
|
||||
bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr,
|
||||
bool ForConstraintInstantiation = false,
|
||||
bool SkipForSpecialization = false,
|
||||
bool ForDefaultArgumentSubstitution = false);
|
||||
|
||||
/// RAII object to handle the state changes required to synthesize
|
||||
/// a function body.
|
||||
|
|
@ -14962,13 +15026,14 @@ public:
|
|||
// for figuring out the relative 'depth' of the constraint. The depth of the
|
||||
// 'primary template' and the 'instantiated from' templates aren't necessarily
|
||||
// the same, such as a case when one is a 'friend' defined in a class.
|
||||
bool AreConstraintExpressionsEqual(const Decl *Old, const Expr *OldConstr,
|
||||
const Decl *New, const Expr *NewConstr);
|
||||
bool AreConstraintExpressionsEqual(const NamedDecl *Old,
|
||||
const Expr *OldConstr,
|
||||
const TemplateCompareNewDeclInfo &New,
|
||||
const Expr *NewConstr);
|
||||
|
||||
// Calculates whether the friend function depends on an enclosing template for
|
||||
// the purposes of [temp.friend] p9.
|
||||
bool
|
||||
FriendConstraintsDependOnEnclosingTemplate(const FunctionTemplateDecl *FTD);
|
||||
bool FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD);
|
||||
|
||||
/// \brief Ensure that the given template arguments satisfy the constraints
|
||||
/// associated with the given template, emitting a diagnostic if they do not.
|
||||
|
|
@ -14989,19 +15054,10 @@ public:
|
|||
SourceRange TemplateIDRange);
|
||||
|
||||
bool CheckFunctionTemplateConstraints(SourceLocation PointOfInstantiation,
|
||||
FunctionTemplateDecl *Template,
|
||||
FunctionDecl *Decl,
|
||||
ArrayRef<TemplateArgument> TemplateArgs,
|
||||
ConstraintSatisfaction &Satisfaction);
|
||||
|
||||
// FIXME: Constraints should be always checked before the declaration is
|
||||
// specialized. This function exists to support a workaround for templated
|
||||
// lambdas, where handling the instantiation scope for the captures is not
|
||||
// implemented yet.
|
||||
bool
|
||||
CheckFunctionSpecializationConstraints(SourceLocation PointOfInstantiation,
|
||||
FunctionDecl *Decl,
|
||||
ConstraintSatisfaction &Satisfaction);
|
||||
|
||||
/// \brief Emit diagnostics explaining why a constraint expression was deemed
|
||||
/// unsatisfied.
|
||||
/// \param First whether this is the first time an unsatisfied constraint is
|
||||
|
|
@ -15082,16 +15138,19 @@ private:
|
|||
/// Used by SetupConstraintCheckingTemplateArgumentsAndScope to set up the
|
||||
/// LocalInstantiationScope of the current non-lambda function. For lambdas,
|
||||
/// use LambdaScopeForCallOperatorInstantiationRAII.
|
||||
bool SetupConstraintScope(FunctionDecl *FD,
|
||||
const MultiLevelTemplateArgumentList &MLTAL,
|
||||
LocalInstantiationScope &Scope);
|
||||
bool
|
||||
SetupConstraintScope(FunctionDecl *FD,
|
||||
std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
|
||||
const MultiLevelTemplateArgumentList &MLTAL,
|
||||
LocalInstantiationScope &Scope);
|
||||
|
||||
/// Used during constraint checking, sets up the constraint template argument
|
||||
/// lists, and calls SetupConstraintScope to set up the
|
||||
/// LocalInstantiationScope to have the proper set of ParVarDecls configured.
|
||||
std::optional<MultiLevelTemplateArgumentList>
|
||||
SetupConstraintCheckingTemplateArgumentsAndScope(
|
||||
FunctionDecl *FD, LocalInstantiationScope &Scope);
|
||||
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
|
||||
LocalInstantiationScope &Scope);
|
||||
|
||||
///@}
|
||||
|
||||
|
|
|
|||
|
|
@ -13090,7 +13090,6 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context,
|
|||
case TSK_ExplicitInstantiationDeclaration:
|
||||
return GVA_AvailableExternally;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
External = GVA_DiscardableODR;
|
||||
break;
|
||||
|
|
@ -13280,7 +13279,6 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
|
|||
case TSK_ExplicitInstantiationDeclaration:
|
||||
return GVA_AvailableExternally;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return GVA_DiscardableODR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,7 +140,6 @@ void ASTDumper::dumpTemplateDeclSpecialization(const SpecializationDecl *D,
|
|||
Visit(Redecl);
|
||||
DumpedAny = true;
|
||||
break;
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitSpecialization:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -816,8 +816,6 @@ ASTNodeImporter::ImportFunctionTemplateWithTemplateArgsFromSpecialization(
|
|||
template <>
|
||||
Expected<TemplateParameterList *>
|
||||
ASTNodeImporter::import(TemplateParameterList *From) {
|
||||
if (!From)
|
||||
return nullptr;
|
||||
SmallVector<NamedDecl *, 4> To(From->size());
|
||||
if (Error Err = ImportContainerChecked(*From, To))
|
||||
return std::move(Err);
|
||||
|
|
@ -956,8 +954,7 @@ ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
|
|||
ToInfo = TemplateArgumentLocInfo(*TSIOrErr);
|
||||
else
|
||||
return TSIOrErr.takeError();
|
||||
} else if (Arg.getKind() == TemplateArgument::Template ||
|
||||
Arg.getKind() == TemplateArgument::TemplateExpansion) {
|
||||
} else {
|
||||
auto ToTemplateKWLocOrErr = import(FromInfo.getTemplateKwLoc());
|
||||
if (!ToTemplateKWLocOrErr)
|
||||
return ToTemplateKWLocOrErr.takeError();
|
||||
|
|
@ -975,9 +972,6 @@ ASTNodeImporter::import(const TemplateArgumentLoc &TALoc) {
|
|||
Importer.getToContext(), *ToTemplateKWLocOrErr,
|
||||
*ToTemplateQualifierLocOrErr, *ToTemplateNameLocOrErr,
|
||||
*ToTemplateEllipsisLocOrErr);
|
||||
} else {
|
||||
ToInfo = TemplateArgumentLocInfo(Importer.getToContext(),
|
||||
FromInfo.getTrivialLoc());
|
||||
}
|
||||
|
||||
return TemplateArgumentLoc(Arg, ToInfo);
|
||||
|
|
@ -3670,12 +3664,6 @@ Error ASTNodeImporter::ImportTemplateInformation(
|
|||
Importer.getToContext(), std::get<1>(*FunctionAndArgsOrErr));
|
||||
|
||||
auto *FTSInfo = FromFD->getTemplateSpecializationInfo();
|
||||
|
||||
Expected<TemplateParameterList *> TemplateParamsOrErr =
|
||||
import(FTSInfo->TemplateParameters);
|
||||
if (!TemplateParamsOrErr)
|
||||
return TemplateParamsOrErr.takeError();
|
||||
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
const auto *FromTAArgsAsWritten = FTSInfo->TemplateArgumentsAsWritten;
|
||||
if (FromTAArgsAsWritten)
|
||||
|
|
@ -3692,10 +3680,8 @@ Error ASTNodeImporter::ImportTemplateInformation(
|
|||
|
||||
TemplateSpecializationKind TSK = FTSInfo->getTemplateSpecializationKind();
|
||||
ToFD->setFunctionTemplateSpecialization(
|
||||
Importer.getToContext(), std::get<0>(*FunctionAndArgsOrErr), ToTAList,
|
||||
/*InsertPos=*/nullptr, TSK, *TemplateParamsOrErr,
|
||||
FromTAArgsAsWritten ? &ToTAInfo : nullptr, *POIOrErr,
|
||||
/*AddSpecialization=*/true);
|
||||
std::get<0>(*FunctionAndArgsOrErr), ToTAList, /* InsertPos= */ nullptr,
|
||||
TSK, FromTAArgsAsWritten ? &ToTAInfo : nullptr, *POIOrErr);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
|
|
@ -3709,11 +3695,6 @@ Error ASTNodeImporter::ImportTemplateInformation(
|
|||
return ToFTDOrErr.takeError();
|
||||
}
|
||||
|
||||
Expected<TemplateParameterList *> TemplateParamsOrErr =
|
||||
import(FromInfo->TemplateParameters);
|
||||
if (!TemplateParamsOrErr)
|
||||
return TemplateParamsOrErr.takeError();
|
||||
|
||||
// Import TemplateArgumentListInfo.
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
const auto *FromTAArgsAsWritten = FromInfo->TemplateArgumentsAsWritten;
|
||||
|
|
@ -3723,7 +3704,7 @@ Error ASTNodeImporter::ImportTemplateInformation(
|
|||
return Err;
|
||||
|
||||
ToFD->setDependentTemplateSpecialization(
|
||||
Importer.getToContext(), Candidates, *TemplateParamsOrErr,
|
||||
Importer.getToContext(), Candidates,
|
||||
FromTAArgsAsWritten ? &ToTAInfo : nullptr);
|
||||
return Error::success();
|
||||
}
|
||||
|
|
@ -6544,22 +6525,19 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
|
|||
if (!IdLocOrErr)
|
||||
return IdLocOrErr.takeError();
|
||||
|
||||
// Import TemplateArgumentListInfo.
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (const auto *ASTTemplateArgs = D->getTemplateArgsAsWritten()) {
|
||||
if (Error Err = ImportTemplateArgumentListInfo(*ASTTemplateArgs, ToTAInfo))
|
||||
return std::move(Err);
|
||||
}
|
||||
|
||||
// Create the specialization.
|
||||
ClassTemplateSpecializationDecl *D2 = nullptr;
|
||||
if (PartialSpec) {
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (Error Err = ImportTemplateArgumentListInfo(
|
||||
*cast<ClassTemplatePartialSpecializationDecl>(D)
|
||||
->getTemplateArgsAsWritten(),
|
||||
ToTAInfo))
|
||||
return std::move(Err);
|
||||
|
||||
if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>(
|
||||
D2, D, Importer.getToContext(), D->getTagKind(), DC, *BeginLocOrErr,
|
||||
*IdLocOrErr, ToTPList,
|
||||
ASTTemplateArgumentListInfo::Create(Importer.getToContext(),
|
||||
ToTAInfo),
|
||||
ClassTemplate, ArrayRef(TemplateArgs),
|
||||
*IdLocOrErr, ToTPList, ClassTemplate, ArrayRef(TemplateArgs),
|
||||
/*CanonInjectedTST=*/CanQualType(),
|
||||
cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl)))
|
||||
return D2;
|
||||
|
|
@ -6590,34 +6568,6 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
|
|||
if (!ClassTemplate->findSpecialization(TemplateArgs, InsertPos))
|
||||
// Add this specialization to the class template.
|
||||
ClassTemplate->AddSpecialization(D2, InsertPos);
|
||||
|
||||
if (const auto *Info = D->getExplicitInstantiationInfo()) {
|
||||
auto ExternKeywordLocOrErr = import(Info->ExternKeywordLoc);
|
||||
if (!ExternKeywordLocOrErr)
|
||||
return ExternKeywordLocOrErr.takeError();
|
||||
auto TemplateKeywordLocOrErr = import(Info->TemplateKeywordLoc);
|
||||
if (!TemplateKeywordLocOrErr)
|
||||
return TemplateKeywordLocOrErr.takeError();
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (Error Err = ImportTemplateArgumentListInfo(
|
||||
*Info->TemplateArgsAsWritten, ToTAInfo))
|
||||
return std::move(Err);
|
||||
D2->setExplicitInstantiationInfo(*ExternKeywordLocOrErr,
|
||||
*TemplateKeywordLocOrErr,
|
||||
ASTTemplateArgumentListInfo::Create(
|
||||
Importer.getToContext(), ToTAInfo));
|
||||
} else if (const auto *Info = D->getExplicitSpecializationInfo()) {
|
||||
auto ParamsOrErr = import(Info->TemplateParams);
|
||||
if (!ParamsOrErr)
|
||||
return ParamsOrErr.takeError();
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (Error Err = ImportTemplateArgumentListInfo(
|
||||
*Info->TemplateArgsAsWritten, ToTAInfo))
|
||||
return std::move(Err);
|
||||
D2->setExplicitSpecializationInfo(*ParamsOrErr,
|
||||
ASTTemplateArgumentListInfo::Create(
|
||||
Importer.getToContext(), ToTAInfo));
|
||||
}
|
||||
}
|
||||
|
||||
D2->setSpecializationKind(D->getSpecializationKind());
|
||||
|
|
@ -6644,6 +6594,19 @@ ExpectedDecl ASTNodeImporter::VisitClassTemplateSpecializationDecl(
|
|||
else
|
||||
return LocOrErr.takeError();
|
||||
|
||||
if (D->getTemplateArgsAsWritten())
|
||||
D2->setTemplateArgsAsWritten(ToTAInfo);
|
||||
|
||||
if (auto LocOrErr = import(D->getTemplateKeywordLoc()))
|
||||
D2->setTemplateKeywordLoc(*LocOrErr);
|
||||
else
|
||||
return LocOrErr.takeError();
|
||||
|
||||
if (auto LocOrErr = import(D->getExternKeywordLoc()))
|
||||
D2->setExternKeywordLoc(*LocOrErr);
|
||||
else
|
||||
return LocOrErr.takeError();
|
||||
|
||||
if (D->getPointOfInstantiation().isValid()) {
|
||||
if (auto POIOrErr = import(D->getPointOfInstantiation()))
|
||||
D2->setPointOfInstantiation(*POIOrErr);
|
||||
|
|
@ -6861,6 +6824,12 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
|
||||
VarTemplateSpecializationDecl *D2 = nullptr;
|
||||
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (const auto *Args = D->getTemplateArgsAsWritten()) {
|
||||
if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
|
||||
return std::move(Err);
|
||||
}
|
||||
|
||||
using PartVarSpecDecl = VarTemplatePartialSpecializationDecl;
|
||||
// Create a new specialization.
|
||||
if (auto *FromPartial = dyn_cast<PartVarSpecDecl>(D)) {
|
||||
|
|
@ -6868,16 +6837,9 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
if (!ToTPListOrErr)
|
||||
return ToTPListOrErr.takeError();
|
||||
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (const auto *Args = D->getTemplateArgsAsWritten())
|
||||
if (Error Err = ImportTemplateArgumentListInfo(*Args, ToTAInfo))
|
||||
return std::move(Err);
|
||||
|
||||
PartVarSpecDecl *ToPartial;
|
||||
if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC,
|
||||
*BeginLocOrErr, *IdLocOrErr, *ToTPListOrErr,
|
||||
ASTTemplateArgumentListInfo::Create(
|
||||
Importer.getToContext(), ToTAInfo),
|
||||
VarTemplate, QualType(), nullptr,
|
||||
D->getStorageClass(), TemplateArgs))
|
||||
return ToPartial;
|
||||
|
|
@ -6902,34 +6864,6 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
QualType(), nullptr, D->getStorageClass(),
|
||||
TemplateArgs))
|
||||
return D2;
|
||||
|
||||
if (const auto *Info = D->getExplicitInstantiationInfo()) {
|
||||
auto ExternKeywordLocOrErr = import(Info->ExternKeywordLoc);
|
||||
if (!ExternKeywordLocOrErr)
|
||||
return ExternKeywordLocOrErr.takeError();
|
||||
auto TemplateKeywordLocOrErr = import(Info->TemplateKeywordLoc);
|
||||
if (!TemplateKeywordLocOrErr)
|
||||
return TemplateKeywordLocOrErr.takeError();
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (Error Err = ImportTemplateArgumentListInfo(
|
||||
*Info->TemplateArgsAsWritten, ToTAInfo))
|
||||
return std::move(Err);
|
||||
D2->setExplicitInstantiationInfo(*ExternKeywordLocOrErr,
|
||||
*TemplateKeywordLocOrErr,
|
||||
ASTTemplateArgumentListInfo::Create(
|
||||
Importer.getToContext(), ToTAInfo));
|
||||
} else if (const auto *Info = D->getExplicitSpecializationInfo()) {
|
||||
auto ParamsOrErr = import(Info->TemplateParams);
|
||||
if (!ParamsOrErr)
|
||||
return ParamsOrErr.takeError();
|
||||
TemplateArgumentListInfo ToTAInfo;
|
||||
if (Error Err = ImportTemplateArgumentListInfo(
|
||||
*Info->TemplateArgsAsWritten, ToTAInfo))
|
||||
return std::move(Err);
|
||||
D2->setExplicitSpecializationInfo(*ParamsOrErr,
|
||||
ASTTemplateArgumentListInfo::Create(
|
||||
Importer.getToContext(), ToTAInfo));
|
||||
}
|
||||
}
|
||||
|
||||
// Update InsertPos, because preceding import calls may have invalidated
|
||||
|
|
@ -6956,6 +6890,9 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateSpecializationDecl(
|
|||
|
||||
D2->setSpecializationKind(D->getSpecializationKind());
|
||||
|
||||
if (D->getTemplateArgsAsWritten())
|
||||
D2->setTemplateArgsAsWritten(ToTAInfo);
|
||||
|
||||
if (auto LocOrErr = import(D->getQualifierLoc()))
|
||||
D2->setQualifierInfo(*LocOrErr);
|
||||
else
|
||||
|
|
|
|||
|
|
@ -233,13 +233,11 @@ void DeclInfo::fill() {
|
|||
Kind = FunctionKind;
|
||||
ParamVars = FD->parameters();
|
||||
ReturnType = FD->getReturnType();
|
||||
TemplateParameters = FD->getTemplateSpecializationParameters();
|
||||
if (ArrayRef<TemplateParameterList *> TPLs =
|
||||
FD->getTemplateParameterLists();
|
||||
!TemplateParameters && !TPLs.empty())
|
||||
TemplateParameters = TPLs.back();
|
||||
if (TemplateParameters)
|
||||
ArrayRef<TemplateParameterList *> TPLs = FD->getTemplateParameterLists();
|
||||
if (!TPLs.empty()) {
|
||||
TemplateKind = TemplateSpecialization;
|
||||
TemplateParameters = TPLs.back();
|
||||
}
|
||||
|
||||
if (K == Decl::CXXMethod || K == Decl::CXXConstructor ||
|
||||
K == Decl::CXXDestructor || K == Decl::CXXConversion) {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include "clang/Basic/TargetCXXABI.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/Visibility.h"
|
||||
#include "clang/Lex/Lexer.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
|
@ -4208,7 +4207,6 @@ bool FunctionDecl::isImplicitlyInstantiable() const {
|
|||
case TSK_ExplicitSpecialization:
|
||||
return false;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return true;
|
||||
|
||||
|
|
@ -4329,21 +4327,12 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const TemplateParameterList *
|
||||
FunctionDecl::getTemplateSpecializationParameters() const {
|
||||
if (const auto *Info = getTemplateSpecializationInfo())
|
||||
return Info->TemplateParameters;
|
||||
if (const auto *Info = getDependentSpecializationInfo())
|
||||
return Info->TemplateParameters;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void FunctionDecl::setFunctionTemplateSpecialization(
|
||||
ASTContext &C, FunctionTemplateDecl *Template,
|
||||
TemplateArgumentList *TemplateArgs, void *InsertPos,
|
||||
TemplateSpecializationKind TSK, const TemplateParameterList *TemplateParams,
|
||||
TemplateSpecializationKind TSK,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation PointOfInstantiation, bool AddSpecialization) {
|
||||
SourceLocation PointOfInstantiation) {
|
||||
assert((TemplateOrSpecialization.isNull() ||
|
||||
isa<MemberSpecializationInfo *>(TemplateOrSpecialization)) &&
|
||||
"Member function is already a specialization");
|
||||
|
|
@ -4355,23 +4344,21 @@ void FunctionDecl::setFunctionTemplateSpecialization(
|
|||
"Member specialization must be an explicit specialization");
|
||||
FunctionTemplateSpecializationInfo *Info =
|
||||
FunctionTemplateSpecializationInfo::Create(
|
||||
C, this, Template, TSK, TemplateArgs, TemplateParams,
|
||||
TemplateArgsAsWritten, PointOfInstantiation,
|
||||
C, this, Template, TSK, TemplateArgs, TemplateArgsAsWritten,
|
||||
PointOfInstantiation,
|
||||
dyn_cast_if_present<MemberSpecializationInfo *>(
|
||||
TemplateOrSpecialization));
|
||||
TemplateOrSpecialization = Info;
|
||||
if (AddSpecialization)
|
||||
Template->addSpecialization(Info, InsertPos);
|
||||
Template->addSpecialization(Info, InsertPos);
|
||||
}
|
||||
|
||||
void FunctionDecl::setDependentTemplateSpecialization(
|
||||
ASTContext &Context, const UnresolvedSetImpl &Templates,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *TemplateArgs) {
|
||||
assert(TemplateOrSpecialization.isNull());
|
||||
DependentFunctionTemplateSpecializationInfo *Info =
|
||||
DependentFunctionTemplateSpecializationInfo::Create(
|
||||
Context, Templates, TemplateParams, TemplateArgs);
|
||||
DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
|
||||
TemplateArgs);
|
||||
TemplateOrSpecialization = Info;
|
||||
}
|
||||
|
||||
|
|
@ -4384,22 +4371,19 @@ FunctionDecl::getDependentSpecializationInfo() const {
|
|||
DependentFunctionTemplateSpecializationInfo *
|
||||
DependentFunctionTemplateSpecializationInfo::Create(
|
||||
ASTContext &Context, const UnresolvedSetImpl &Candidates,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *TArgs) {
|
||||
const auto *TArgsWritten =
|
||||
TArgs ? ASTTemplateArgumentListInfo::Create(Context, *TArgs) : nullptr;
|
||||
return new (Context.Allocate(
|
||||
totalSizeToAlloc<FunctionTemplateDecl *>(Candidates.size())))
|
||||
DependentFunctionTemplateSpecializationInfo(Candidates, TemplateParams,
|
||||
TArgsWritten);
|
||||
DependentFunctionTemplateSpecializationInfo(Candidates, TArgsWritten);
|
||||
}
|
||||
|
||||
DependentFunctionTemplateSpecializationInfo::
|
||||
DependentFunctionTemplateSpecializationInfo(
|
||||
const UnresolvedSetImpl &Candidates,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsWritten)
|
||||
: NumCandidates(Candidates.size()), TemplateParameters(TemplateParams),
|
||||
: NumCandidates(Candidates.size()),
|
||||
TemplateArgumentsAsWritten(TemplateArgsWritten) {
|
||||
std::transform(Candidates.begin(), Candidates.end(), getTrailingObjects(),
|
||||
[](NamedDecl *ND) {
|
||||
|
|
@ -4559,17 +4543,6 @@ bool FunctionDecl::isOutOfLine() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
SourceLocation FunctionDecl::getFunctionLocStart() const {
|
||||
if (const TemplateParameterList *TemplateParams =
|
||||
getTemplateSpecializationParameters()) {
|
||||
const ASTContext &Ctx = getASTContext();
|
||||
return Lexer::findNextToken(TemplateParams->getSourceRange().getEnd(),
|
||||
Ctx.getSourceManager(), Ctx.getLangOpts())
|
||||
->getLocation();
|
||||
}
|
||||
return getInnerLocStart();
|
||||
}
|
||||
|
||||
SourceRange FunctionDecl::getSourceRange() const {
|
||||
return SourceRange(getOuterLocStart(), EndRangeLoc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1105,7 +1105,6 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
|||
Out << *Attrs << ' ';
|
||||
|
||||
if (D->getIdentifier()) {
|
||||
// FIXME: Missing template parameter lists.
|
||||
D->getQualifier().print(Out, Policy);
|
||||
Out << *D;
|
||||
|
||||
|
|
|
|||
|
|
@ -245,8 +245,8 @@ bool TemplateParameterList::hasAssociatedConstraints() const {
|
|||
return HasRequiresClause || HasConstrainedParameters;
|
||||
}
|
||||
|
||||
ArrayRef<TemplateArgument> TemplateParameterList::getInjectedTemplateArgs(
|
||||
const ASTContext &Context) const {
|
||||
ArrayRef<TemplateArgument>
|
||||
TemplateParameterList::getInjectedTemplateArgs(const ASTContext &Context) {
|
||||
if (!InjectedArgs) {
|
||||
InjectedArgs = new (Context) TemplateArgument[size()];
|
||||
llvm::transform(*this, InjectedArgs, [&](NamedDecl *ND) {
|
||||
|
|
@ -946,7 +946,6 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
|
|||
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
|
||||
ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
|
||||
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
|
||||
const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI,
|
||||
MemberSpecializationInfo *MSInfo) {
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
|
||||
|
|
@ -957,8 +956,7 @@ FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
|
|||
void *Mem =
|
||||
C.Allocate(totalSizeToAlloc<MemberSpecializationInfo *>(MSInfo ? 1 : 0));
|
||||
return new (Mem) FunctionTemplateSpecializationInfo(
|
||||
FD, Template, TSK, TemplateArgs, TemplateParams, ArgsAsWritten, POI,
|
||||
MSInfo);
|
||||
FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -1052,38 +1050,54 @@ ClassTemplateSpecializationDecl::getSourceRange() const {
|
|||
return CTPSD->getSourceRange();
|
||||
return cast<ClassTemplateDecl *>(Pattern)->getSourceRange();
|
||||
}
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitSpecialization: {
|
||||
const auto *Info = getExplicitSpecializationInfo();
|
||||
auto TPLs = getTemplateParameterLists();
|
||||
return SourceRange(TPLs.empty() ? Info->TemplateParams->getTemplateLoc()
|
||||
: TPLs.front()->getTemplateLoc(),
|
||||
isThisDeclarationADefinition()
|
||||
? CXXRecordDecl::getSourceRange().getEnd()
|
||||
: Info->TemplateArgsAsWritten->getRAngleLoc());
|
||||
SourceRange Range = CXXRecordDecl::getSourceRange();
|
||||
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
|
||||
!isThisDeclarationADefinition() && Args)
|
||||
Range.setEnd(Args->getRAngleLoc());
|
||||
return Range;
|
||||
}
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition: {
|
||||
const auto *Info = getExplicitInstantiationInfo();
|
||||
return SourceRange(Info->ExternKeywordLoc.isValid()
|
||||
? Info->ExternKeywordLoc
|
||||
: Info->TemplateKeywordLoc,
|
||||
Info->TemplateArgsAsWritten->getRAngleLoc());
|
||||
SourceRange Range = CXXRecordDecl::getSourceRange();
|
||||
if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
|
||||
Range.setBegin(ExternKW);
|
||||
else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
|
||||
TemplateKW.isValid())
|
||||
Range.setBegin(TemplateKW);
|
||||
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
|
||||
Range.setEnd(Args->getRAngleLoc());
|
||||
return Range;
|
||||
}
|
||||
}
|
||||
llvm_unreachable("unhandled template specialization kind");
|
||||
}
|
||||
|
||||
void ClassTemplateSpecializationDecl::setExplicitSpecializationInfo(
|
||||
TemplateParameterList *TemplateParams,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten) {
|
||||
auto *Info = new (getASTContext()) ExplicitSpecializationInfo();
|
||||
Info->TemplateParams = TemplateParams;
|
||||
Info->TemplateArgsAsWritten = TemplateArgsAsWritten;
|
||||
ExplicitInfo = Info;
|
||||
void ClassTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
|
||||
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
||||
if (!Info) {
|
||||
// Don't allocate if the location is invalid.
|
||||
if (Loc.isInvalid())
|
||||
return;
|
||||
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
||||
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
||||
ExplicitInfo = Info;
|
||||
}
|
||||
Info->ExternKeywordLoc = Loc;
|
||||
}
|
||||
|
||||
if (AdoptTemplateParameterList(TemplateParams, this))
|
||||
setInvalidDecl();
|
||||
void ClassTemplateSpecializationDecl::setTemplateKeywordLoc(
|
||||
SourceLocation Loc) {
|
||||
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
||||
if (!Info) {
|
||||
// Don't allocate if the location is invalid.
|
||||
if (Loc.isInvalid())
|
||||
return;
|
||||
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
||||
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
||||
ExplicitInfo = Info;
|
||||
}
|
||||
Info->TemplateKeywordLoc = Loc;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -1154,7 +1168,6 @@ void ClassTemplatePartialSpecializationDecl::anchor() {}
|
|||
ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
|
||||
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
|
||||
CanQualType CanonInjectedTST,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl)
|
||||
|
|
@ -1163,24 +1176,25 @@ ClassTemplatePartialSpecializationDecl::ClassTemplatePartialSpecializationDecl(
|
|||
// Tracking StrictPackMatch for Partial
|
||||
// Specializations is not needed.
|
||||
SpecializedTemplate, Args, /*StrictPackMatch=*/false, PrevDecl),
|
||||
InstantiatedFromMember(nullptr, false),
|
||||
TemplateParams(Params), InstantiatedFromMember(nullptr, false),
|
||||
CanonInjectedTST(CanonInjectedTST) {
|
||||
setSpecializationKind(TSK_ExplicitSpecialization);
|
||||
setExplicitSpecializationInfo(Params, ArgsAsWritten);
|
||||
if (AdoptTemplateParameterList(Params, this))
|
||||
setInvalidDecl();
|
||||
}
|
||||
|
||||
ClassTemplatePartialSpecializationDecl *
|
||||
ClassTemplatePartialSpecializationDecl::Create(
|
||||
ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
ClassTemplateDecl *SpecializedTemplate, ArrayRef<TemplateArgument> Args,
|
||||
CanQualType CanonInjectedTST,
|
||||
ClassTemplatePartialSpecializationDecl *PrevDecl) {
|
||||
assert(!Params->empty() && "template with no template parameters");
|
||||
return new (Context, DC) ClassTemplatePartialSpecializationDecl(
|
||||
Context, TK, DC, StartLoc, IdLoc, Params, ArgsAsWritten,
|
||||
SpecializedTemplate, Args, CanonInjectedTST, PrevDecl);
|
||||
auto *Result = new (Context, DC) ClassTemplatePartialSpecializationDecl(
|
||||
Context, TK, DC, StartLoc, IdLoc, Params, SpecializedTemplate, Args,
|
||||
CanonInjectedTST, PrevDecl);
|
||||
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
||||
return Result;
|
||||
}
|
||||
|
||||
ClassTemplatePartialSpecializationDecl *
|
||||
|
|
@ -1207,7 +1221,11 @@ SourceRange ClassTemplatePartialSpecializationDecl::getSourceRange() const {
|
|||
getInstantiatedFromMember();
|
||||
MT && !isMemberSpecialization())
|
||||
return MT->getSourceRange();
|
||||
return ClassTemplateSpecializationDecl::getSourceRange();
|
||||
SourceRange Range = ClassTemplateSpecializationDecl::getSourceRange();
|
||||
if (const TemplateParameterList *TPL = getTemplateParameters();
|
||||
TPL && getTemplateParameterLists().empty())
|
||||
Range.setBegin(TPL->getTemplateLoc());
|
||||
return Range;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -1466,11 +1484,8 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
|
|||
}
|
||||
return VTD->getCanonicalDecl()->getSourceRange();
|
||||
}
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitSpecialization: {
|
||||
SourceRange Range = VarDecl::getSourceRange();
|
||||
if (const auto *Info = getExplicitSpecializationInfo())
|
||||
Range.setBegin(Info->TemplateParams->getTemplateLoc());
|
||||
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten();
|
||||
!hasInit() && Args)
|
||||
Range.setEnd(Args->getRAngleLoc());
|
||||
|
|
@ -1478,11 +1493,10 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
|
|||
}
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition: {
|
||||
const auto *Info = getExplicitInstantiationInfo();
|
||||
SourceRange Range = VarDecl::getSourceRange();
|
||||
if (SourceLocation ExternKW = Info->ExternKeywordLoc; ExternKW.isValid())
|
||||
if (SourceLocation ExternKW = getExternKeywordLoc(); ExternKW.isValid())
|
||||
Range.setBegin(ExternKW);
|
||||
else if (SourceLocation TemplateKW = Info->TemplateKeywordLoc;
|
||||
else if (SourceLocation TemplateKW = getTemplateKeywordLoc();
|
||||
TemplateKW.isValid())
|
||||
Range.setBegin(TemplateKW);
|
||||
if (const ASTTemplateArgumentListInfo *Args = getTemplateArgsAsWritten())
|
||||
|
|
@ -1493,16 +1507,30 @@ SourceRange VarTemplateSpecializationDecl::getSourceRange() const {
|
|||
llvm_unreachable("unhandled template specialization kind");
|
||||
}
|
||||
|
||||
void VarTemplateSpecializationDecl::setExplicitSpecializationInfo(
|
||||
TemplateParameterList *TemplateParams,
|
||||
const ASTTemplateArgumentListInfo *TemplateArgsAsWritten) {
|
||||
auto *Info = new (getASTContext()) ExplicitSpecializationInfo();
|
||||
Info->TemplateParams = TemplateParams;
|
||||
Info->TemplateArgsAsWritten = TemplateArgsAsWritten;
|
||||
ExplicitInfo = Info;
|
||||
void VarTemplateSpecializationDecl::setExternKeywordLoc(SourceLocation Loc) {
|
||||
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
||||
if (!Info) {
|
||||
// Don't allocate if the location is invalid.
|
||||
if (Loc.isInvalid())
|
||||
return;
|
||||
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
||||
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
||||
ExplicitInfo = Info;
|
||||
}
|
||||
Info->ExternKeywordLoc = Loc;
|
||||
}
|
||||
|
||||
if (AdoptTemplateParameterList(TemplateParams, getDeclContext()))
|
||||
setInvalidDecl();
|
||||
void VarTemplateSpecializationDecl::setTemplateKeywordLoc(SourceLocation Loc) {
|
||||
auto *Info = dyn_cast_if_present<ExplicitInstantiationInfo *>(ExplicitInfo);
|
||||
if (!Info) {
|
||||
// Don't allocate if the location is invalid.
|
||||
if (Loc.isInvalid())
|
||||
return;
|
||||
Info = new (getASTContext()) ExplicitInstantiationInfo;
|
||||
Info->TemplateArgsAsWritten = getTemplateArgsAsWritten();
|
||||
ExplicitInfo = Info;
|
||||
}
|
||||
Info->TemplateKeywordLoc = Loc;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
@ -1514,28 +1542,28 @@ void VarTemplatePartialSpecializationDecl::anchor() {}
|
|||
VarTemplatePartialSpecializationDecl::VarTemplatePartialSpecializationDecl(
|
||||
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, ArrayRef<TemplateArgument> Args)
|
||||
: VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
|
||||
DC, StartLoc, IdLoc, SpecializedTemplate, T,
|
||||
TInfo, S, Args),
|
||||
InstantiatedFromMember(nullptr, false) {
|
||||
setSpecializationKind(TSK_ExplicitSpecialization);
|
||||
setExplicitSpecializationInfo(Params, ArgsAsWritten);
|
||||
TemplateParams(Params), InstantiatedFromMember(nullptr, false) {
|
||||
if (AdoptTemplateParameterList(Params, DC))
|
||||
setInvalidDecl();
|
||||
}
|
||||
|
||||
VarTemplatePartialSpecializationDecl *
|
||||
VarTemplatePartialSpecializationDecl::Create(
|
||||
ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
|
||||
SourceLocation IdLoc, TemplateParameterList *Params,
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten,
|
||||
VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
|
||||
StorageClass S, ArrayRef<TemplateArgument> Args) {
|
||||
assert(!Params->empty() && "template with no template parameters");
|
||||
return new (Context, DC) VarTemplatePartialSpecializationDecl(
|
||||
Context, DC, StartLoc, IdLoc, Params, ArgsAsWritten, SpecializedTemplate,
|
||||
T, TInfo, S, Args);
|
||||
auto *Result = new (Context, DC) VarTemplatePartialSpecializationDecl(
|
||||
Context, DC, StartLoc, IdLoc, Params, SpecializedTemplate, T, TInfo, S,
|
||||
Args);
|
||||
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
||||
return Result;
|
||||
}
|
||||
|
||||
VarTemplatePartialSpecializationDecl *
|
||||
|
|
@ -1549,7 +1577,11 @@ SourceRange VarTemplatePartialSpecializationDecl::getSourceRange() const {
|
|||
getInstantiatedFromMember();
|
||||
MT && !isMemberSpecialization())
|
||||
return MT->getSourceRange();
|
||||
return VarTemplateSpecializationDecl::getSourceRange();
|
||||
SourceRange Range = VarTemplateSpecializationDecl::getSourceRange();
|
||||
if (const TemplateParameterList *TPL = getTemplateParameters();
|
||||
TPL && getTemplateParameterLists().empty())
|
||||
Range.setBegin(TPL->getTemplateLoc());
|
||||
return Range;
|
||||
}
|
||||
|
||||
static TemplateParameterList *createBuiltinTemplateParameterList(
|
||||
|
|
|
|||
|
|
@ -1131,9 +1131,6 @@ void JSONNodeDumper::VisitExplicitInstantiationDecl(
|
|||
case TSK_ImplicitInstantiation:
|
||||
JOS.attribute("templateSpecializationKind", "implicit_instantiation");
|
||||
break;
|
||||
case TSK_FriendDeclaration:
|
||||
JOS.attribute("templateSpecializationKind", "friend_declaration");
|
||||
break;
|
||||
case TSK_ExplicitSpecialization:
|
||||
JOS.attribute("templateSpecializationKind", "explicit_specialization");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1044,9 +1044,6 @@ void clang::TextNodeDumper::dumpTemplateSpecializationKind(
|
|||
case TSK_ImplicitInstantiation:
|
||||
OS << " implicit_instantiation";
|
||||
break;
|
||||
case TSK_FriendDeclaration:
|
||||
OS << " friend_declaration";
|
||||
break;
|
||||
case TSK_ExplicitSpecialization:
|
||||
OS << " explicit_specialization";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,6 @@ RegistryMaps::RegistryMaps() {
|
|||
//
|
||||
// Other:
|
||||
// equalsNode
|
||||
// declaresSameEntityAsNode
|
||||
|
||||
registerMatcher("mapAnyOf",
|
||||
std::make_unique<internal::MapAnyOfBuilderDescriptor>());
|
||||
|
|
|
|||
|
|
@ -690,7 +690,7 @@ ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) {
|
|||
canResolveToExpr(Exp),
|
||||
parmVarDecl(hasType(nonConstReferenceType())).bind("parm"));
|
||||
const auto IsInstantiated = hasDeclaration(isInstantiated());
|
||||
const auto FuncDecl = hasDeclaration(functionDecl());
|
||||
const auto FuncDecl = hasDeclaration(functionDecl().bind("func"));
|
||||
const auto Matches = match(
|
||||
traverse(
|
||||
TK_AsIs,
|
||||
|
|
@ -704,16 +704,13 @@ ExprMutationAnalyzer::Analyzer::findFunctionArgMutation(const Expr *Exp) {
|
|||
Stm, Context);
|
||||
for (const auto &Nodes : Matches) {
|
||||
const auto *Exp = Nodes.getNodeAs<Expr>(NodeID<Expr>::value);
|
||||
const auto *Parm = Nodes.getNodeAs<ParmVarDecl>("parm");
|
||||
const auto *Func =
|
||||
cast<FunctionDecl>(Parm->getDeclContext())->getDefinition();
|
||||
if (!Func || !Func->doesThisDeclarationHaveABody())
|
||||
const auto *Func = Nodes.getNodeAs<FunctionDecl>("func");
|
||||
if (!Func->getBody() || !Func->getPrimaryTemplate())
|
||||
return Exp;
|
||||
Parm = Func->getParamDecl(Parm->getFunctionScopeIndex());
|
||||
|
||||
const auto *Parm = Nodes.getNodeAs<ParmVarDecl>("parm");
|
||||
const ArrayRef<ParmVarDecl *> AllParams =
|
||||
Func->getTemplateInstantiationPattern(/*ForDefinition=*/true)
|
||||
->parameters();
|
||||
Func->getPrimaryTemplate()->getTemplatedDecl()->parameters();
|
||||
QualType ParmType =
|
||||
AllParams[std::min<size_t>(Parm->getFunctionScopeIndex(),
|
||||
AllParams.size() - 1)]
|
||||
|
|
|
|||
|
|
@ -365,7 +365,6 @@ cir::GlobalLinkageKind CIRGenModule::getVTableLinkage(const CXXRecordDecl *rd) {
|
|||
: cir::GlobalLinkageKind::InternalLinkage;
|
||||
return cir::GlobalLinkageKind::ExternalLinkage;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return cir::GlobalLinkageKind::LinkOnceODRLinkage;
|
||||
|
||||
|
|
@ -398,7 +397,6 @@ cir::GlobalLinkageKind CIRGenModule::getVTableLinkage(const CXXRecordDecl *rd) {
|
|||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
return discardableODRLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
|
|
|||
|
|
@ -1149,22 +1149,21 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
|
|||
|
||||
return llvm::GlobalVariable::ExternalLinkage;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
return !Context.getLangOpts().AppleKext
|
||||
? llvm::GlobalVariable::LinkOnceODRLinkage
|
||||
: llvm::Function::InternalLinkage;
|
||||
case TSK_ImplicitInstantiation:
|
||||
return !Context.getLangOpts().AppleKext ?
|
||||
llvm::GlobalVariable::LinkOnceODRLinkage :
|
||||
llvm::Function::InternalLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return !Context.getLangOpts().AppleKext
|
||||
? llvm::GlobalVariable::WeakODRLinkage
|
||||
: llvm::Function::InternalLinkage;
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return !Context.getLangOpts().AppleKext ?
|
||||
llvm::GlobalVariable::WeakODRLinkage :
|
||||
llvm::Function::InternalLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
return IsExternalDefinition
|
||||
? llvm::GlobalVariable::AvailableExternallyLinkage
|
||||
: llvm::GlobalVariable::ExternalLinkage;
|
||||
}
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
return IsExternalDefinition
|
||||
? llvm::GlobalVariable::AvailableExternallyLinkage
|
||||
: llvm::GlobalVariable::ExternalLinkage;
|
||||
}
|
||||
}
|
||||
|
||||
// -fapple-kext mode does not support weak linkage, so we must use
|
||||
|
|
@ -1189,7 +1188,6 @@ CodeGenModule::getVTableLinkage(const CXXRecordDecl *RD) {
|
|||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
return DiscardableODRLinkage;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
|
|
|||
|
|
@ -185,7 +185,6 @@ bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
|
|||
return isa<ClassTemplateSpecializationDecl>(D);
|
||||
case TSK_ExplicitSpecialization:
|
||||
return false;
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
|
|
|
|||
|
|
@ -318,7 +318,6 @@ static bool hasVTable(const CXXRecordDecl *D) {
|
|||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
return true;
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
|
@ -335,7 +334,6 @@ static bool hasVTable(const CXXRecordDecl *D) {
|
|||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
return false;
|
||||
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
|
@ -363,7 +361,6 @@ static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) {
|
|||
if (isInlined(KeyFunctionD))
|
||||
return CXXLinkage::LinkOnceODRLinkage;
|
||||
return CXXLinkage::ExternalLinkage;
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
llvm_unreachable("No external vtable for implicit instantiations");
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
|
|
@ -378,7 +375,6 @@ static CXXLinkage getVTableLinkage(const CXXRecordDecl *D) {
|
|||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
return CXXLinkage::LinkOnceODRLinkage;
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition:
|
||||
|
|
@ -605,7 +601,6 @@ bool InstallAPIVisitor::VisitCXXRecordDecl(const CXXRecordDecl *D) {
|
|||
case TSK_Undeclared:
|
||||
case TSK_ExplicitSpecialization:
|
||||
break;
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
continue;
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
|
|
|
|||
|
|
@ -2059,17 +2059,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
|
|||
TemplateParams = &FakedParamLists;
|
||||
}
|
||||
}
|
||||
MultiTemplateParamsArg ParamLists(
|
||||
TemplateParams ? &(*TemplateParams)[0] : nullptr,
|
||||
TemplateParams ? TemplateParams->size() : 0);
|
||||
|
||||
// Build the class template specialization.
|
||||
TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
|
||||
getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
|
||||
SS, *TemplateId, attrs, ParamLists, &SkipBody);
|
||||
// Some template parameter lists may have been dropped because they were
|
||||
// extraneous.
|
||||
if (TemplateParams)
|
||||
TemplateParams->resize(ParamLists.size());
|
||||
SS, *TemplateId, attrs,
|
||||
MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
|
||||
: nullptr,
|
||||
TemplateParams ? TemplateParams->size() : 0),
|
||||
&SkipBody);
|
||||
}
|
||||
} else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation &&
|
||||
TUK == TagUseKind::Declaration) {
|
||||
|
|
|
|||
|
|
@ -317,6 +317,12 @@ addVectorTexturePartialSpecialization(Sema &S, NamespaceDecl *HLSLNamespace,
|
|||
ElaboratedTypeKeyword::Class, TemplateName(TextureTemplate),
|
||||
{TemplateArgument(VectorType)}, {}));
|
||||
|
||||
auto *PartialSpec = ClassTemplatePartialSpecializationDecl::Create(
|
||||
AST, TagDecl::TagKind::Class, HLSLNamespace, SourceLocation(),
|
||||
SourceLocation(), TemplateParams, TextureTemplate,
|
||||
{TemplateArgument(VectorType)},
|
||||
CanQualType::CreateUnsafe(CanonInjectedTST), nullptr);
|
||||
|
||||
// Set the template arguments as written.
|
||||
TemplateArgument Arg(VectorType);
|
||||
TemplateArgumentLoc ArgLoc =
|
||||
|
|
@ -324,13 +330,8 @@ addVectorTexturePartialSpecialization(Sema &S, NamespaceDecl *HLSLNamespace,
|
|||
TemplateArgumentListInfo ArgsInfo =
|
||||
TemplateArgumentListInfo(SourceLocation(), SourceLocation());
|
||||
ArgsInfo.addArgument(ArgLoc);
|
||||
|
||||
auto *PartialSpec = ClassTemplatePartialSpecializationDecl::Create(
|
||||
AST, TagDecl::TagKind::Class, HLSLNamespace, SourceLocation(),
|
||||
SourceLocation(), TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(AST, ArgsInfo), TextureTemplate,
|
||||
{TemplateArgument(VectorType)},
|
||||
CanQualType::CreateUnsafe(CanonInjectedTST), nullptr);
|
||||
PartialSpec->setTemplateArgsAsWritten(
|
||||
ASTTemplateArgumentListInfo::Create(AST, ArgsInfo));
|
||||
|
||||
PartialSpec->setImplicit(true);
|
||||
PartialSpec->setLexicalDeclContext(HLSLNamespace);
|
||||
|
|
|
|||
|
|
@ -200,10 +200,15 @@ static bool DiagRecursiveConstraintEval(
|
|||
// 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) {
|
||||
// FIXME: This is a very expensive way to calculate this.
|
||||
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(ND);
|
||||
static unsigned
|
||||
CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND,
|
||||
bool SkipForSpecialization = false) {
|
||||
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
|
||||
ND, ND->getLexicalDeclContext(), /*Final=*/false,
|
||||
/*Innermost=*/std::nullopt,
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr,
|
||||
/*ForConstraintInstantiation=*/true, SkipForSpecialization);
|
||||
return MLTAL.getNumLevels();
|
||||
}
|
||||
|
||||
|
|
@ -1330,8 +1335,10 @@ bool Sema::CheckConstraintSatisfaction(
|
|||
return false;
|
||||
}
|
||||
|
||||
static ExprResult SubstituteConceptsInConstraintExpression(
|
||||
Sema &S, const ConceptSpecializationExpr *CSE, UnsignedOrNone SubstIndex) {
|
||||
static ExprResult
|
||||
SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D,
|
||||
const ConceptSpecializationExpr *CSE,
|
||||
UnsignedOrNone SubstIndex) {
|
||||
Sema::SFINAETrap Trap(S);
|
||||
// [C++2c] [temp.constr.normal]
|
||||
// Otherwise, to form CE, any non-dependent concept template argument Ai
|
||||
|
|
@ -1339,8 +1346,7 @@ static ExprResult SubstituteConceptsInConstraintExpression(
|
|||
// If any such substitution results in an invalid concept-id,
|
||||
// the program is ill-formed; no diagnostic is required.
|
||||
|
||||
Expr *ConstraintExpr =
|
||||
CSE->getNamedConcept()->getCanonicalDecl()->getConstraintExpr();
|
||||
ConceptDecl *Concept = CSE->getNamedConcept()->getCanonicalDecl();
|
||||
Sema::ArgPackSubstIndexRAII _(S, SubstIndex);
|
||||
|
||||
const ASTTemplateArgumentListInfo *ArgsAsWritten =
|
||||
|
|
@ -1350,17 +1356,23 @@ static ExprResult SubstituteConceptsInConstraintExpression(
|
|||
return !ArgLoc.getArgument().isDependent() &&
|
||||
ArgLoc.getArgument().isConceptOrConceptTemplateParameter();
|
||||
})) {
|
||||
return ConstraintExpr;
|
||||
return Concept->getConstraintExpr();
|
||||
}
|
||||
|
||||
return S.SubstConceptTemplateArguments(
|
||||
CSE, ConstraintExpr,
|
||||
S.getTemplateInstantiationArgs(CSE->getSpecializationDecl()));
|
||||
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
|
||||
Concept, Concept->getLexicalDeclContext(),
|
||||
/*Final=*/false, CSE->getTemplateArguments(),
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr,
|
||||
/*ForConstraintInstantiation=*/true);
|
||||
return S.SubstConceptTemplateArguments(CSE, Concept->getConstraintExpr(),
|
||||
MLTAL);
|
||||
}
|
||||
|
||||
bool Sema::SetupConstraintScope(FunctionDecl *FD,
|
||||
const MultiLevelTemplateArgumentList &MLTAL,
|
||||
LocalInstantiationScope &Scope) {
|
||||
bool Sema::SetupConstraintScope(
|
||||
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
|
||||
const MultiLevelTemplateArgumentList &MLTAL,
|
||||
LocalInstantiationScope &Scope) {
|
||||
assert(!isLambdaCallOperator(FD) &&
|
||||
"Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda "
|
||||
"instantiations");
|
||||
|
|
@ -1369,7 +1381,8 @@ bool Sema::SetupConstraintScope(FunctionDecl *FD,
|
|||
InstantiatingTemplate Inst(
|
||||
*this, FD->getPointOfInstantiation(),
|
||||
Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate,
|
||||
FD->getTemplateSpecializationArgs()->asArray(), SourceRange());
|
||||
TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
|
||||
SourceRange());
|
||||
if (Inst.isInvalid())
|
||||
return true;
|
||||
|
||||
|
|
@ -1405,10 +1418,11 @@ bool Sema::SetupConstraintScope(FunctionDecl *FD,
|
|||
? FD->getInstantiatedFromMemberFunction()
|
||||
: FD->getInstantiatedFromDecl();
|
||||
|
||||
InstantiatingTemplate Inst(*this, FD->getPointOfInstantiation(),
|
||||
Sema::InstantiatingTemplate::ConstraintsCheck{},
|
||||
InstantiatedFrom, ArrayRef<TemplateArgument>(),
|
||||
SourceRange());
|
||||
InstantiatingTemplate Inst(
|
||||
*this, FD->getPointOfInstantiation(),
|
||||
Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom,
|
||||
TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{},
|
||||
SourceRange());
|
||||
if (Inst.isInvalid())
|
||||
return true;
|
||||
|
||||
|
|
@ -1425,12 +1439,23 @@ bool Sema::SetupConstraintScope(FunctionDecl *FD,
|
|||
// constraint-instantiation and checking.
|
||||
std::optional<MultiLevelTemplateArgumentList>
|
||||
Sema::SetupConstraintCheckingTemplateArgumentsAndScope(
|
||||
FunctionDecl *FD, LocalInstantiationScope &Scope) {
|
||||
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(FD);
|
||||
FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs,
|
||||
LocalInstantiationScope &Scope) {
|
||||
MultiLevelTemplateArgumentList MLTAL;
|
||||
|
||||
// Collect the list of template arguments relative to the 'primary' template.
|
||||
// We need the entire list, since the constraint is completely uninstantiated
|
||||
// at this point.
|
||||
MLTAL =
|
||||
getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(),
|
||||
/*Final=*/false, /*Innermost=*/std::nullopt,
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr,
|
||||
/*ForConstraintInstantiation=*/true);
|
||||
// Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII.
|
||||
if (isLambdaCallOperator(FD))
|
||||
return MLTAL;
|
||||
if (SetupConstraintScope(FD, MLTAL, Scope))
|
||||
if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope))
|
||||
return std::nullopt;
|
||||
|
||||
return MLTAL;
|
||||
|
|
@ -1477,7 +1502,7 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
|
|||
LocalInstantiationScope Scope(*this, !ForOverloadResolution);
|
||||
std::optional<MultiLevelTemplateArgumentList> MLTAL =
|
||||
SetupConstraintCheckingTemplateArgumentsAndScope(
|
||||
const_cast<FunctionDecl *>(FD), Scope);
|
||||
const_cast<FunctionDecl *>(FD), {}, Scope);
|
||||
|
||||
if (!MLTAL)
|
||||
return true;
|
||||
|
|
@ -1500,10 +1525,15 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
|
|||
Satisfaction);
|
||||
}
|
||||
|
||||
static const Expr *
|
||||
SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Decl *ND,
|
||||
const Expr *ConstrExpr) {
|
||||
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(ND);
|
||||
static const Expr *SubstituteConstraintExpressionWithoutSatisfaction(
|
||||
Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo,
|
||||
const Expr *ConstrExpr) {
|
||||
MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs(
|
||||
DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false,
|
||||
/*Innermost=*/std::nullopt,
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true,
|
||||
/*SkipForSpecialization*/ false);
|
||||
|
||||
if (MLTAL.getNumSubstitutedLevels() == 0)
|
||||
return ConstrExpr;
|
||||
|
|
@ -1513,7 +1543,8 @@ SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Decl *ND,
|
|||
// this may happen while we're comparing two templates' constraint
|
||||
// equivalence.
|
||||
std::optional<LocalInstantiationScope> ScopeForParameters;
|
||||
if (ND->isFunctionOrFunctionTemplate()) {
|
||||
if (const NamedDecl *ND = DeclInfo.getDecl();
|
||||
ND && ND->isFunctionOrFunctionTemplate()) {
|
||||
ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true);
|
||||
const FunctionDecl *FD = ND->getAsFunction();
|
||||
if (FunctionTemplateDecl *Template = FD->getDescribedFunctionTemplate();
|
||||
|
|
@ -1557,9 +1588,13 @@ SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Decl *ND,
|
|||
// possible that e.g. constraints involving C<Class<T>> and C<Class> are
|
||||
// perceived identical.
|
||||
std::optional<Sema::ContextRAII> ContextScope;
|
||||
const DeclContext *DC = ND->getFriendObjectKind()
|
||||
? ND->getLexicalDeclContext()
|
||||
: ND->getDeclContext();
|
||||
const DeclContext *DC = [&] {
|
||||
if (!DeclInfo.getDecl())
|
||||
return DeclInfo.getDeclContext();
|
||||
return DeclInfo.getDecl()->getFriendObjectKind()
|
||||
? DeclInfo.getLexicalDeclContext()
|
||||
: DeclInfo.getDeclContext();
|
||||
}();
|
||||
if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) {
|
||||
ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers());
|
||||
ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)),
|
||||
|
|
@ -1575,14 +1610,15 @@ SubstituteConstraintExpressionWithoutSatisfaction(Sema &S, const Decl *ND,
|
|||
return SubstConstr.get();
|
||||
}
|
||||
|
||||
bool Sema::AreConstraintExpressionsEqual(const Decl *Old, const Expr *OldConstr,
|
||||
const Decl *New,
|
||||
bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
|
||||
const Expr *OldConstr,
|
||||
const TemplateCompareNewDeclInfo &New,
|
||||
const Expr *NewConstr) {
|
||||
if (OldConstr == NewConstr)
|
||||
return true;
|
||||
// C++ [temp.constr.decl]p4
|
||||
if (Old != New &&
|
||||
Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
|
||||
if (Old && !New.isInvalid() && !New.ContainsDecl(Old) &&
|
||||
Old->getLexicalDeclContext() != New.getLexicalDeclContext()) {
|
||||
Sema::SFINAETrap _(*this);
|
||||
if (const Expr *SubstConstr =
|
||||
SubstituteConstraintExpressionWithoutSatisfaction(*this, Old,
|
||||
|
|
@ -1604,15 +1640,19 @@ bool Sema::AreConstraintExpressionsEqual(const Decl *Old, const Expr *OldConstr,
|
|||
return ID1 == ID2;
|
||||
}
|
||||
|
||||
bool Sema::FriendConstraintsDependOnEnclosingTemplate(
|
||||
const FunctionTemplateDecl *FTD) {
|
||||
assert(FTD->getFriendObjectKind() && "Must be a friend!");
|
||||
bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) {
|
||||
assert(FD->getFriendObjectKind() && "Must be a friend!");
|
||||
|
||||
// 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");
|
||||
|
||||
SmallVector<AssociatedConstraint, 3> ACs;
|
||||
FTD->getAssociatedConstraints(ACs);
|
||||
FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs);
|
||||
|
||||
const FunctionDecl *FD = FTD->getTemplatedDecl();
|
||||
unsigned OldTemplateDepth = FTD->getTemplateDepth();
|
||||
unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD);
|
||||
for (const AssociatedConstraint &AC : ACs)
|
||||
if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth,
|
||||
AC.ConstraintExpr))
|
||||
|
|
@ -1648,9 +1688,9 @@ bool Sema::EnsureTemplateArgumentListConstraints(
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckFunctionTemplateConstraints(
|
||||
SourceLocation PointOfInstantiation, FunctionTemplateDecl *Template,
|
||||
ArrayRef<TemplateArgument> TemplateArgs,
|
||||
static bool CheckFunctionConstraintsWithoutInstantiation(
|
||||
Sema &SemaRef, SourceLocation PointOfInstantiation,
|
||||
FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
|
||||
ConstraintSatisfaction &Satisfaction) {
|
||||
SmallVector<AssociatedConstraint, 3> TemplateAC;
|
||||
Template->getAssociatedConstraints(TemplateAC);
|
||||
|
|
@ -1659,22 +1699,47 @@ bool Sema::CheckFunctionTemplateConstraints(
|
|||
return false;
|
||||
}
|
||||
|
||||
LocalInstantiationScope Scope(*this);
|
||||
LocalInstantiationScope Scope(SemaRef);
|
||||
|
||||
MultiLevelTemplateArgumentList MLTAL =
|
||||
getTemplateInstantiationArgs(Template, TemplateArgs);
|
||||
FunctionDecl *FD = Template->getTemplatedDecl();
|
||||
// Collect the list of template arguments relative to the 'primary'
|
||||
// template. We need the entire list, since the constraint is completely
|
||||
// uninstantiated at this point.
|
||||
|
||||
Sema::ContextRAII SavedContext(*this, Template->getTemplatedDecl());
|
||||
return CheckConstraintSatisfaction(Template, TemplateAC, MLTAL,
|
||||
PointOfInstantiation, Satisfaction);
|
||||
MultiLevelTemplateArgumentList MLTAL;
|
||||
{
|
||||
// getTemplateInstantiationArgs uses this instantiation context to find out
|
||||
// template arguments for uninstantiated functions.
|
||||
// We don't want this RAII object to persist, because there would be
|
||||
// otherwise duplicate diagnostic notes.
|
||||
Sema::InstantiatingTemplate Inst(
|
||||
SemaRef, PointOfInstantiation,
|
||||
Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
|
||||
PointOfInstantiation);
|
||||
if (Inst.isInvalid())
|
||||
return true;
|
||||
MLTAL = SemaRef.getTemplateInstantiationArgs(
|
||||
/*D=*/FD, FD,
|
||||
/*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);
|
||||
}
|
||||
|
||||
Sema::ContextRAII SavedContext(SemaRef, FD);
|
||||
return SemaRef.CheckConstraintSatisfaction(
|
||||
Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction);
|
||||
}
|
||||
|
||||
bool Sema::CheckFunctionSpecializationConstraints(
|
||||
bool Sema::CheckFunctionTemplateConstraints(
|
||||
SourceLocation PointOfInstantiation, FunctionDecl *Decl,
|
||||
ArrayRef<TemplateArgument> TemplateArgs,
|
||||
ConstraintSatisfaction &Satisfaction) {
|
||||
// In most cases we're not going to have constraints, so check for that first.
|
||||
FunctionTemplateDecl *Template = Decl->getPrimaryTemplate();
|
||||
assert(Template && "Function is not a specialization");
|
||||
|
||||
if (!Template)
|
||||
return ::CheckFunctionConstraintsWithoutInstantiation(
|
||||
*this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(),
|
||||
TemplateArgs, Satisfaction);
|
||||
|
||||
// Note - code synthesis context for the constraints check is created
|
||||
// inside CheckConstraintsSatisfaction.
|
||||
|
|
@ -1691,7 +1756,8 @@ bool Sema::CheckFunctionSpecializationConstraints(
|
|||
LocalInstantiationScope Scope(*this);
|
||||
|
||||
std::optional<MultiLevelTemplateArgumentList> MLTAL =
|
||||
SetupConstraintCheckingTemplateArgumentsAndScope(Decl, Scope);
|
||||
SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs,
|
||||
Scope);
|
||||
|
||||
if (!MLTAL)
|
||||
return true;
|
||||
|
|
@ -2275,8 +2341,12 @@ bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) {
|
|||
InnerArgs = std::move(CTAI.SugaredConverted);
|
||||
}
|
||||
|
||||
MultiLevelTemplateArgumentList MLTAL =
|
||||
SemaRef.getTemplateInstantiationArgs(Concept, InnerArgs);
|
||||
MultiLevelTemplateArgumentList MLTAL = SemaRef.getTemplateInstantiationArgs(
|
||||
Concept, Concept->getLexicalDeclContext(),
|
||||
/*Final=*/true, InnerArgs,
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr,
|
||||
/*ForConstraintInstantiation=*/true);
|
||||
|
||||
return SubstituteParameterMappings(SemaRef, &MLTAL,
|
||||
CSE->getTemplateArgsAsWritten(),
|
||||
|
|
@ -2357,7 +2427,7 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr(
|
|||
// [...]
|
||||
NormalizedConstraint *SubNF;
|
||||
if (ExprResult Res =
|
||||
SubstituteConceptsInConstraintExpression(S, CSE, SubstIndex);
|
||||
SubstituteConceptsInConstraintExpression(S, D, CSE, SubstIndex);
|
||||
Res.isUsable())
|
||||
// Use canonical declarations to merge ConceptDecls across different
|
||||
// modules.
|
||||
|
|
@ -2507,8 +2577,8 @@ bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1,
|
|||
return false;
|
||||
}
|
||||
|
||||
unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1);
|
||||
unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2);
|
||||
unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true);
|
||||
unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true);
|
||||
|
||||
for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) {
|
||||
if (Depth2 > Depth1) {
|
||||
|
|
|
|||
|
|
@ -4750,10 +4750,10 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
|
|||
adjustDeclContextForDeclaratorDecl(New, Old);
|
||||
|
||||
// Ensure the template parameters are compatible.
|
||||
if (NewTemplate && !TemplateParameterListsAreEqual(
|
||||
NewTemplate, NewTemplate->getTemplateParameters(),
|
||||
OldTemplate, OldTemplate->getTemplateParameters(),
|
||||
/*Complain=*/true, TPL_TemplateMatch))
|
||||
if (NewTemplate &&
|
||||
!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
|
||||
OldTemplate->getTemplateParameters(),
|
||||
/*Complain=*/true, TPL_TemplateMatch))
|
||||
return New->setInvalidDecl();
|
||||
|
||||
// C++ [class.mem]p1:
|
||||
|
|
@ -6414,7 +6414,20 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC,
|
|||
return false;
|
||||
|
||||
// Cannot qualify members within a class.
|
||||
Diag(Loc, diag::err_member_qualification) << Name << SS.getRange();
|
||||
Diag(Loc, diag::err_member_qualification)
|
||||
<< Name << SS.getRange();
|
||||
SS.clear();
|
||||
|
||||
// C++ constructors and destructors with incorrect scopes can break
|
||||
// our AST invariants by having the wrong underlying types. If
|
||||
// that's the case, then drop this declaration entirely.
|
||||
if ((Name.getNameKind() == DeclarationName::CXXConstructorName ||
|
||||
Name.getNameKind() == DeclarationName::CXXDestructorName) &&
|
||||
!Context.hasSameType(
|
||||
Name.getCXXNameType(),
|
||||
Context.getCanonicalTagType(cast<CXXRecordDecl>(Cur))))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -8016,8 +8029,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
|||
}
|
||||
|
||||
if (IsVariableTemplateSpecialization) {
|
||||
// FIXME: This should be the template keyword location for the last
|
||||
// template parameter list.
|
||||
SourceLocation TemplateKWLoc =
|
||||
TemplateParamLists.size() > 0
|
||||
? TemplateParamLists[0]->getTemplateLoc()
|
||||
|
|
@ -8060,8 +8071,10 @@ NamedDecl *Sema::ActOnVariableDeclarator(
|
|||
|
||||
// If we have any template parameter lists that don't directly belong to
|
||||
// the variable (matching the scope specifier), store them.
|
||||
// An explicit variable template specialization does not own any template
|
||||
// parameter lists.
|
||||
unsigned VDTemplateParamLists =
|
||||
IsVariableTemplate || IsVariableTemplateSpecialization ? 1 : 0;
|
||||
(TemplateParams && !IsExplicitSpecialization) ? 1 : 0;
|
||||
if (TemplateParamLists.size() > VDTemplateParamLists)
|
||||
NewVD->setTemplateParameterListsInfo(
|
||||
Context, TemplateParamLists.drop_back(VDTemplateParamLists));
|
||||
|
|
@ -10112,7 +10125,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
bool isMemberSpecialization = false;
|
||||
bool isFunctionTemplateSpecialization = false;
|
||||
|
||||
TemplateParameterList *TemplateParams = nullptr;
|
||||
bool HasExplicitTemplateArgs = false;
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
|
||||
|
|
@ -10197,14 +10209,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: nullptr;
|
||||
TemplateParamListsRef = TemplateParamLists;
|
||||
TemplateParams = MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateId, TemplateParamListsRef, isFriend,
|
||||
isMemberSpecialization, Invalid);
|
||||
// Some template parameter lists may have been dropped because they were
|
||||
// extraneous.
|
||||
TemplateParamLists.resize(TemplateParamListsRef.size());
|
||||
TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateId, TemplateParamLists, isFriend,
|
||||
isMemberSpecialization, Invalid);
|
||||
if (TemplateParams) {
|
||||
// Check that we can declare a template here.
|
||||
if (CheckTemplateDeclScope(S, TemplateParams))
|
||||
|
|
@ -10239,10 +10248,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
NewFD);
|
||||
FunctionTemplate->setLexicalDeclContext(CurContext);
|
||||
NewFD->setDescribedFunctionTemplate(FunctionTemplate);
|
||||
|
||||
// For source fidelity, store the other template param lists.
|
||||
if (TemplateParamLists.size() > 1) {
|
||||
NewFD->setTemplateParameterListsInfo(Context,
|
||||
ArrayRef<TemplateParameterList *>(TemplateParamLists)
|
||||
.drop_back(1));
|
||||
}
|
||||
} else {
|
||||
// This is a function template specialization.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
NewFD->setInnerLocStart(TemplateParams->getTemplateLoc());
|
||||
// For source fidelity, store all the template param lists.
|
||||
if (TemplateParamLists.size() > 0)
|
||||
NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
|
||||
|
||||
// C++0x [temp.expl.spec]p20 forbids "template<> friend void foo(int);".
|
||||
if (isFriend) {
|
||||
|
|
@ -10272,12 +10290,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
TemplateArgs.setRAngleLoc(InsertLoc);
|
||||
}
|
||||
}
|
||||
// For source fidelity, store the other template param lists.
|
||||
if (TemplateParamLists.size() > 1) {
|
||||
NewFD->setTemplateParameterListsInfo(
|
||||
Context,
|
||||
ArrayRef<TemplateParameterList *>(TemplateParamLists).drop_back(1));
|
||||
}
|
||||
} else {
|
||||
// Check that we can declare a template here.
|
||||
if (!TemplateParamLists.empty() && isMemberSpecialization &&
|
||||
|
|
@ -10879,11 +10891,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// template is instantiated. In such cases, we store the declarations
|
||||
// found by name lookup and defer resolution until instantiation.
|
||||
if (CheckDependentFunctionTemplateSpecialization(
|
||||
NewFD, TemplateParams, ExplicitTemplateArgs, Previous))
|
||||
NewFD, ExplicitTemplateArgs, Previous))
|
||||
NewFD->setInvalidDecl();
|
||||
} else if (!NewFD->isInvalidDecl()) {
|
||||
if (CheckFunctionTemplateSpecialization(NewFD, TemplateParams,
|
||||
ExplicitTemplateArgs, Previous))
|
||||
if (CheckFunctionTemplateSpecialization(NewFD, ExplicitTemplateArgs,
|
||||
Previous))
|
||||
NewFD->setInvalidDecl();
|
||||
}
|
||||
} else if (isMemberSpecialization && !FunctionTemplate) {
|
||||
|
|
@ -11187,7 +11199,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
// Precalculate whether this is a friend function template with a constraint
|
||||
// that depends on an enclosing template, per [temp.friend]p9.
|
||||
if (isFriend && FunctionTemplate &&
|
||||
FriendConstraintsDependOnEnclosingTemplate(FunctionTemplate)) {
|
||||
FriendConstraintsDependOnEnclosingTemplate(NewFD)) {
|
||||
NewFD->setFriendConstraintRefersToEnclosingTemplate(true);
|
||||
|
||||
// C++ [temp.friend]p9:
|
||||
|
|
|
|||
|
|
@ -13938,13 +13938,10 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS,
|
|||
}
|
||||
|
||||
if (!Invalid && OldDecl && !OldDecl->isInvalidDecl()) {
|
||||
// It's ok that we don't pass the declarations corresponding to the
|
||||
// template parameter lists here, because type alias templates cannot be
|
||||
// declared out-of-line.
|
||||
if (TemplateParameterListsAreEqual(
|
||||
/*NewInstFrom=*/nullptr, TemplateParams,
|
||||
/*OldInstFrom=*/nullptr, OldDecl->getTemplateParameters(),
|
||||
/*Complain=*/true, TPL_TemplateMatch))
|
||||
if (TemplateParameterListsAreEqual(TemplateParams,
|
||||
OldDecl->getTemplateParameters(),
|
||||
/*Complain=*/true,
|
||||
TPL_TemplateMatch))
|
||||
OldTemplateParams =
|
||||
OldDecl->getMostRecentDecl()->getTemplateParameters();
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1129,8 +1129,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
|
|||
return ExprError();
|
||||
}
|
||||
|
||||
DeclResult VDecl = CheckVarTemplateId(
|
||||
VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(), *TemplateArgs);
|
||||
DeclResult VDecl =
|
||||
CheckVarTemplateId(VarTempl, TemplateKWLoc, MemberNameInfo.getLoc(),
|
||||
*TemplateArgs, /*SetWrittenArgs=*/false);
|
||||
if (VDecl.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
|
|
|
|||
|
|
@ -1325,10 +1325,8 @@ OverloadKind Sema::CheckOverload(Scope *S, FunctionDecl *New,
|
|||
!New->getType()->isDependentType()) {
|
||||
LookupResult TemplateSpecResult(LookupResult::Temporary, Old);
|
||||
TemplateSpecResult.addAllDecls(Old);
|
||||
if (CheckFunctionTemplateSpecialization(New, /*TemplateParams=*/nullptr,
|
||||
/*ExplicitTemplateArgs=*/nullptr,
|
||||
TemplateSpecResult,
|
||||
/*QualifiedFriend*/ true)) {
|
||||
if (CheckFunctionTemplateSpecialization(New, nullptr, TemplateSpecResult,
|
||||
/*QualifiedFriend*/true)) {
|
||||
New->setInvalidDecl();
|
||||
return OverloadKind::Overload;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2113,71 +2113,19 @@ DeclResult Sema::CheckClassTemplate(
|
|||
}
|
||||
}
|
||||
|
||||
if (!PrevClassTemplate && PrevDecl) {
|
||||
// C++ [temp]p5:
|
||||
// A class template shall not have the same name as any other
|
||||
// template, class, function, object, enumeration, enumerator,
|
||||
// namespace, or type in the same scope (3.3), except as specified
|
||||
// in (14.5.4).
|
||||
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If this is a templated friend in a dependent context we should not put it
|
||||
// on the redecl chain. In some cases, the templated friend can be the most
|
||||
// recent declaration tricking the template instantiator to make substitutions
|
||||
// there.
|
||||
// FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious
|
||||
bool ShouldAddRedecl =
|
||||
!(TUK == TagUseKind::Friend && CurContext->isDependentContext());
|
||||
|
||||
CXXRecordDecl *NewClass = CXXRecordDecl::Create(
|
||||
Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
|
||||
/*PrevDecl=*/PrevClassTemplate && ShouldAddRedecl
|
||||
? PrevClassTemplate->getTemplatedDecl()
|
||||
: nullptr);
|
||||
SetNestedNameSpecifier(*this, NewClass, SS);
|
||||
if (NumOuterTemplateParamLists > 0)
|
||||
NewClass->setTemplateParameterListsInfo(
|
||||
Context,
|
||||
llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists));
|
||||
|
||||
// Add alignment attributes if necessary; these attributes are checked when
|
||||
// the ASTContext lays out the structure.
|
||||
if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
|
||||
if (LangOpts.HLSL)
|
||||
NewClass->addAttr(PackedAttr::CreateImplicit(Context));
|
||||
AddAlignmentAttributesForRecord(NewClass);
|
||||
AddMsStructLayoutForRecord(NewClass);
|
||||
}
|
||||
|
||||
ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(
|
||||
Context, SemanticContext, NameLoc, DeclarationName(Name), TemplateParams,
|
||||
NewClass);
|
||||
|
||||
NewClass->setDescribedClassTemplate(NewTemplate);
|
||||
|
||||
if (ModulePrivateLoc.isValid())
|
||||
NewTemplate->setModulePrivate();
|
||||
|
||||
// Set the lexical context of these templates
|
||||
NewClass->setLexicalDeclContext(CurContext);
|
||||
NewTemplate->setLexicalDeclContext(CurContext);
|
||||
|
||||
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(
|
||||
NewTemplate, TemplateParams, PrevClassTemplate,
|
||||
TemplateCompareNewDeclInfo(SemanticContext ? SemanticContext
|
||||
: CurContext,
|
||||
CurContext, KWLoc),
|
||||
TemplateParams, PrevClassTemplate,
|
||||
PrevClassTemplate->getTemplateParameters(), /*Complain=*/true,
|
||||
TPL_TemplateMatch)) {
|
||||
NewTemplate->setInvalidDecl();
|
||||
NewClass->setInvalidDecl();
|
||||
TPL_TemplateMatch))
|
||||
return true;
|
||||
}
|
||||
|
||||
// C++ [temp.class]p4:
|
||||
// In a redeclaration, partial specialization, explicit
|
||||
|
|
@ -2222,6 +2170,15 @@ DeclResult Sema::CheckClassTemplate(
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (PrevDecl) {
|
||||
// C++ [temp]p5:
|
||||
// A class template shall not have the same name as any other
|
||||
// template, class, function, object, enumeration, enumerator,
|
||||
// namespace, or type in the same scope (3.3), except as specified
|
||||
// in (14.5.4).
|
||||
Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the template parameter list of this declaration, possibly
|
||||
|
|
@ -2252,20 +2209,62 @@ DeclResult Sema::CheckClassTemplate(
|
|||
<< SS.getRange();
|
||||
}
|
||||
|
||||
// Set the access specifier.
|
||||
if (!Invalid && TUK != TagUseKind::Friend &&
|
||||
NewTemplate->getDeclContext()->isRecord())
|
||||
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
|
||||
// If this is a templated friend in a dependent context we should not put it
|
||||
// on the redecl chain. In some cases, the templated friend can be the most
|
||||
// recent declaration tricking the template instantiator to make substitutions
|
||||
// there.
|
||||
// FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious
|
||||
bool ShouldAddRedecl =
|
||||
!(TUK == TagUseKind::Friend && CurContext->isDependentContext());
|
||||
|
||||
if (ShouldAddRedecl && PrevClassTemplate)
|
||||
CXXRecordDecl *NewClass = CXXRecordDecl::Create(
|
||||
Context, Kind, SemanticContext, KWLoc, NameLoc, Name,
|
||||
PrevClassTemplate && ShouldAddRedecl
|
||||
? PrevClassTemplate->getTemplatedDecl()
|
||||
: nullptr);
|
||||
SetNestedNameSpecifier(*this, NewClass, SS);
|
||||
if (NumOuterTemplateParamLists > 0)
|
||||
NewClass->setTemplateParameterListsInfo(
|
||||
Context,
|
||||
llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists));
|
||||
|
||||
// Add alignment attributes if necessary; these attributes are checked when
|
||||
// the ASTContext lays out the structure.
|
||||
if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) {
|
||||
if (LangOpts.HLSL)
|
||||
NewClass->addAttr(PackedAttr::CreateImplicit(Context));
|
||||
AddAlignmentAttributesForRecord(NewClass);
|
||||
AddMsStructLayoutForRecord(NewClass);
|
||||
}
|
||||
|
||||
ClassTemplateDecl *NewTemplate
|
||||
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
|
||||
DeclarationName(Name), TemplateParams,
|
||||
NewClass);
|
||||
|
||||
if (ShouldAddRedecl)
|
||||
NewTemplate->setPreviousDecl(PrevClassTemplate);
|
||||
|
||||
NewClass->setDescribedClassTemplate(NewTemplate);
|
||||
|
||||
if (ModulePrivateLoc.isValid())
|
||||
NewTemplate->setModulePrivate();
|
||||
|
||||
if (IsMemberSpecialization) {
|
||||
assert(PrevClassTemplate &&
|
||||
"Member specialization without a primary template?");
|
||||
NewTemplate->setMemberSpecialization();
|
||||
}
|
||||
|
||||
// Set the access specifier.
|
||||
if (!Invalid && TUK != TagUseKind::Friend &&
|
||||
NewTemplate->getDeclContext()->isRecord())
|
||||
SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS);
|
||||
|
||||
// Set the lexical context of these templates
|
||||
NewClass->setLexicalDeclContext(CurContext);
|
||||
NewTemplate->setLexicalDeclContext(CurContext);
|
||||
|
||||
if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip))
|
||||
NewClass->startDefinition();
|
||||
|
||||
|
|
@ -2838,7 +2837,7 @@ static SourceRange getRangeOfTypeInNestedNameSpecifier(ASTContext &Context,
|
|||
TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
||||
SourceLocation DeclStartLoc, SourceLocation DeclLoc, const CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation *TemplateId,
|
||||
ArrayRef<TemplateParameterList *> &ParamLists, bool IsFriend,
|
||||
ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend,
|
||||
bool &IsMemberSpecialization, bool &Invalid, bool SuppressDiagnostic) {
|
||||
IsMemberSpecialization = false;
|
||||
Invalid = false;
|
||||
|
|
@ -3104,12 +3103,10 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
|||
|
||||
if (ParamIdx < ParamLists.size()) {
|
||||
// Check the template parameter list, if we can.
|
||||
// FIXME: Should pass the declaration corresponding to each list.
|
||||
if (ExpectedTemplateParams &&
|
||||
!TemplateParameterListsAreEqual(
|
||||
/*NewInstFrom=*/nullptr, ParamLists[ParamIdx],
|
||||
/*OldInstFrom=*/nullptr, ExpectedTemplateParams,
|
||||
/*Complain=*/!SuppressDiagnostic, TPL_TemplateMatch))
|
||||
!TemplateParameterListsAreEqual(ParamLists[ParamIdx],
|
||||
ExpectedTemplateParams,
|
||||
!SuppressDiagnostic, TPL_TemplateMatch))
|
||||
Invalid = true;
|
||||
|
||||
if (!Invalid &&
|
||||
|
|
@ -3176,9 +3173,6 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier(
|
|||
diag::note_explicit_template_spec_does_not_need_header)
|
||||
<< NestedTypes.back();
|
||||
|
||||
// Recover as if those extra template parameter lists weren't there.
|
||||
ParamLists = ParamLists.take_back(ParamIdx + 1);
|
||||
|
||||
// We have a template parameter list with no corresponding scope, which
|
||||
// means that the resulting template declaration can't be instantiated
|
||||
// properly (we'll end up with dependent nodes when we shouldn't).
|
||||
|
|
@ -4486,9 +4480,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
|
|||
VarTemplatePartialSpecializationDecl *Partial =
|
||||
VarTemplatePartialSpecializationDecl::Create(
|
||||
Context, VarTemplate->getDeclContext(), TemplateKWLoc,
|
||||
TemplateNameLoc, TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(Context, TemplateArgs),
|
||||
VarTemplate, TSI->getType(), TSI, SC, CTAI.CanonicalConverted);
|
||||
TemplateNameLoc, TemplateParams, VarTemplate, TSI->getType(), TSI,
|
||||
SC, CTAI.CanonicalConverted);
|
||||
Partial->setTemplateArgsAsWritten(TemplateArgs);
|
||||
|
||||
if (!PrevPartial)
|
||||
VarTemplate->AddPartialSpecialization(Partial, InsertPos);
|
||||
|
|
@ -4501,9 +4495,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
|
|||
Specialization = VarTemplateSpecializationDecl::Create(
|
||||
Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc,
|
||||
VarTemplate, TSI->getType(), TSI, SC, CTAI.CanonicalConverted);
|
||||
Specialization->setExplicitSpecializationInfo(
|
||||
TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(Context, TemplateArgs));
|
||||
Specialization->setTemplateArgsAsWritten(TemplateArgs);
|
||||
|
||||
if (!PrevDecl)
|
||||
VarTemplate->AddSpecialization(Specialization, InsertPos);
|
||||
|
|
@ -4589,7 +4581,8 @@ static bool IsLibstdcxxStdFormatKind(Preprocessor &PP, VarDecl *Var) {
|
|||
DeclResult
|
||||
Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
||||
SourceLocation TemplateNameLoc,
|
||||
const TemplateArgumentListInfo &TemplateArgs) {
|
||||
const TemplateArgumentListInfo &TemplateArgs,
|
||||
bool SetWrittenArgs) {
|
||||
assert(Template && "A variable template id without template?");
|
||||
|
||||
// Check that the template argument list is well-formed for this template.
|
||||
|
|
@ -4788,6 +4781,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
|
|||
TemplateNameLoc /*, LateAttrs, StartingScope*/);
|
||||
if (!Decl)
|
||||
return true;
|
||||
if (SetWrittenArgs)
|
||||
Decl->setTemplateArgsAsWritten(TemplateArgs);
|
||||
|
||||
if (VarTemplatePartialSpecializationDecl *D =
|
||||
dyn_cast<VarTemplatePartialSpecializationDecl>(InstantiationPattern))
|
||||
|
|
@ -4805,7 +4800,7 @@ ExprResult Sema::CheckVarTemplateId(
|
|||
const TemplateArgumentListInfo *TemplateArgs) {
|
||||
|
||||
DeclResult Decl = CheckVarTemplateId(Template, TemplateLoc, NameInfo.getLoc(),
|
||||
*TemplateArgs);
|
||||
*TemplateArgs, /*SetWrittenArgs=*/false);
|
||||
if (Decl.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
|
|
@ -6197,8 +6192,7 @@ bool Sema::CheckTemplateArgumentList(
|
|||
if (UpdateArgsWithConversions)
|
||||
TemplateArgs = std::move(NewArgs);
|
||||
|
||||
// Template template parameters can never have their constraints checked.
|
||||
if (!PartialTemplateArgs && !isa<TemplateTemplateParmDecl>(Template)) {
|
||||
if (!PartialTemplateArgs) {
|
||||
// Setup the context/ThisScope for the case where we are needing to
|
||||
// re-instantiate constraints outside of normal instantiation.
|
||||
DeclContext *NewContext = Template->getDeclContext();
|
||||
|
|
@ -6217,8 +6211,11 @@ bool Sema::CheckTemplateArgumentList(
|
|||
ContextRAII Context(*this, NewContext);
|
||||
CXXThisScopeRAII Scope(*this, RD, ThisQuals, RD != nullptr);
|
||||
|
||||
MultiLevelTemplateArgumentList MLTAL =
|
||||
getTemplateInstantiationArgs(Template, CTAI.SugaredConverted);
|
||||
MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs(
|
||||
Template, NewContext, /*Final=*/true, CTAI.SugaredConverted,
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr,
|
||||
/*ForConceptInstantiation=*/true);
|
||||
if (!isa<ConceptDecl>(Template) &&
|
||||
EnsureTemplateArgumentListConstraints(
|
||||
Template, MLTAL,
|
||||
|
|
@ -8209,8 +8206,9 @@ Sema::BuildExpressionFromNonTypeTemplateArgument(const TemplateArgument &Arg,
|
|||
|
||||
/// Match two template parameters within template parameter lists.
|
||||
static bool MatchTemplateParameterKind(
|
||||
Sema &S, NamedDecl *New, const Decl *NewInstFrom, NamedDecl *Old,
|
||||
const Decl *OldInstFrom, bool Complain,
|
||||
Sema &S, NamedDecl *New,
|
||||
const Sema::TemplateCompareNewDeclInfo &NewInstFrom, NamedDecl *Old,
|
||||
const NamedDecl *OldInstFrom, bool Complain,
|
||||
Sema::TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
|
||||
// Check the actual kind (type, non-type, template).
|
||||
if (Old->getKind() != New->getKind()) {
|
||||
|
|
@ -8298,7 +8296,7 @@ static bool MatchTemplateParameterKind(
|
|||
if (OldTTP->templateParameterKind() != NewTTP->templateParameterKind())
|
||||
return false;
|
||||
if (!S.TemplateParameterListsAreEqual(
|
||||
NewTTP, NewTTP->getTemplateParameters(), OldTTP,
|
||||
NewInstFrom, NewTTP->getTemplateParameters(), OldInstFrom,
|
||||
OldTTP->getTemplateParameters(), Complain,
|
||||
(Kind == Sema::TPL_TemplateMatch
|
||||
? Sema::TPL_TemplateTemplateParmMatch
|
||||
|
|
@ -8376,8 +8374,8 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S,
|
|||
}
|
||||
|
||||
bool Sema::TemplateParameterListsAreEqual(
|
||||
const Decl *NewInstFrom, TemplateParameterList *New,
|
||||
const Decl *OldInstFrom, TemplateParameterList *Old, bool Complain,
|
||||
const TemplateCompareNewDeclInfo &NewInstFrom, TemplateParameterList *New,
|
||||
const NamedDecl *OldInstFrom, TemplateParameterList *Old, bool Complain,
|
||||
TemplateParameterListEqualKind Kind, SourceLocation TemplateArgLoc) {
|
||||
if (Old->size() != New->size()) {
|
||||
if (Complain)
|
||||
|
|
@ -8759,7 +8757,7 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
|
|||
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
|
||||
SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
|
||||
TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
|
||||
MultiTemplateParamsArg &TemplateParameterLists, SkipBodyInfo *SkipBody) {
|
||||
MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) {
|
||||
assert(TUK != TagUseKind::Reference && "References are not specializations");
|
||||
|
||||
SourceLocation TemplateNameLoc = TemplateId.TemplateNameLoc;
|
||||
|
|
@ -8957,13 +8955,15 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
|
|||
Specialization = ClassTemplateSpecializationDecl::Create(
|
||||
Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
|
||||
ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
|
||||
Specialization->setTemplateArgsAsWritten(TemplateArgs);
|
||||
SetNestedNameSpecifier(*this, Specialization, SS);
|
||||
if (TemplateParameterLists.size() > 0) {
|
||||
Specialization->setTemplateParameterListsInfo(Context,
|
||||
TemplateParameterLists);
|
||||
}
|
||||
|
||||
if (!PrevDecl)
|
||||
ClassTemplate->AddSpecialization(Specialization, InsertPos);
|
||||
|
||||
Specialization->setExplicitSpecializationInfo(
|
||||
TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(Context, TemplateArgs));
|
||||
} else {
|
||||
CanQualType CanonType = CanQualType::CreateUnsafe(
|
||||
Context.getCanonicalTemplateSpecializationType(
|
||||
|
|
@ -8999,8 +8999,13 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
|
|||
ClassTemplatePartialSpecializationDecl *Partial =
|
||||
ClassTemplatePartialSpecializationDecl::Create(
|
||||
Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(Context, TemplateArgs),
|
||||
ClassTemplate, CTAI.CanonicalConverted, CanonType, PrevPartial);
|
||||
Partial->setTemplateArgsAsWritten(TemplateArgs);
|
||||
SetNestedNameSpecifier(*this, Partial, SS);
|
||||
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
|
||||
Partial->setTemplateParameterListsInfo(
|
||||
Context, TemplateParameterLists.drop_back(1));
|
||||
}
|
||||
|
||||
if (!PrevPartial)
|
||||
ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
|
||||
|
|
@ -9010,18 +9015,10 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
|
|||
// template specialization, make a note of that.
|
||||
if (isMemberSpecialization)
|
||||
Partial->setMemberSpecialization();
|
||||
}
|
||||
|
||||
SetNestedNameSpecifier(*this, Specialization, SS);
|
||||
if (TemplateParameterLists.size() > 1 && SS.isSet()) {
|
||||
Specialization->setTemplateParameterListsInfo(
|
||||
Context, TemplateParameterLists.drop_back(1));
|
||||
CheckTemplatePartialSpecialization(Partial);
|
||||
}
|
||||
|
||||
if (isPartialSpecialization)
|
||||
CheckTemplatePartialSpecialization(
|
||||
cast<ClassTemplatePartialSpecializationDecl>(Specialization));
|
||||
|
||||
// C++ [temp.expl.spec]p6:
|
||||
// If a template, a member template or the member of a class template is
|
||||
// explicitly specialized then that specialization shall be declared
|
||||
|
|
@ -9381,7 +9378,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
switch (NewTSK) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
assert(
|
||||
(PrevTSK == TSK_Undeclared || PrevTSK == TSK_ImplicitInstantiation) &&
|
||||
"previous declaration must be implicit!");
|
||||
|
|
@ -9396,7 +9392,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
// instantiation.
|
||||
return false;
|
||||
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
if (PrevPointOfInstantiation.isInvalid()) {
|
||||
// The declaration itself has not actually been instantiated, so it is
|
||||
|
|
@ -9443,7 +9438,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
return false;
|
||||
|
||||
case TSK_Undeclared:
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
// We're explicitly instantiating something that may have already been
|
||||
// implicitly instantiated; that's fine.
|
||||
|
|
@ -9479,7 +9473,6 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
case TSK_ExplicitInstantiationDefinition:
|
||||
switch (PrevTSK) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
// We're explicitly instantiating something that may have already been
|
||||
// implicitly instantiated; that's fine.
|
||||
|
|
@ -9539,8 +9532,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
|||
}
|
||||
|
||||
bool Sema::CheckDependentFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, const TemplateParameterList *TemplateParams,
|
||||
const TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous) {
|
||||
// Remove anything from Previous that isn't a function template in
|
||||
// the correct context.
|
||||
|
|
@ -9577,14 +9569,13 @@ bool Sema::CheckDependentFunctionTemplateSpecialization(
|
|||
}
|
||||
|
||||
FD->setDependentTemplateSpecialization(Context, Previous.asUnresolvedSet(),
|
||||
TemplateParams, ExplicitTemplateArgs);
|
||||
ExplicitTemplateArgs);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckFunctionTemplateSpecialization(
|
||||
FunctionDecl *FD, const TemplateParameterList *TemplateParams,
|
||||
TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous,
|
||||
bool QualifiedFriend) {
|
||||
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
|
||||
LookupResult &Previous, bool QualifiedFriend) {
|
||||
// The set of function template specializations that could match this
|
||||
// explicit function template specialization.
|
||||
UnresolvedSet<8> Candidates;
|
||||
|
|
@ -9834,11 +9825,9 @@ bool Sema::CheckFunctionTemplateSpecialization(
|
|||
TemplateArgumentList *TemplArgs = TemplateArgumentList::CreateCopy(
|
||||
Context, Specialization->getTemplateSpecializationArgs()->asArray());
|
||||
FD->setFunctionTemplateSpecialization(
|
||||
Context, Specialization->getPrimaryTemplate(), TemplArgs,
|
||||
/*InsertPos=*/nullptr, SpecInfo->getTemplateSpecializationKind(),
|
||||
TemplateParams,
|
||||
ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr,
|
||||
/*PointOfInstantiation=*/SourceLocation(), /*AddSpecialization=*/true);
|
||||
Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr,
|
||||
SpecInfo->getTemplateSpecializationKind(),
|
||||
ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr);
|
||||
|
||||
// A function template specialization inherits the target attributes
|
||||
// of its template. (We require the attributes explicitly in the
|
||||
|
|
@ -9988,13 +9977,14 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
|
|||
// FIXME: Is this really valid? Other compilers reject.
|
||||
if (Member->getFriendObjectKind() != Decl::FOK_None) {
|
||||
// Preserve instantiation information.
|
||||
if (InstantiatedFrom) {
|
||||
if (auto *MD = dyn_cast<CXXMethodDecl>(Member))
|
||||
MD->setInstantiationOfMemberFunction(
|
||||
cast<CXXMethodDecl>(InstantiatedFrom), TSK_FriendDeclaration);
|
||||
else if (auto *RD = dyn_cast<CXXRecordDecl>(Member))
|
||||
RD->setInstantiationOfMemberClass(cast<CXXRecordDecl>(InstantiatedFrom),
|
||||
TSK_FriendDeclaration);
|
||||
if (InstantiatedFrom && isa<CXXMethodDecl>(Member)) {
|
||||
cast<CXXMethodDecl>(Member)->setInstantiationOfMemberFunction(
|
||||
cast<CXXMethodDecl>(InstantiatedFrom),
|
||||
cast<CXXMethodDecl>(Instantiation)->getTemplateSpecializationKind());
|
||||
} else if (InstantiatedFrom && isa<CXXRecordDecl>(Member)) {
|
||||
cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass(
|
||||
cast<CXXRecordDecl>(InstantiatedFrom),
|
||||
cast<CXXRecordDecl>(Instantiation)->getTemplateSpecializationKind());
|
||||
}
|
||||
|
||||
Previous.clear();
|
||||
|
|
@ -10081,8 +10071,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
|
|||
template<typename DeclT>
|
||||
static void completeMemberSpecializationImpl(Sema &S, DeclT *OrigD,
|
||||
SourceLocation Loc) {
|
||||
if (auto Kind = OrigD->getTemplateSpecializationKind();
|
||||
Kind != TSK_ImplicitInstantiation && Kind != TSK_FriendDeclaration)
|
||||
if (OrigD->getTemplateSpecializationKind() != TSK_ImplicitInstantiation)
|
||||
return;
|
||||
|
||||
// FIXME: Inform AST mutation listeners of this AST mutation.
|
||||
|
|
@ -10412,6 +10401,7 @@ DeclResult Sema::ActOnExplicitInstantiation(
|
|||
Specialization = ClassTemplateSpecializationDecl::Create(
|
||||
Context, Kind, ClassTemplate->getDeclContext(), KWLoc, TemplateNameLoc,
|
||||
ClassTemplate, CTAI.CanonicalConverted, CTAI.StrictPackMatch, PrevDecl);
|
||||
SetNestedNameSpecifier(*this, Specialization, SS);
|
||||
|
||||
// A MSInheritanceAttr attached to the previous declaration must be
|
||||
// propagated to the new node prior to instantiation.
|
||||
|
|
@ -10430,19 +10420,22 @@ DeclResult Sema::ActOnExplicitInstantiation(
|
|||
}
|
||||
}
|
||||
|
||||
Specialization->setExplicitInstantiationInfo(
|
||||
ExternLoc, TemplateLoc,
|
||||
ASTTemplateArgumentListInfo::Create(Context, TemplateArgs));
|
||||
Specialization->setTemplateArgsAsWritten(TemplateArgs);
|
||||
|
||||
// Set source locations for keywords.
|
||||
Specialization->setExternKeywordLoc(ExternLoc);
|
||||
Specialization->setTemplateKeywordLoc(TemplateLoc);
|
||||
Specialization->setBraceRange(SourceRange());
|
||||
|
||||
bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>();
|
||||
ProcessDeclAttributeList(S, Specialization, Attr);
|
||||
ProcessAPINotes(Specialization);
|
||||
|
||||
// Add the explicit instantiation into its lexical context.
|
||||
auto *LexicalDC = ClassTemplate->getLexicalDeclContext();
|
||||
Specialization->setLexicalDeclContext(LexicalDC);
|
||||
LexicalDC->addDecl(Specialization);
|
||||
// Add the explicit instantiation into its lexical context. However,
|
||||
// since explicit instantiations are never found by name lookup, we
|
||||
// just put it into the declaration context directly.
|
||||
Specialization->setLexicalDeclContext(CurContext);
|
||||
CurContext->addDecl(Specialization);
|
||||
|
||||
// Syntax is now OK, so return if it has no other effect on semantics.
|
||||
if (HasNoEffect) {
|
||||
|
|
@ -10771,15 +10764,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
LookupParsedName(Previous, S, &D.getCXXScopeSpec(),
|
||||
/*ObjectType=*/QualType());
|
||||
|
||||
// If the declarator is a template-id, translate the parser's template
|
||||
// argument list into our AST format.
|
||||
bool HasExplicitTemplateArgs = false;
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
HasExplicitTemplateArgs = true;
|
||||
}
|
||||
|
||||
if (!R->isFunctionType()) {
|
||||
// C++ [temp.explicit]p1:
|
||||
// A [...] static data member of a class template can be explicitly
|
||||
|
|
@ -10829,7 +10813,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (!HasExplicitTemplateArgs) {
|
||||
if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {
|
||||
// C++1y [temp.explicit]p3:
|
||||
// If the explicit instantiation is for a variable, the unqualified-id
|
||||
// in the declaration shall be a template-id.
|
||||
|
|
@ -10841,8 +10825,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
return true;
|
||||
}
|
||||
|
||||
DeclResult Res = CheckVarTemplateId(PrevTemplate, TemplateLoc,
|
||||
D.getIdentifierLoc(), TemplateArgs);
|
||||
// Translate the parser's template argument list into our AST format.
|
||||
TemplateArgumentListInfo TemplateArgs =
|
||||
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
|
||||
DeclResult Res =
|
||||
CheckVarTemplateId(PrevTemplate, TemplateLoc, D.getIdentifierLoc(),
|
||||
TemplateArgs, /*SetWrittenArgs=*/true);
|
||||
if (Res.isInvalid())
|
||||
return true;
|
||||
|
||||
|
|
@ -10890,10 +10879,8 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
// Instantiate static data member or variable template.
|
||||
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
|
||||
if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Prev)) {
|
||||
assert(HasExplicitTemplateArgs);
|
||||
VTSD->setExplicitInstantiationInfo(
|
||||
ExternLoc, TemplateLoc,
|
||||
ASTTemplateArgumentListInfo::Create(Context, TemplateArgs));
|
||||
VTSD->setExternKeywordLoc(ExternLoc);
|
||||
VTSD->setTemplateKeywordLoc(TemplateLoc);
|
||||
}
|
||||
|
||||
// Merge attributes.
|
||||
|
|
@ -10922,6 +10909,15 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
|
|||
return (Decl *)nullptr;
|
||||
}
|
||||
|
||||
// If the declarator is a template-id, translate the parser's template
|
||||
// argument list into our AST format.
|
||||
bool HasExplicitTemplateArgs = false;
|
||||
TemplateArgumentListInfo TemplateArgs;
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
|
||||
HasExplicitTemplateArgs = true;
|
||||
}
|
||||
|
||||
// C++ [temp.explicit]p1:
|
||||
// A [...] function [...] can be explicitly instantiated from its template.
|
||||
// A member function [...] of a class template can be explicitly
|
||||
|
|
|
|||
|
|
@ -3182,16 +3182,36 @@ CheckDeducedArgumentConstraints(Sema &S, NamedDecl *Template,
|
|||
ArrayRef<TemplateArgument> CanonicalDeducedArgs,
|
||||
TemplateDeductionInfo &Info) {
|
||||
llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints;
|
||||
if (auto *TD = dyn_cast<ClassTemplatePartialSpecializationDecl>(Template))
|
||||
bool DeducedArgsNeedReplacement = false;
|
||||
if (auto *TD = dyn_cast<ClassTemplatePartialSpecializationDecl>(Template)) {
|
||||
TD->getAssociatedConstraints(AssociatedConstraints);
|
||||
else if (auto *TD = dyn_cast<VarTemplatePartialSpecializationDecl>(Template))
|
||||
DeducedArgsNeedReplacement = !TD->isClassScopeExplicitSpecialization();
|
||||
} else if (auto *TD =
|
||||
dyn_cast<VarTemplatePartialSpecializationDecl>(Template)) {
|
||||
TD->getAssociatedConstraints(AssociatedConstraints);
|
||||
else
|
||||
DeducedArgsNeedReplacement = !TD->isClassScopeExplicitSpecialization();
|
||||
} else {
|
||||
cast<TemplateDecl>(Template)->getAssociatedConstraints(
|
||||
AssociatedConstraints);
|
||||
}
|
||||
|
||||
MultiLevelTemplateArgumentList MLTAL =
|
||||
S.getTemplateInstantiationArgs(Template, SugaredDeducedArgs);
|
||||
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)
|
||||
Innermost = SugaredDeducedArgs;
|
||||
|
||||
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, SugaredDeducedArgs);
|
||||
|
||||
if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL,
|
||||
Info.getLocation(),
|
||||
|
|
@ -3954,8 +3974,9 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
|
|||
bool IsLambda = isLambdaCallOperator(FD) || isLambdaConversionOperator(FD);
|
||||
if (!IsLambda && !IsIncomplete) {
|
||||
if (CheckFunctionTemplateConstraints(
|
||||
Info.getLocation(), FunctionTemplate, CTAI.CanonicalConverted,
|
||||
Info.AssociatedConstraintsSatisfaction))
|
||||
Info.getLocation(),
|
||||
FunctionTemplate->getCanonicalDecl()->getTemplatedDecl(),
|
||||
CTAI.CanonicalConverted, Info.AssociatedConstraintsSatisfaction))
|
||||
return TemplateDeductionResult::MiscellaneousDeductionFailure;
|
||||
if (!Info.AssociatedConstraintsSatisfaction.IsSatisfied) {
|
||||
Info.reset(Info.takeSugared(), TemplateArgumentList::CreateCopy(
|
||||
|
|
@ -4001,8 +4022,8 @@ TemplateDeductionResult Sema::FinishTemplateArgumentDeduction(
|
|||
// ([temp.constr.constr]). If the constraints are not satisfied, type
|
||||
// deduction fails.
|
||||
if (IsLambda && !IsIncomplete) {
|
||||
if (CheckFunctionSpecializationConstraints(
|
||||
Info.getLocation(), Specialization,
|
||||
if (CheckFunctionTemplateConstraints(
|
||||
Info.getLocation(), Specialization, CTAI.CanonicalConverted,
|
||||
Info.AssociatedConstraintsSatisfaction))
|
||||
return TemplateDeductionResult::MiscellaneousDeductionFailure;
|
||||
|
||||
|
|
@ -6028,7 +6049,7 @@ FunctionTemplateDecl *Sema::getMoreSpecializedTemplate(
|
|||
// function parameters that positionally correspond between the two
|
||||
// templates are not of the same type, neither template is more specialized
|
||||
// than the other.
|
||||
if (!TemplateParameterListsAreEqual(FT1, TPL1, FT2, TPL2, false,
|
||||
if (!TemplateParameterListsAreEqual(TPL1, TPL2, false,
|
||||
Sema::TPL_TemplateParamsEquivalent))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -6383,7 +6404,7 @@ getMoreSpecialized(Sema &S, QualType T1, QualType T2, TemplateLikeDecl *P1,
|
|||
// function parameters that positionally correspond between the two
|
||||
// templates are not of the same type, neither template is more specialized
|
||||
// than the other.
|
||||
if (!S.TemplateParameterListsAreEqual(P1, TPL1, P2, TPL2, false,
|
||||
if (!S.TemplateParameterListsAreEqual(TPL1, TPL2, false,
|
||||
Sema::TPL_TemplateParamsEquivalent))
|
||||
return nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ static bool HaveSameAssociatedConstraints(
|
|||
return true;
|
||||
|
||||
// General case: pairwise compare each associated constraint expression.
|
||||
Sema::TemplateCompareNewDeclInfo NewInfo(New);
|
||||
for (size_t I = 0, E = OldACs.size(); I != E; ++I)
|
||||
if (!SemaRef.AreConstraintExpressionsEqual(Old, OldACs[I].ConstraintExpr,
|
||||
New, NewACs[I].ConstraintExpr))
|
||||
if (!SemaRef.AreConstraintExpressionsEqual(
|
||||
Old, OldACs[I].ConstraintExpr, NewInfo, NewACs[I].ConstraintExpr))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
@ -502,7 +503,6 @@ struct ConvertConstructorToDeductionGuideTransform {
|
|||
: SemaRef(S), Template(Template) {
|
||||
// If the template is nested, then we need to use the original
|
||||
// pattern to iterate over the constructors.
|
||||
// FIXME: Should this just use getTemplateInstantiationPattern?
|
||||
ClassTemplateDecl *Pattern = Template;
|
||||
while (Pattern->getInstantiatedFromMemberTemplate()) {
|
||||
if (Pattern->isMemberSpecialization())
|
||||
|
|
@ -510,9 +510,9 @@ struct ConvertConstructorToDeductionGuideTransform {
|
|||
Pattern = Pattern->getInstantiatedFromMemberTemplate();
|
||||
NestedPattern = Pattern;
|
||||
}
|
||||
|
||||
if (NestedPattern)
|
||||
OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(
|
||||
Decl::castFromDeclContext(Template->getDeclContext()));
|
||||
OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template);
|
||||
}
|
||||
|
||||
Sema &SemaRef;
|
||||
|
|
@ -1053,9 +1053,52 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F,
|
|||
}
|
||||
}
|
||||
|
||||
MultiLevelTemplateArgumentList ArgsForBuildingRC =
|
||||
SemaRef.getTemplateInstantiationArgs(F, TemplateArgsForBuildingRC);
|
||||
// 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);
|
||||
// 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.
|
||||
//
|
||||
// For example:
|
||||
// template <typename T> // depth 0
|
||||
// struct Outer {
|
||||
// template <typename U>
|
||||
// struct Foo { Foo(U); };
|
||||
//
|
||||
// template <typename U> // depth 1
|
||||
// requires C<U>
|
||||
// Foo(U) -> Foo<int>;
|
||||
// };
|
||||
// template <typename U>
|
||||
// using AFoo = Outer<int>::Foo<U>;
|
||||
//
|
||||
// In this scenario, the deduction guide for `Foo` inside `Outer<int>`:
|
||||
// - The occurrence of U in the require-expression is [depth:1, index:0]
|
||||
// - 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);
|
||||
}
|
||||
|
||||
ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC);
|
||||
if (E.isInvalid())
|
||||
|
|
|
|||
|
|
@ -49,6 +49,38 @@ using namespace sema;
|
|||
//===----------------------------------------------------------------------===/
|
||||
|
||||
namespace {
|
||||
namespace TemplateInstArgsHelpers {
|
||||
struct Response {
|
||||
const Decl *NextDecl = nullptr;
|
||||
bool IsDone = false;
|
||||
bool ClearRelativeToPrimary = true;
|
||||
static Response Done() {
|
||||
Response R;
|
||||
R.IsDone = true;
|
||||
return R;
|
||||
}
|
||||
static Response ChangeDecl(const Decl *ND) {
|
||||
Response R;
|
||||
R.NextDecl = ND;
|
||||
return R;
|
||||
}
|
||||
static Response ChangeDecl(const DeclContext *Ctx) {
|
||||
Response R;
|
||||
R.NextDecl = Decl::castFromDeclContext(Ctx);
|
||||
return R;
|
||||
}
|
||||
|
||||
static Response UseNextDecl(const Decl *CurDecl) {
|
||||
return ChangeDecl(CurDecl->getDeclContext());
|
||||
}
|
||||
|
||||
static Response DontClearRelativeToPrimaryNextDecl(const Decl *CurDecl) {
|
||||
Response R = Response::UseNextDecl(CurDecl);
|
||||
R.ClearRelativeToPrimary = false;
|
||||
return R;
|
||||
}
|
||||
};
|
||||
|
||||
// Retrieve the primary template for a lambda call operator. It's
|
||||
// unfortunate that we only have the mappings of call operators rather
|
||||
// than lambda classes.
|
||||
|
|
@ -136,197 +168,397 @@ bool isLambdaEnclosedByTypeAliasDecl(
|
|||
.TraverseType(Underlying);
|
||||
}
|
||||
|
||||
// Add template arguments from a variable template instantiation.
|
||||
Response
|
||||
HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec,
|
||||
MultiLevelTemplateArgumentList &Result,
|
||||
bool SkipForSpecialization) {
|
||||
// For a class-scope explicit specialization, there are no template arguments
|
||||
// at this level, but there may be enclosing template arguments.
|
||||
if (VarTemplSpec->isClassScopeExplicitSpecialization())
|
||||
return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);
|
||||
|
||||
// We're done when we hit an explicit specialization.
|
||||
if (VarTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
|
||||
!isa<VarTemplatePartialSpecializationDecl>(VarTemplSpec))
|
||||
return Response::Done();
|
||||
|
||||
// If this variable template specialization was instantiated from a
|
||||
// specialized member that is a variable template, we're done.
|
||||
assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?");
|
||||
llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
|
||||
Specialized = VarTemplSpec->getSpecializedTemplateOrPartial();
|
||||
if (VarTemplatePartialSpecializationDecl *Partial =
|
||||
dyn_cast<VarTemplatePartialSpecializationDecl *>(Specialized)) {
|
||||
if (!SkipForSpecialization)
|
||||
Result.addOuterTemplateArguments(
|
||||
Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
|
||||
/*Final=*/false);
|
||||
if (Partial->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
} else {
|
||||
VarTemplateDecl *Tmpl = cast<VarTemplateDecl *>(Specialized);
|
||||
if (!SkipForSpecialization)
|
||||
Result.addOuterTemplateArguments(
|
||||
Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(),
|
||||
/*Final=*/false);
|
||||
if (Tmpl->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
}
|
||||
return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec);
|
||||
}
|
||||
|
||||
// If we have a template template parameter with translation unit context,
|
||||
// then we're performing substitution into a default template argument of
|
||||
// this template template parameter before we've constructed the template
|
||||
// that will own this template template parameter. In this case, we
|
||||
// use empty template parameter lists for all of the outer templates
|
||||
// to avoid performing any substitutions.
|
||||
Response
|
||||
HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP,
|
||||
MultiLevelTemplateArgumentList &Result) {
|
||||
for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I)
|
||||
Result.addOuterTemplateArguments(std::nullopt);
|
||||
return Response::Done();
|
||||
}
|
||||
|
||||
Response HandlePartialClassTemplateSpec(
|
||||
const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec,
|
||||
MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) {
|
||||
if (!SkipForSpecialization)
|
||||
Result.addOuterRetainedLevels(PartialClassTemplSpec->getTemplateDepth());
|
||||
return Response::Done();
|
||||
}
|
||||
|
||||
// Add template arguments from a class template instantiation.
|
||||
Response
|
||||
HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec,
|
||||
MultiLevelTemplateArgumentList &Result,
|
||||
bool SkipForSpecialization) {
|
||||
if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) {
|
||||
// We're done when we hit an explicit specialization.
|
||||
if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization &&
|
||||
!isa<ClassTemplatePartialSpecializationDecl>(ClassTemplSpec))
|
||||
return Response::Done();
|
||||
|
||||
if (!SkipForSpecialization)
|
||||
Result.addOuterTemplateArguments(
|
||||
const_cast<ClassTemplateSpecializationDecl *>(ClassTemplSpec),
|
||||
ClassTemplSpec->getTemplateInstantiationArgs().asArray(),
|
||||
/*Final=*/false);
|
||||
|
||||
// If this class template specialization was instantiated from a
|
||||
// specialized member that is a class template, we're done.
|
||||
assert(ClassTemplSpec->getSpecializedTemplate() && "No class template?");
|
||||
if (ClassTemplSpec->getSpecializedTemplate()->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
|
||||
// If this was instantiated from a partial template specialization, we need
|
||||
// to get the next level of declaration context from the partial
|
||||
// specialization, as the ClassTemplateSpecializationDecl's
|
||||
// DeclContext/LexicalDeclContext will be for the primary template.
|
||||
if (auto *InstFromPartialTempl =
|
||||
ClassTemplSpec->getSpecializedTemplateOrPartial()
|
||||
.dyn_cast<ClassTemplatePartialSpecializationDecl *>())
|
||||
return Response::ChangeDecl(
|
||||
InstFromPartialTempl->getLexicalDeclContext());
|
||||
}
|
||||
return Response::UseNextDecl(ClassTemplSpec);
|
||||
}
|
||||
|
||||
Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function,
|
||||
MultiLevelTemplateArgumentList &Result,
|
||||
const FunctionDecl *Pattern, bool RelativeToPrimary,
|
||||
bool ForConstraintInstantiation,
|
||||
bool ForDefaultArgumentSubstitution) {
|
||||
// Add template arguments from a function template specialization.
|
||||
if (!RelativeToPrimary &&
|
||||
Function->getTemplateSpecializationKindForInstantiation() ==
|
||||
TSK_ExplicitSpecialization)
|
||||
return Response::Done();
|
||||
|
||||
if (!RelativeToPrimary &&
|
||||
Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
|
||||
// This is an implicit instantiation of an explicit specialization. We
|
||||
// don't get any template arguments from this function but might get
|
||||
// some from an enclosing template.
|
||||
return Response::UseNextDecl(Function);
|
||||
} else if (const TemplateArgumentList *TemplateArgs =
|
||||
Function->getTemplateSpecializationArgs()) {
|
||||
// Add the template arguments for this specialization.
|
||||
Result.addOuterTemplateArguments(const_cast<FunctionDecl *>(Function),
|
||||
TemplateArgs->asArray(),
|
||||
/*Final=*/false);
|
||||
|
||||
if (RelativeToPrimary &&
|
||||
(Function->getTemplateSpecializationKind() ==
|
||||
TSK_ExplicitSpecialization ||
|
||||
(Function->getFriendObjectKind() &&
|
||||
!Function->getPrimaryTemplate()->getFriendObjectKind())))
|
||||
return Response::UseNextDecl(Function);
|
||||
|
||||
// If this function was instantiated from a specialized member that is
|
||||
// a function template, we're done.
|
||||
assert(Function->getPrimaryTemplate() && "No function template?");
|
||||
if (!ForDefaultArgumentSubstitution &&
|
||||
Function->getPrimaryTemplate()->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
|
||||
// If this function is a generic lambda specialization, we are done.
|
||||
if (!ForConstraintInstantiation &&
|
||||
isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function))
|
||||
return Response::Done();
|
||||
|
||||
} else if (auto *Template = Function->getDescribedFunctionTemplate()) {
|
||||
assert(
|
||||
(ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
|
||||
"Outer template not instantiated?");
|
||||
if (ForConstraintInstantiation) {
|
||||
for (auto &Inst : llvm::reverse(SemaRef.CodeSynthesisContexts)) {
|
||||
if (Inst.Kind == Sema::CodeSynthesisContext::ConstraintsCheck &&
|
||||
Inst.Entity == Template) {
|
||||
// After CWG2369, the outer templates are not instantiated when
|
||||
// checking its associated constraints. So add them back through the
|
||||
// synthesis context; this is useful for e.g. nested constraints
|
||||
// involving lambdas.
|
||||
Result.addOuterTemplateArguments(Template, Inst.template_arguments(),
|
||||
/*Final=*/false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If this is a friend or local declaration and it declares an entity at
|
||||
// namespace scope, take arguments from its lexical parent
|
||||
// instead of its semantic parent, unless of course the pattern we're
|
||||
// instantiating actually comes from the file's context!
|
||||
if ((Function->getFriendObjectKind() || Function->isLocalExternDecl()) &&
|
||||
Function->getNonTransparentDeclContext()->isFileContext() &&
|
||||
(!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) {
|
||||
return Response::ChangeDecl(Function->getLexicalDeclContext());
|
||||
}
|
||||
|
||||
if (ForConstraintInstantiation && Function->getFriendObjectKind())
|
||||
return Response::ChangeDecl(Function->getLexicalDeclContext());
|
||||
return Response::UseNextDecl(Function);
|
||||
}
|
||||
|
||||
Response HandleFunctionTemplateDecl(Sema &SemaRef,
|
||||
const FunctionTemplateDecl *FTD,
|
||||
MultiLevelTemplateArgumentList &Result) {
|
||||
if (!isa<ClassTemplateSpecializationDecl>(FTD->getDeclContext())) {
|
||||
Result.addOuterTemplateArguments(
|
||||
const_cast<FunctionTemplateDecl *>(FTD),
|
||||
const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(
|
||||
SemaRef.Context),
|
||||
/*Final=*/false);
|
||||
|
||||
NestedNameSpecifier NNS = FTD->getTemplatedDecl()->getQualifier();
|
||||
|
||||
for (const Type *Ty = NNS.getKind() == NestedNameSpecifier::Kind::Type
|
||||
? NNS.getAsType()
|
||||
: nullptr,
|
||||
*NextTy = nullptr;
|
||||
Ty && Ty->isInstantiationDependentType();
|
||||
Ty = std::exchange(NextTy, nullptr)) {
|
||||
if (NestedNameSpecifier P = Ty->getPrefix();
|
||||
P.getKind() == NestedNameSpecifier::Kind::Type)
|
||||
NextTy = P.getAsType();
|
||||
const auto *TSTy = dyn_cast<TemplateSpecializationType>(Ty);
|
||||
if (!TSTy)
|
||||
continue;
|
||||
|
||||
ArrayRef<TemplateArgument> Arguments = TSTy->template_arguments();
|
||||
// Prefer template arguments from the injected-class-type if possible.
|
||||
// For example,
|
||||
// ```cpp
|
||||
// template <class... Pack> struct S {
|
||||
// template <class T> void foo();
|
||||
// };
|
||||
// template <class... Pack> template <class T>
|
||||
// ^^^^^^^^^^^^^ InjectedTemplateArgs
|
||||
// They're of kind TemplateArgument::Pack, not of
|
||||
// TemplateArgument::Type.
|
||||
// void S<Pack...>::foo() {}
|
||||
// ^^^^^^^
|
||||
// TSTy->template_arguments() (which are of PackExpansionType)
|
||||
// ```
|
||||
// This meets the contract in
|
||||
// TreeTransform::TryExpandParameterPacks that the template arguments
|
||||
// for unexpanded parameters should be of a Pack kind.
|
||||
if (TSTy->isCurrentInstantiation()) {
|
||||
auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
|
||||
if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
|
||||
Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
|
||||
else if (auto *Specialization =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(RD))
|
||||
Arguments = Specialization->getTemplateInstantiationArgs().asArray();
|
||||
}
|
||||
Result.addOuterTemplateArguments(
|
||||
TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
|
||||
/*Final=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
return Response::ChangeDecl(FTD->getLexicalDeclContext());
|
||||
}
|
||||
|
||||
Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec,
|
||||
MultiLevelTemplateArgumentList &Result,
|
||||
ASTContext &Context,
|
||||
bool ForConstraintInstantiation) {
|
||||
if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) {
|
||||
assert(
|
||||
(ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) &&
|
||||
"Outer template not instantiated?");
|
||||
if (ClassTemplate->isMemberSpecialization())
|
||||
return Response::Done();
|
||||
if (ForConstraintInstantiation)
|
||||
Result.addOuterTemplateArguments(
|
||||
const_cast<CXXRecordDecl *>(Rec),
|
||||
ClassTemplate->getInjectedTemplateArgs(SemaRef.Context),
|
||||
/*Final=*/false);
|
||||
}
|
||||
|
||||
if (const MemberSpecializationInfo *MSInfo =
|
||||
Rec->getMemberSpecializationInfo())
|
||||
if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
return Response::Done();
|
||||
|
||||
bool IsFriend = Rec->getFriendObjectKind() ||
|
||||
(Rec->getDescribedClassTemplate() &&
|
||||
Rec->getDescribedClassTemplate()->getFriendObjectKind());
|
||||
if (ForConstraintInstantiation && IsFriend &&
|
||||
Rec->getNonTransparentDeclContext()->isFileContext()) {
|
||||
return Response::ChangeDecl(Rec->getLexicalDeclContext());
|
||||
}
|
||||
|
||||
// This is to make sure we pick up the VarTemplateSpecializationDecl or the
|
||||
// TypeAliasTemplateDecl that this lambda is defined inside of.
|
||||
if (Rec->isLambda()) {
|
||||
if (const Decl *LCD = Rec->getLambdaContextDecl())
|
||||
return Response::ChangeDecl(LCD);
|
||||
// Retrieve the template arguments for a using alias declaration.
|
||||
// This is necessary for constraint checking, since we always keep
|
||||
// constraints relative to the primary template.
|
||||
if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef);
|
||||
ForConstraintInstantiation && TypeAlias) {
|
||||
if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(),
|
||||
TypeAlias.PrimaryTypeAliasDecl)) {
|
||||
Result.addOuterTemplateArguments(TypeAlias.Template,
|
||||
TypeAlias.AssociatedTemplateArguments,
|
||||
/*Final=*/false);
|
||||
// Visit the parent of the current type alias declaration rather than
|
||||
// the lambda thereof.
|
||||
// E.g., in the following example:
|
||||
// struct S {
|
||||
// template <class> using T = decltype([]<Concept> {} ());
|
||||
// };
|
||||
// void foo() {
|
||||
// S::T var;
|
||||
// }
|
||||
// The instantiated lambda expression (which we're visiting at 'var')
|
||||
// has a function DeclContext 'foo' rather than the Record DeclContext
|
||||
// S. This seems to be an oversight to me that we may want to set a
|
||||
// Sema Context from the CXXScopeSpec before substituting into T.
|
||||
return Response::ChangeDecl(TypeAlias.Template->getDeclContext());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Response::UseNextDecl(Rec);
|
||||
}
|
||||
|
||||
Response HandleImplicitConceptSpecializationDecl(
|
||||
const ImplicitConceptSpecializationDecl *CSD,
|
||||
MultiLevelTemplateArgumentList &Result) {
|
||||
Result.addOuterTemplateArguments(
|
||||
const_cast<ImplicitConceptSpecializationDecl *>(CSD),
|
||||
CSD->getTemplateArguments(),
|
||||
/*Final=*/false);
|
||||
return Response::UseNextDecl(CSD);
|
||||
}
|
||||
|
||||
Response HandleGenericDeclContext(const Decl *CurDecl) {
|
||||
return Response::UseNextDecl(CurDecl);
|
||||
}
|
||||
} // namespace TemplateInstArgsHelpers
|
||||
} // namespace
|
||||
|
||||
MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
|
||||
const Decl *D, std::optional<ArrayRef<TemplateArgument>> Innermost,
|
||||
UnsignedOrNone NumLevels, bool SkipInnerNonInstantiated) {
|
||||
MultiLevelTemplateArgumentList TemplateArgs;
|
||||
const NamedDecl *ND, const DeclContext *DC, bool Final,
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost, bool RelativeToPrimary,
|
||||
const FunctionDecl *Pattern, bool ForConstraintInstantiation,
|
||||
bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) {
|
||||
assert((ND || DC) && "Can't find arguments for a decl if one isn't provided");
|
||||
// Accumulate the set of template argument lists in this structure.
|
||||
MultiLevelTemplateArgumentList Result;
|
||||
|
||||
// The scope being followed for an out-of-line-definition.
|
||||
NestedNameSpecifier Qualifier = std::nullopt;
|
||||
ArrayRef<TemplateParameterList *> TPLs;
|
||||
using namespace TemplateInstArgsHelpers;
|
||||
const Decl *CurDecl = ND;
|
||||
|
||||
while (!NumLevels || *NumLevels != 0U) {
|
||||
bool Final = false;
|
||||
if (const TemplateParameterList *TPL =
|
||||
isa<TemplateDecl>(D)
|
||||
? cast<TemplateDecl>(D)->getTemplateParameters()
|
||||
: D->getDescribedTemplateParams()) {
|
||||
// Template-like entities should always produce a final substitution
|
||||
// level, as they shouldn't be transformed again.
|
||||
Final = true;
|
||||
// If Innermost is provided, use that as the template arguments.
|
||||
if (!Innermost)
|
||||
Innermost = TPL->getInjectedTemplateArgs(Context);
|
||||
else
|
||||
SkipInnerNonInstantiated = false;
|
||||
if (Innermost) {
|
||||
Result.addOuterTemplateArguments(const_cast<NamedDecl *>(ND), *Innermost,
|
||||
Final);
|
||||
// Populate placeholder template arguments for TemplateTemplateParmDecls.
|
||||
// This is essential for the case e.g.
|
||||
//
|
||||
// template <class> concept Concept = false;
|
||||
// template <template <Concept C> class T> void foo(T<int>)
|
||||
//
|
||||
// where parameter C has a depth of 1 but the substituting argument `int`
|
||||
// has a depth of 0.
|
||||
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl))
|
||||
HandleDefaultTempArgIntoTempTempParam(TTP, Result);
|
||||
CurDecl = DC ? Decl::castFromDeclContext(DC)
|
||||
: Response::UseNextDecl(CurDecl).NextDecl;
|
||||
} else if (!CurDecl)
|
||||
CurDecl = Decl::castFromDeclContext(DC);
|
||||
|
||||
while (!CurDecl->isFileContextDecl()) {
|
||||
Response R;
|
||||
if (const auto *VarTemplSpec =
|
||||
dyn_cast<VarTemplateSpecializationDecl>(CurDecl)) {
|
||||
R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization);
|
||||
} else if (const auto *PartialClassTemplSpec =
|
||||
dyn_cast<ClassTemplatePartialSpecializationDecl>(CurDecl)) {
|
||||
R = HandlePartialClassTemplateSpec(PartialClassTemplSpec, Result,
|
||||
SkipForSpecialization);
|
||||
} else if (const auto *ClassTemplSpec =
|
||||
dyn_cast<ClassTemplateSpecializationDecl>(CurDecl)) {
|
||||
R = HandleClassTemplateSpec(ClassTemplSpec, Result,
|
||||
SkipForSpecialization);
|
||||
} else if (const auto *Function = dyn_cast<FunctionDecl>(CurDecl)) {
|
||||
R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary,
|
||||
ForConstraintInstantiation,
|
||||
ForDefaultArgumentSubstitution);
|
||||
} else if (const auto *Rec = dyn_cast<CXXRecordDecl>(CurDecl)) {
|
||||
R = HandleRecordDecl(*this, Rec, Result, Context,
|
||||
ForConstraintInstantiation);
|
||||
} else if (const auto *CSD =
|
||||
dyn_cast<ImplicitConceptSpecializationDecl>(CurDecl)) {
|
||||
R = HandleImplicitConceptSpecializationDecl(CSD, Result);
|
||||
} else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CurDecl)) {
|
||||
R = HandleFunctionTemplateDecl(*this, FTD, Result);
|
||||
} else if (const auto *CTD = dyn_cast<ClassTemplateDecl>(CurDecl)) {
|
||||
R = Response::ChangeDecl(CTD->getLexicalDeclContext());
|
||||
} else if (!isa<DeclContext>(CurDecl)) {
|
||||
R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl);
|
||||
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
|
||||
R = HandleDefaultTempArgIntoTempTempParam(TTP, Result);
|
||||
}
|
||||
} else {
|
||||
assert(!Innermost &&
|
||||
"Shouldn't provide innermost for a non-template-like declaration");
|
||||
|
||||
if (isa<ClassTemplateSpecializationDecl, VarTemplateSpecializationDecl>(
|
||||
D)) {
|
||||
auto specCase = [&](const auto *ND) {
|
||||
if (ND->getSpecializationKind() == TSK_ExplicitSpecialization) {
|
||||
assert(TPLs.empty());
|
||||
return;
|
||||
}
|
||||
SkipInnerNonInstantiated = false;
|
||||
Innermost = ND->getTemplateInstantiationArgs().asArray();
|
||||
};
|
||||
if (isa<ClassTemplateSpecializationDecl>(D))
|
||||
specCase(cast<ClassTemplateSpecializationDecl>(D));
|
||||
else
|
||||
specCase(cast<VarTemplateSpecializationDecl>(D));
|
||||
} else if (isa<ImplicitConceptSpecializationDecl>(D)) {
|
||||
SkipInnerNonInstantiated = false;
|
||||
Innermost =
|
||||
cast<ImplicitConceptSpecializationDecl>(D)->getTemplateArguments();
|
||||
Final = true;
|
||||
} else if (const auto *ND = dyn_cast<FunctionDecl>(D)) {
|
||||
const FunctionTemplateSpecializationInfo *Info =
|
||||
ND->getTemplateSpecializationInfo();
|
||||
if (!Info || Info->getTemplateSpecializationKind() ==
|
||||
TSK_ExplicitSpecialization) {
|
||||
assert(TPLs.empty());
|
||||
} else {
|
||||
SkipInnerNonInstantiated = false;
|
||||
Innermost = Info->TemplateArguments->asArray();
|
||||
}
|
||||
} else if (const auto *ND = dyn_cast<CXXRecordDecl>(D);
|
||||
ND && ND->isLambda()) {
|
||||
assert(TPLs.empty() &&
|
||||
"lambdas can't be part of an out-of-line definition");
|
||||
// FIXME: If this lambda is enclosed by a type alias template, look
|
||||
// into the current CodeSynthesisContexts to find the template
|
||||
// arguments used to specialize it.
|
||||
if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef);
|
||||
TypeAlias &&
|
||||
isLambdaEnclosedByTypeAliasDecl(ND->getLambdaCallOperator(),
|
||||
TypeAlias.PrimaryTypeAliasDecl)) {
|
||||
Innermost = TypeAlias.AssociatedTemplateArguments;
|
||||
Final = true;
|
||||
D = TypeAlias.Template;
|
||||
continue;
|
||||
}
|
||||
if (const Decl *LCD = ND->getLambdaContextDecl()) {
|
||||
D = LCD;
|
||||
continue;
|
||||
}
|
||||
} else if (isa<TranslationUnitDecl, NamespaceBaseDecl, ExportDecl,
|
||||
LinkageSpecDecl>(D)) {
|
||||
// The end of the line, there can't be any template arguments further.
|
||||
assert(TPLs.empty());
|
||||
assert(!NumLevels && "Declaration had less levels than expected");
|
||||
return TemplateArgs;
|
||||
}
|
||||
R = HandleGenericDeclContext(CurDecl);
|
||||
}
|
||||
|
||||
const Decl *CurDecl = D;
|
||||
|
||||
// There is either a current qualifier for an out-of-line definition being
|
||||
// followed, in which case it should be advanced, or the next qualifier
|
||||
// and template parameter listss should be retrieved from the current
|
||||
// declaration, if any.
|
||||
bool InOutOfLineDefinition = Qualifier != std::nullopt;
|
||||
switch (Qualifier.getKind()) {
|
||||
case NestedNameSpecifier::Kind::Null: {
|
||||
// Get the current qualifier and template parameter lists.
|
||||
assert(TPLs.empty());
|
||||
if (auto *TD = dyn_cast<TemplateDecl>(D)) {
|
||||
D = TD->getTemplatedDecl();
|
||||
// One of the template entities which doesn't have a templated decl.
|
||||
if (!D)
|
||||
break;
|
||||
}
|
||||
if (auto *DD = dyn_cast<DeclaratorDecl>(D)) {
|
||||
TPLs = DD->getTemplateParameterLists();
|
||||
Qualifier = DD->getQualifier();
|
||||
} else if (const auto *TD = dyn_cast<TagDecl>(D)) {
|
||||
TPLs = TD->getTemplateParameterLists();
|
||||
Qualifier = TD->getQualifier();
|
||||
}
|
||||
assert((Qualifier || TPLs.empty()) &&
|
||||
"template parameter lists without qualifier");
|
||||
break;
|
||||
}
|
||||
case NestedNameSpecifier::Kind::Namespace:
|
||||
case NestedNameSpecifier::Kind::Global:
|
||||
llvm_unreachable("handled above");
|
||||
case NestedNameSpecifier::Kind::Type:
|
||||
Qualifier = Qualifier.getAsType()->getPrefix();
|
||||
break;
|
||||
case NestedNameSpecifier::Kind::MicrosoftSuper:
|
||||
Qualifier = std::nullopt;
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next declaration from the current qualifier.
|
||||
switch (Qualifier.getKind()) {
|
||||
case NestedNameSpecifier::Kind::Null:
|
||||
// If there is no qualifier, the template context always follows
|
||||
// lexically.
|
||||
D = Decl::castFromDeclContext(CurDecl->getLexicalDeclContext());
|
||||
break;
|
||||
case NestedNameSpecifier::Kind::Namespace:
|
||||
case NestedNameSpecifier::Kind::Global:
|
||||
// Skip namespace, as they are never templated.
|
||||
D = Context.getTranslationUnitDecl();
|
||||
break;
|
||||
case NestedNameSpecifier::Kind::Type:
|
||||
if (const Type *T = Qualifier.getAsType();
|
||||
const auto *TT = T->getAs<TagType>())
|
||||
D = TT->getDecl();
|
||||
else if (const auto *TST = T->getAsNonAliasTemplateSpecializationType())
|
||||
D = TST->getTemplateName().getAsTemplateDecl(/*IgnoreDeduced=*/true);
|
||||
else
|
||||
llvm_unreachable("unexpected type kind");
|
||||
break;
|
||||
case NestedNameSpecifier::Kind::MicrosoftSuper:
|
||||
D = Qualifier.getAsMicrosoftSuper();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Innermost)
|
||||
continue;
|
||||
|
||||
auto DeclArgs = *std::exchange(Innermost, std::nullopt);
|
||||
assert(!DeclArgs.empty());
|
||||
|
||||
if (InOutOfLineDefinition) {
|
||||
// There either may or may not be a template parameter list corresponding
|
||||
// to the current qualifier chunk.
|
||||
// A template level only exists where there is a non-empty template
|
||||
// parameter list. Explicit specializations, ie `template <>` are never a
|
||||
// template level.
|
||||
TemplateParameterList *TPL =
|
||||
!TPLs.empty() ? TPLs.consume_back() : nullptr;
|
||||
if (!TPL || TPL->empty())
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!SkipInnerNonInstantiated)
|
||||
TemplateArgs.addOuterTemplateArguments(const_cast<Decl *>(CurDecl),
|
||||
DeclArgs, Final);
|
||||
|
||||
// A new level was just added. So if there is a level limit, decrement it.
|
||||
if (NumLevels)
|
||||
NumLevels = *NumLevels - 1U;
|
||||
|
||||
// FIXME: Workaround for template template parameters on other template
|
||||
// template parameters and on type alias templates.
|
||||
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
|
||||
unsigned ExtraLevels = TTP->getDepth() - D->getTemplateDepth() + 1;
|
||||
if (NumLevels) {
|
||||
ExtraLevels = std::min(ExtraLevels, *NumLevels);
|
||||
NumLevels = *NumLevels - ExtraLevels;
|
||||
}
|
||||
for (unsigned I = 0; I < ExtraLevels; ++I)
|
||||
TemplateArgs.addOuterTemplateArguments(std::nullopt);
|
||||
}
|
||||
if (R.IsDone)
|
||||
return Result;
|
||||
if (R.ClearRelativeToPrimary)
|
||||
RelativeToPrimary = false;
|
||||
assert(R.NextDecl);
|
||||
CurDecl = R.NextDecl;
|
||||
}
|
||||
return TemplateArgs;
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
|
||||
|
|
@ -1509,8 +1741,10 @@ namespace {
|
|||
|
||||
CXXRecordDecl::LambdaDependencyKind
|
||||
ComputeLambdaDependency(LambdaScopeInfo *LSI) {
|
||||
if (auto TypeAlias = ::getEnclosingTypeAliasTemplateDecl(getSema());
|
||||
TypeAlias && ::isLambdaEnclosedByTypeAliasDecl(
|
||||
if (auto TypeAlias =
|
||||
TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl(
|
||||
getSema());
|
||||
TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl(
|
||||
LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) {
|
||||
unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth();
|
||||
if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels())
|
||||
|
|
@ -3866,9 +4100,6 @@ bool Sema::InstantiateClassTemplateSpecialization(
|
|||
ClassTemplateSpecializationDecl *ClassTemplateSpec,
|
||||
TemplateSpecializationKind TSK, bool Complain,
|
||||
bool PrimaryStrictPackMatch) {
|
||||
assert(ClassTemplateSpec->getTemplateDepth() == 0 &&
|
||||
"non-instantiated declaration");
|
||||
|
||||
// Perform the actual instantiation on the canonical declaration.
|
||||
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
|
||||
ClassTemplateSpec->getCanonicalDecl());
|
||||
|
|
@ -3892,12 +4123,9 @@ bool Sema::InstantiateClassTemplateSpecialization(
|
|||
if (!Pattern.isUsable())
|
||||
return Pattern.isInvalid();
|
||||
|
||||
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
|
||||
ClassTemplateSpec, /*Innermost=*/std::nullopt,
|
||||
/*NumLevels=*/Pattern.get()->getTemplateDepth());
|
||||
|
||||
bool Err = InstantiateClassImpl(PointOfInstantiation, ClassTemplateSpec,
|
||||
Pattern.get(), TemplateArgs, TSK, Complain);
|
||||
bool Err = InstantiateClassImpl(
|
||||
PointOfInstantiation, ClassTemplateSpec, Pattern.get(),
|
||||
getTemplateInstantiationArgs(ClassTemplateSpec), TSK, Complain);
|
||||
|
||||
// If we haven't already warn on avaibility, consider the avaibility
|
||||
// attributes of the partial specialization.
|
||||
|
|
@ -4259,7 +4487,14 @@ ExprResult Sema::SubstConceptTemplateArguments(
|
|||
[](const TemplateArgumentLoc &Loc) { return Loc.getArgument(); });
|
||||
|
||||
MultiLevelTemplateArgumentList MLTALForConstraint =
|
||||
getTemplateInstantiationArgs(CSE->getNamedConcept(), NewArgList);
|
||||
getTemplateInstantiationArgs(
|
||||
CSE->getNamedConcept(),
|
||||
CSE->getNamedConcept()->getLexicalDeclContext(),
|
||||
/*Final=*/false,
|
||||
/*Innermost=*/NewArgList,
|
||||
/*RelativeToPrimary=*/true,
|
||||
/*Pattern=*/nullptr,
|
||||
/*ForConstraintInstantiation=*/true);
|
||||
|
||||
// Rebuild a constraint, only substituting non-dependent concept names
|
||||
// and nothing else.
|
||||
|
|
|
|||
|
|
@ -49,63 +49,40 @@ static bool isDeclWithinFunction(const Decl *D) {
|
|||
return false;
|
||||
}
|
||||
|
||||
template <typename DeclT>
|
||||
template<typename DeclT>
|
||||
static bool SubstQualifier(Sema &SemaRef, const DeclT *OldDecl, DeclT *NewDecl,
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs,
|
||||
DeclContext *Owner) {
|
||||
if (auto TPLs = OldDecl->getTemplateParameterLists(); !TPLs.empty()) {
|
||||
SmallVector<TemplateParameterList *, 4> TempParamLists(TPLs.size());
|
||||
MultiLevelTemplateArgumentList MLTAL;
|
||||
const MultiLevelTemplateArgumentList &TemplateArgs) {
|
||||
if (!OldDecl->getQualifierLoc())
|
||||
return false;
|
||||
|
||||
for (auto I = 0U; I < MLTAL.getNumRetainedOuterLevels(); ++I) {
|
||||
TemplateParameterList *InstParams = SemaRef.SubstTemplateParams(
|
||||
TPLs[I], Owner, MLTAL, /*EvaluateConstraints=*/true);
|
||||
assert(InstParams);
|
||||
TempParamLists[I] = InstParams;
|
||||
MLTAL.addOuterRetainedLevel();
|
||||
}
|
||||
assert((NewDecl->getFriendObjectKind() ||
|
||||
!OldDecl->getLexicalDeclContext()->isDependentContext()) &&
|
||||
"non-friend with qualified name defined in dependent context");
|
||||
Sema::ContextRAII SavedContext(
|
||||
SemaRef,
|
||||
const_cast<DeclContext *>(NewDecl->getFriendObjectKind()
|
||||
? NewDecl->getLexicalDeclContext()
|
||||
: OldDecl->getLexicalDeclContext()));
|
||||
|
||||
auto *It = TemplateArgs.begin();
|
||||
for (unsigned I = 0; I != TPLs.size(); ++I) {
|
||||
TemplateParameterList *InstParams = SemaRef.SubstTemplateParams(
|
||||
TPLs[I], Owner, MLTAL, /*EvaluateConstraints=*/true);
|
||||
assert(InstParams);
|
||||
TempParamLists[I] = InstParams;
|
||||
if (It < TemplateArgs.end()) {
|
||||
auto [DeclAndFinal, Args] = *(It++);
|
||||
MLTAL.addOuterTemplateArguments(DeclAndFinal.getPointer(), Args,
|
||||
DeclAndFinal.getInt());
|
||||
}
|
||||
}
|
||||
NewDecl->setTemplateParameterListsInfo(SemaRef.Context, TempParamLists);
|
||||
}
|
||||
if (NestedNameSpecifierLoc QualifierLoc = OldDecl->getQualifierLoc()) {
|
||||
Sema::ContextRAII SavedContext(
|
||||
SemaRef,
|
||||
const_cast<DeclContext *>(NewDecl->getFriendObjectKind()
|
||||
? NewDecl->getLexicalDeclContext()
|
||||
: OldDecl->getLexicalDeclContext()));
|
||||
|
||||
NestedNameSpecifierLoc NewQualifierLoc =
|
||||
SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
|
||||
NestedNameSpecifierLoc NewQualifierLoc
|
||||
= SemaRef.SubstNestedNameSpecifierLoc(OldDecl->getQualifierLoc(),
|
||||
TemplateArgs);
|
||||
|
||||
if (!NewQualifierLoc)
|
||||
return true;
|
||||
if (!NewQualifierLoc)
|
||||
return true;
|
||||
|
||||
NewDecl->setQualifierInfo(NewQualifierLoc);
|
||||
}
|
||||
NewDecl->setQualifierInfo(NewQualifierLoc);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TemplateDeclInstantiator::SubstQualifier(const DeclaratorDecl *OldDecl,
|
||||
DeclaratorDecl *NewDecl) {
|
||||
return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs, Owner);
|
||||
return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs);
|
||||
}
|
||||
|
||||
bool TemplateDeclInstantiator::SubstQualifier(const TagDecl *OldDecl,
|
||||
TagDecl *NewDecl) {
|
||||
return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs, Owner);
|
||||
return ::SubstQualifier(SemaRef, OldDecl, NewDecl, TemplateArgs);
|
||||
}
|
||||
|
||||
// Include attribute instantiation code.
|
||||
|
|
@ -1759,10 +1736,10 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {
|
|||
return VisitVarDecl(D, /*InstantiatingVarTemplate=*/false);
|
||||
}
|
||||
|
||||
Decl *
|
||||
TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
|
||||
bool InstantiatingVarTemplate,
|
||||
ArrayRef<BindingDecl *> *Bindings) {
|
||||
Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D,
|
||||
bool InstantiatingVarTemplate,
|
||||
ArrayRef<BindingDecl*> *Bindings) {
|
||||
|
||||
// Do substitution on the type of the declaration
|
||||
TypeSourceInfo *TSI = SemaRef.SubstType(
|
||||
D->getTypeSourceInfo(), TemplateArgs, D->getTypeSpecStartLoc(),
|
||||
|
|
@ -2405,8 +2382,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
|||
|
||||
// Make sure the parameter lists match.
|
||||
if (!SemaRef.TemplateParameterListsAreEqual(
|
||||
RecordInst, InstParams, MostRecentPrevCT, PrevParams, true,
|
||||
Sema::TPL_TemplateMatch))
|
||||
RecordInst, InstParams, MostRecentPrevCT->getTemplatedDecl(),
|
||||
PrevParams, true, Sema::TPL_TemplateMatch))
|
||||
return nullptr;
|
||||
|
||||
// Do some additional validation, then merge default arguments
|
||||
|
|
@ -2734,23 +2711,6 @@ static QualType adjustFunctionTypeForInstantiation(ASTContext &Context,
|
|||
NewFunc->getParamTypes(), NewEPI);
|
||||
}
|
||||
|
||||
static void mergeFunctionDecl(Sema &SemaRef, FunctionDecl *NewFD, QualType NewT,
|
||||
FunctionDecl *OldFD) {
|
||||
SemaRef.mergeDeclAttributes(NewFD, OldFD);
|
||||
|
||||
if (QualType OT = OldFD->getReturnType();
|
||||
OT != NewT->castAs<FunctionType>()->getReturnType()) {
|
||||
// If this function has a deduced return type and has already been
|
||||
// defined, copy the deduced value from the old declaration.
|
||||
if (AutoType *OldAT = OT->getContainedAutoType();
|
||||
OldAT && OldAT->isDeduced()) {
|
||||
QualType DT = OldAT->getDeducedType();
|
||||
NewFD->setType(DT.isNull() ? SemaRef.SubstAutoTypeDependent(NewT)
|
||||
: SemaRef.SubstAutoType(NewT, DT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Normal class members are of more specific types and therefore
|
||||
/// don't make it here. This function serves three purposes:
|
||||
/// 1) instantiating function templates
|
||||
|
|
@ -2781,21 +2741,16 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
|||
}
|
||||
}
|
||||
|
||||
FunctionDecl *PrevDecl = nullptr;
|
||||
if (FunctionTemplate && !TemplateParams) {
|
||||
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
PrevDecl = FunctionTemplate->findSpecialization(Innermost, InsertPos);
|
||||
if (PrevDecl) {
|
||||
if (PrevDecl->getTemplateSpecializationInfo()->isExplicitSpecialization())
|
||||
return PrevDecl;
|
||||
for (FunctionDecl *F : PrevDecl->redecls())
|
||||
// If we already have a function template specialization for this
|
||||
// function template, return it.
|
||||
if (F->getPrimaryTemplate() == FunctionTemplate)
|
||||
return F;
|
||||
}
|
||||
FunctionDecl *SpecFunc
|
||||
= FunctionTemplate->findSpecialization(Innermost, InsertPos);
|
||||
|
||||
// If we already have a function template specialization, return it.
|
||||
if (SpecFunc)
|
||||
return SpecFunc;
|
||||
}
|
||||
|
||||
bool MergeWithParentScope = (TemplateParams != nullptr) ||
|
||||
|
|
@ -2888,9 +2843,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
|||
D->FriendConstraintRefersToEnclosingTemplate());
|
||||
Function->setRangeEnd(D->getSourceRange().getEnd());
|
||||
}
|
||||
Function->setPreviousDeclaration(PrevDecl);
|
||||
if (PrevDecl)
|
||||
mergeFunctionDecl(SemaRef, Function, T, PrevDecl);
|
||||
|
||||
if (D->isInlined())
|
||||
Function->setImplicitlyInline();
|
||||
|
|
@ -2947,10 +2899,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
|||
|
||||
FunctionTemplate->setLexicalDeclContext(LexicalDC);
|
||||
|
||||
if (PrevDecl)
|
||||
FunctionTemplate->setPreviousDecl(
|
||||
PrevDecl->getDescribedFunctionTemplate());
|
||||
|
||||
if (isFriend && D->isThisDeclarationADefinition()) {
|
||||
FunctionTemplate->setInstantiatedFromMemberTemplate(
|
||||
D->getDescribedFunctionTemplate());
|
||||
|
|
@ -2960,14 +2908,10 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
|||
Sema::CodeSynthesisContext::BuildingDeductionGuides) {
|
||||
// Record this function template specialization.
|
||||
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
|
||||
Function->setFunctionTemplateSpecialization(
|
||||
SemaRef.Context, FunctionTemplate,
|
||||
TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost),
|
||||
/*InsertPos=*/nullptr, /*TSK=*/TSK_ImplicitInstantiation,
|
||||
/*TemplateParams=*/nullptr,
|
||||
/*TemplateArgsAsWritten=*/nullptr,
|
||||
/*PointOfInstantiation=*/SourceLocation(),
|
||||
/*AddSpecialization=*/PrevDecl == nullptr);
|
||||
Function->setFunctionTemplateSpecialization(FunctionTemplate,
|
||||
TemplateArgumentList::CreateCopy(SemaRef.Context,
|
||||
Innermost),
|
||||
/*InsertPos=*/nullptr);
|
||||
} else if (FunctionRewriteKind == RewriteKind::None) {
|
||||
if (isFriend && D->isThisDeclarationADefinition()) {
|
||||
// Do not connect the friend to the template unless it's actually a
|
||||
|
|
@ -3025,7 +2969,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
|||
}
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(
|
||||
Function, DFTSI->TemplateParameters ? TemplateParams : nullptr,
|
||||
Function,
|
||||
DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
|
||||
Previous))
|
||||
Function->setInvalidDecl();
|
||||
|
|
@ -3043,8 +2987,9 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
|
|||
ExplicitArgs))
|
||||
return nullptr;
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Function, TemplateParams,
|
||||
&ExplicitArgs, Previous))
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Function,
|
||||
&ExplicitArgs,
|
||||
Previous))
|
||||
Function->setInvalidDecl();
|
||||
|
||||
IsExplicitSpecialization = true;
|
||||
|
|
@ -3161,8 +3106,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
CXXMethodDecl *D, TemplateParameterList *TemplateParams,
|
||||
RewriteKind FunctionRewriteKind) {
|
||||
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
||||
|
||||
FunctionDecl *PrevDecl = nullptr;
|
||||
if (FunctionTemplate && !TemplateParams) {
|
||||
// We are creating a function template specialization from a function
|
||||
// template. Check whether there is already a function template
|
||||
|
|
@ -3170,16 +3113,12 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
|
||||
|
||||
void *InsertPos = nullptr;
|
||||
PrevDecl = FunctionTemplate->findSpecialization(Innermost, InsertPos);
|
||||
if (PrevDecl) {
|
||||
if (PrevDecl->getTemplateSpecializationInfo()->isExplicitSpecialization())
|
||||
return PrevDecl;
|
||||
for (FunctionDecl *F : PrevDecl->redecls())
|
||||
// If we already have a function template specialization for this
|
||||
// function template, return it.
|
||||
if (F->getPrimaryTemplate() == FunctionTemplate)
|
||||
return F;
|
||||
}
|
||||
FunctionDecl *SpecFunc
|
||||
= FunctionTemplate->findSpecialization(Innermost, InsertPos);
|
||||
|
||||
// If we already have a function template specialization, return it.
|
||||
if (SpecFunc)
|
||||
return SpecFunc;
|
||||
}
|
||||
|
||||
bool isFriend;
|
||||
|
|
@ -3196,6 +3135,19 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope(
|
||||
SemaRef, D, TemplateArgs, Scope);
|
||||
|
||||
// Instantiate enclosing template arguments for friends.
|
||||
SmallVector<TemplateParameterList *, 4> TempParamLists;
|
||||
ArrayRef<TemplateParameterList *> TPLs = D->getTemplateParameterLists();
|
||||
if (isFriend && !TPLs.empty()) {
|
||||
TempParamLists.resize(TPLs.size());
|
||||
for (unsigned I = 0; I != TPLs.size(); ++I) {
|
||||
TemplateParameterList *InstParams = SubstTemplateParams(TPLs[I]);
|
||||
if (!InstParams)
|
||||
return nullptr;
|
||||
TempParamLists[I] = InstParams;
|
||||
}
|
||||
}
|
||||
|
||||
auto InstantiatedExplicitSpecifier = ExplicitSpecifier::getFromDecl(D);
|
||||
// deduction guides need this
|
||||
const bool CouldInstantiate =
|
||||
|
|
@ -3321,9 +3273,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
D->UsesFPIntrin(), D->isInlineSpecified(), D->getConstexprKind(),
|
||||
D->getEndLoc(), TrailingRequiresClause);
|
||||
}
|
||||
Method->setPreviousDeclaration(PrevDecl);
|
||||
if (PrevDecl)
|
||||
mergeFunctionDecl(SemaRef, Method, T, PrevDecl);
|
||||
|
||||
if (D->isInlined())
|
||||
Method->setImplicitlyInline();
|
||||
|
|
@ -3355,33 +3304,25 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
} else if (D->isOutOfLine())
|
||||
FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
|
||||
Method->setDescribedFunctionTemplate(FunctionTemplate);
|
||||
|
||||
if (PrevDecl)
|
||||
FunctionTemplate->setPreviousDecl(
|
||||
PrevDecl->getDescribedFunctionTemplate());
|
||||
} else if (FunctionTemplate) {
|
||||
// Record this function template specialization.
|
||||
ArrayRef<TemplateArgument> Innermost = TemplateArgs.getInnermost();
|
||||
Method->setFunctionTemplateSpecialization(
|
||||
SemaRef.Context, FunctionTemplate,
|
||||
TemplateArgumentList::CreateCopy(SemaRef.Context, Innermost),
|
||||
/*InsertPos=*/nullptr, /*TSK=*/TSK_ImplicitInstantiation,
|
||||
/*TemplateParams=*/nullptr,
|
||||
/*TemplateArgsAsWritten=*/nullptr,
|
||||
/*PointOfInstantiation=*/SourceLocation(),
|
||||
/*AddSpecialization=*/PrevDecl == nullptr);
|
||||
Method->setFunctionTemplateSpecialization(FunctionTemplate,
|
||||
TemplateArgumentList::CreateCopy(SemaRef.Context,
|
||||
Innermost),
|
||||
/*InsertPos=*/nullptr);
|
||||
} else if (!isFriend && FunctionRewriteKind == RewriteKind::None) {
|
||||
// Record that this is an instantiation of a member function.
|
||||
Method->setInstantiationOfMemberFunction(D, TSK_ImplicitInstantiation);
|
||||
}
|
||||
|
||||
if (SubstQualifier(D, Method))
|
||||
return nullptr;
|
||||
|
||||
// If we are instantiating a member function defined
|
||||
// out-of-line, the instantiation will have the same lexical
|
||||
// context (which will be a namespace scope) as the template.
|
||||
if (isFriend) {
|
||||
if (!TempParamLists.empty())
|
||||
Method->setTemplateParameterListsInfo(SemaRef.Context, TempParamLists);
|
||||
|
||||
Method->setLexicalDeclContext(Owner);
|
||||
Method->setObjectOfFriendDecl();
|
||||
} else if (D->isOutOfLine())
|
||||
|
|
@ -3424,8 +3365,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
}
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(
|
||||
Method, DFTSI->TemplateParameters,
|
||||
DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
|
||||
Method, DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
|
||||
Previous))
|
||||
Method->setInvalidDecl();
|
||||
|
||||
|
|
@ -3441,8 +3381,9 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
|
|||
ExplicitArgs))
|
||||
return nullptr;
|
||||
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Method, TemplateParams,
|
||||
&ExplicitArgs, Previous))
|
||||
if (SemaRef.CheckFunctionTemplateSpecialization(Method,
|
||||
&ExplicitArgs,
|
||||
Previous))
|
||||
Method->setInvalidDecl();
|
||||
|
||||
IsExplicitSpecialization = true;
|
||||
|
|
@ -4572,22 +4513,16 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
|
|||
|
||||
// Substitute into the template arguments of the class template explicit
|
||||
// specialization.
|
||||
// The template parameters list for an explicit specialization is always empty
|
||||
// and has no constraints, so there is nothing to substitute.
|
||||
TemplateArgumentListInfo InstTemplateArgs;
|
||||
const ExplicitSpecializationInfo *ExplicitSpecInfo =
|
||||
D->getExplicitSpecializationInfo();
|
||||
if (ExplicitSpecInfo) {
|
||||
auto *Args = ExplicitSpecInfo->TemplateArgsAsWritten;
|
||||
InstTemplateArgs.setLAngleLoc(Args->getLAngleLoc());
|
||||
InstTemplateArgs.setRAngleLoc(Args->getRAngleLoc());
|
||||
if (const ASTTemplateArgumentListInfo *TemplateArgsInfo =
|
||||
D->getTemplateArgsAsWritten()) {
|
||||
InstTemplateArgs.setLAngleLoc(TemplateArgsInfo->getLAngleLoc());
|
||||
InstTemplateArgs.setRAngleLoc(TemplateArgsInfo->getRAngleLoc());
|
||||
|
||||
if (SemaRef.SubstTemplateArguments(Args->arguments(), TemplateArgs,
|
||||
InstTemplateArgs))
|
||||
if (SemaRef.SubstTemplateArguments(TemplateArgsInfo->arguments(),
|
||||
TemplateArgs, InstTemplateArgs))
|
||||
return nullptr;
|
||||
}
|
||||
// Otherwise, an ExplicitInstantiation always occurs in a non-dependent
|
||||
// context, so there is nothing to substitute.
|
||||
|
||||
// Check that the template argument list is well-formed for this
|
||||
// class template.
|
||||
|
|
@ -4642,14 +4577,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
|
|||
SemaRef.Context, D->getTagKind(), Owner, D->getBeginLoc(),
|
||||
D->getLocation(), InstClassTemplate, CTAI.CanonicalConverted,
|
||||
CTAI.StrictPackMatch, PrevDecl);
|
||||
if (ExplicitSpecInfo)
|
||||
InstD->setExplicitSpecializationInfo(
|
||||
ExplicitSpecInfo->TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(SemaRef.Context, InstTemplateArgs));
|
||||
else if (const auto *Info = D->getExplicitInstantiationInfo())
|
||||
InstD->setExplicitInstantiationInfo(Info->ExternKeywordLoc,
|
||||
Info->TemplateKeywordLoc,
|
||||
Info->TemplateArgsAsWritten);
|
||||
InstD->setTemplateArgsAsWritten(InstTemplateArgs);
|
||||
|
||||
// Add this partial specialization to the set of class template partial
|
||||
// specializations.
|
||||
|
|
@ -4663,6 +4591,8 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
|
|||
InstD->setAccess(D->getAccess());
|
||||
InstD->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation);
|
||||
InstD->setSpecializationKind(D->getSpecializationKind());
|
||||
InstD->setExternKeywordLoc(D->getExternKeywordLoc());
|
||||
InstD->setTemplateKeywordLoc(D->getTemplateKeywordLoc());
|
||||
|
||||
Owner->addDecl(InstD);
|
||||
|
||||
|
|
@ -4682,6 +4612,7 @@ TemplateDeclInstantiator::VisitClassTemplateSpecializationDecl(
|
|||
Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
||||
VarTemplateSpecializationDecl *D) {
|
||||
|
||||
TemplateArgumentListInfo VarTemplateArgsInfo;
|
||||
VarTemplateDecl *VarTemplate = D->getSpecializedTemplate();
|
||||
assert(VarTemplate &&
|
||||
"A template specialization without specialized template?");
|
||||
|
|
@ -4692,15 +4623,9 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
|||
if (!InstVarTemplate)
|
||||
return nullptr;
|
||||
|
||||
assert(!D->getExplicitInstantiationInfo());
|
||||
const auto *ExplicitSpecializationInfo = D->getExplicitSpecializationInfo();
|
||||
// Substitute the current template arguments.
|
||||
TemplateArgumentListInfo VarTemplateArgsInfo;
|
||||
if (ExplicitSpecializationInfo) {
|
||||
// The template parameters for an explicit specialization are empty and
|
||||
// never need to be transformed.
|
||||
const auto *TemplateArgsInfo =
|
||||
ExplicitSpecializationInfo->TemplateArgsAsWritten;
|
||||
if (const ASTTemplateArgumentListInfo *TemplateArgsInfo =
|
||||
D->getTemplateArgsAsWritten()) {
|
||||
VarTemplateArgsInfo.setLAngleLoc(TemplateArgsInfo->getLAngleLoc());
|
||||
VarTemplateArgsInfo.setRAngleLoc(TemplateArgsInfo->getRAngleLoc());
|
||||
|
||||
|
|
@ -4731,17 +4656,12 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
|||
PrevDecl->getPointOfInstantiation(), Ignored))
|
||||
return nullptr;
|
||||
|
||||
VarTemplateSpecializationDecl *VTSD = VisitVarTemplateSpecializationDecl(
|
||||
InstVarTemplate, D, CTAI.CanonicalConverted, PrevDecl);
|
||||
if (!VTSD)
|
||||
return nullptr;
|
||||
if (ExplicitSpecializationInfo)
|
||||
VTSD->setExplicitSpecializationInfo(
|
||||
ExplicitSpecializationInfo->TemplateParams,
|
||||
ASTTemplateArgumentListInfo::Create(
|
||||
SemaRef.Context,
|
||||
ExplicitSpecializationInfo->TemplateArgsAsWritten));
|
||||
return VTSD;
|
||||
if (VarTemplateSpecializationDecl *VTSD = VisitVarTemplateSpecializationDecl(
|
||||
InstVarTemplate, D, CTAI.CanonicalConverted, PrevDecl)) {
|
||||
VTSD->setTemplateArgsAsWritten(VarTemplateArgsInfo);
|
||||
return VTSD;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VarTemplateSpecializationDecl *
|
||||
|
|
@ -4750,8 +4670,6 @@ TemplateDeclInstantiator::VisitVarTemplateSpecializationDecl(
|
|||
ArrayRef<TemplateArgument> Converted,
|
||||
VarTemplateSpecializationDecl *PrevDecl) {
|
||||
|
||||
LocalInstantiationScope Scope(SemaRef);
|
||||
|
||||
// Do substitution on the type of the declaration
|
||||
TypeSourceInfo *TSI =
|
||||
SemaRef.SubstType(D->getTypeSourceInfo(), TemplateArgs,
|
||||
|
|
@ -5007,17 +4925,16 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
|
|||
InstParams, InsertPos);
|
||||
|
||||
// Create the class template partial specialization declaration.
|
||||
// FIXME: Avoid recreating the ASTTemplateArgumentListInfo if nothing changed.
|
||||
ClassTemplatePartialSpecializationDecl *InstPartialSpec =
|
||||
ClassTemplatePartialSpecializationDecl::Create(
|
||||
SemaRef.Context, PartialSpec->getTagKind(), Owner,
|
||||
PartialSpec->getBeginLoc(), PartialSpec->getLocation(), InstParams,
|
||||
ASTTemplateArgumentListInfo::Create(SemaRef.Context,
|
||||
InstTemplateArgs),
|
||||
ClassTemplate, CTAI.CanonicalConverted,
|
||||
/*CanonInjectedTST=*/CanQualType(),
|
||||
/*PrevDecl=*/nullptr);
|
||||
|
||||
InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);
|
||||
|
||||
// Substitute the nested name specifier, if any.
|
||||
if (SubstQualifier(PartialSpec, InstPartialSpec))
|
||||
return nullptr;
|
||||
|
|
@ -5134,11 +5051,10 @@ TemplateDeclInstantiator::InstantiateVarTemplatePartialSpecialization(
|
|||
VarTemplatePartialSpecializationDecl *InstPartialSpec =
|
||||
VarTemplatePartialSpecializationDecl::Create(
|
||||
SemaRef.Context, Owner, PartialSpec->getInnerLocStart(),
|
||||
PartialSpec->getLocation(), InstParams,
|
||||
ASTTemplateArgumentListInfo::Create(SemaRef.Context,
|
||||
InstTemplateArgs),
|
||||
VarTemplate, TSI->getType(), TSI, PartialSpec->getStorageClass(),
|
||||
CTAI.CanonicalConverted);
|
||||
PartialSpec->getLocation(), InstParams, VarTemplate, TSI->getType(),
|
||||
TSI, PartialSpec->getStorageClass(), CTAI.CanonicalConverted);
|
||||
|
||||
InstPartialSpec->setTemplateArgsAsWritten(InstTemplateArgs);
|
||||
|
||||
// Substitute the nested name specifier, if any.
|
||||
if (SubstQualifier(PartialSpec, InstPartialSpec))
|
||||
|
|
@ -5373,11 +5289,8 @@ bool Sema::addInstantiatedParametersToScope(
|
|||
|
||||
bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
|
||||
ParmVarDecl *Param) {
|
||||
assert(FD->getTemplateDepth() == 0 && "function not instantiated");
|
||||
assert(Param->hasUninstantiatedDefaultArg());
|
||||
|
||||
const auto *PatternDecl =
|
||||
FD->getTemplateInstantiationPattern(/*ForDefinition=*/false);
|
||||
// FIXME: We don't track member specialization info for non-defining
|
||||
// friend declarations, so we will not be able to later find the function
|
||||
// pattern. As a workaround, don't instantiate the default argument in this
|
||||
|
|
@ -5385,50 +5298,36 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD,
|
|||
// purposes. [dcl.fct.default]p4:
|
||||
// if a friend declaration D specifies a default argument expression,
|
||||
// that declaration shall be a definition.
|
||||
if (!PatternDecl)
|
||||
if (FD->getFriendObjectKind() != Decl::FOK_None &&
|
||||
!FD->getTemplateInstantiationPattern())
|
||||
return true;
|
||||
|
||||
ParmVarDecl *OrigParam = Param;
|
||||
|
||||
unsigned NumLevels = PatternDecl->getTemplateDepth();
|
||||
MultiLevelTemplateArgumentList TemplateArgs;
|
||||
// The default argument for a templated function must always be defined on
|
||||
// it's first declaration.
|
||||
if (const auto *Info = FD->getTemplateSpecializationInfo();
|
||||
Info &&
|
||||
Info->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) {
|
||||
TemplateArgs = getTemplateInstantiationArgs(
|
||||
Info->getTemplate()->getFirstDecl(), Info->TemplateArguments->asArray(),
|
||||
NumLevels);
|
||||
} else {
|
||||
FunctionDecl *OrigFD = FD;
|
||||
if (Info) {
|
||||
FD = InstantiateFunctionDeclaration(
|
||||
cast<FunctionTemplateDecl>(Info->getTemplate()->getFirstDecl()),
|
||||
Info->TemplateArguments, CallLoc);
|
||||
// The above should always succeed for valid code, but may fail due to
|
||||
// error recovery. For example, if both a fatal error and an uncompilable
|
||||
// error occur, we stop instantiating templates at all.
|
||||
if (!FD)
|
||||
return true;
|
||||
} else {
|
||||
FD = FD->getFirstDecl();
|
||||
}
|
||||
if (FD != OrigFD)
|
||||
Param =
|
||||
cast<ParmVarDecl>(FD->getParamDecl(Param->getFunctionScopeIndex()));
|
||||
|
||||
TemplateArgs =
|
||||
getTemplateInstantiationArgs(FD, /*Innermost=*/std::nullopt, NumLevels);
|
||||
}
|
||||
|
||||
// Instantiate the expression.
|
||||
if (Param->hasUninstantiatedDefaultArg() &&
|
||||
SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
|
||||
return true;
|
||||
//
|
||||
// FIXME: Pass in a correct Pattern argument, otherwise
|
||||
// getTemplateInstantiationArgs uses the lexical context of FD, e.g.
|
||||
//
|
||||
// template<typename T>
|
||||
// struct A {
|
||||
// static int FooImpl();
|
||||
//
|
||||
// template<typename Tp>
|
||||
// // bug: default argument A<T>::FooImpl() is evaluated with 2-level
|
||||
// // template argument list [[T], [Tp]], should be [[Tp]].
|
||||
// friend A<Tp> Foo(int a);
|
||||
// };
|
||||
//
|
||||
// template<typename T>
|
||||
// A<T> Foo(int a = A<T>::FooImpl());
|
||||
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
|
||||
FD, FD->getLexicalDeclContext(),
|
||||
/*Final=*/false, /*Innermost=*/std::nullopt,
|
||||
/*RelativeToPrimary=*/true, /*Pattern=*/nullptr,
|
||||
/*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false,
|
||||
/*ForDefaultArgumentSubstitution=*/true);
|
||||
|
||||
if (Param != OrigParam)
|
||||
OrigParam->setDefaultArg(Param->getDefaultArg());
|
||||
if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true))
|
||||
return true;
|
||||
|
||||
if (ASTMutationListener *L = getASTMutationListener())
|
||||
L->DefaultArgumentInstantiated(Param);
|
||||
|
|
@ -5467,22 +5366,16 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation,
|
|||
Sema::ContextRAII savedContext(*this, Decl);
|
||||
LocalInstantiationScope Scope(*this);
|
||||
|
||||
MultiLevelTemplateArgumentList TemplateArgs =
|
||||
getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(),
|
||||
/*Final=*/false, /*Innermost=*/std::nullopt,
|
||||
/*RelativeToPrimary*/ true);
|
||||
|
||||
// FIXME: We can't use getTemplateInstantiationPattern(false) in general
|
||||
// here, because for a non-defining friend declaration in a class template,
|
||||
// we don't store enough information to map back to the friend declaration in
|
||||
// the template.
|
||||
FunctionDecl *Template = Proto->getExceptionSpecTemplate();
|
||||
unsigned NumLevels = Template->getTemplateDepth();
|
||||
MultiLevelTemplateArgumentList TemplateArgs;
|
||||
if (const auto *Info = Decl->getTemplateSpecializationInfo();
|
||||
Info &&
|
||||
Info->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
|
||||
TemplateArgs = getTemplateInstantiationArgs(
|
||||
Info->getTemplate(), Info->TemplateArguments->asArray(), NumLevels);
|
||||
else
|
||||
TemplateArgs = getTemplateInstantiationArgs(
|
||||
Decl, /*Innermost=*/std::nullopt, NumLevels);
|
||||
|
||||
if (addInstantiatedParametersToScope(Decl, Template, Scope, TemplateArgs)) {
|
||||
UpdateExceptionSpec(Decl, EST_None);
|
||||
return;
|
||||
|
|
@ -5647,10 +5540,7 @@ FunctionDecl *Sema::InstantiateFunctionDeclaration(
|
|||
MultiLevelTemplateArgumentList MArgs(FTD, Args->asArray(),
|
||||
/*Final=*/false);
|
||||
|
||||
return cast_or_null<FunctionDecl>(SubstDecl(
|
||||
FD,
|
||||
isa<CXXMethodDecl>(FD) ? FD->getParent() : FD->getLexicalDeclContext(),
|
||||
MArgs));
|
||||
return cast_or_null<FunctionDecl>(SubstDecl(FD, FD->getParent(), MArgs));
|
||||
}
|
||||
|
||||
void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
||||
|
|
@ -6005,61 +5895,36 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
|
|||
RebuildTypeSourceInfoForDefaultSpecialMembers();
|
||||
SetDeclDefaulted(Function, PatternDecl->getLocation());
|
||||
} else {
|
||||
if (const FunctionTemplateSpecializationInfo *Info =
|
||||
Function->getTemplateSpecializationInfo();
|
||||
Info && !Info->isExplicitSpecialization()) {
|
||||
const FunctionDecl *TemplatedDecl =
|
||||
Info->getTemplate()->getTemplatedDecl();
|
||||
// Find the primary template redeclaration which corresponds to the
|
||||
// definition.
|
||||
auto Redecls = TemplatedDecl->redecls();
|
||||
auto It = llvm::find_if(Redecls, [](const FunctionDecl *FD) {
|
||||
return FD->isInstantiatedFromMemberTemplate() ||
|
||||
FD->isThisDeclarationADefinition();
|
||||
});
|
||||
assert(It != Redecls.end() && "Should't get here without a definition");
|
||||
if (*It != TemplatedDecl) {
|
||||
// If the primary template found is not the same as this function's
|
||||
// primary template, then instantiate that primary template and use it
|
||||
// instead.
|
||||
FunctionDecl *NewFunction = InstantiateFunctionDeclaration(
|
||||
(*It)->getDescribedFunctionTemplate(), Info->TemplateArguments,
|
||||
PointOfInstantiation);
|
||||
// This should always succeed for well-formed code.
|
||||
if (!NewFunction)
|
||||
return;
|
||||
|
||||
assert(NewFunction != Function && "Expected a new specialization");
|
||||
assert(declaresSameEntity(NewFunction, Function));
|
||||
if (TemplateSpecializationKind TSK =
|
||||
Info->getTemplateSpecializationKind();
|
||||
TSK == TSK_ExplicitInstantiationDefinition ||
|
||||
TSK == TSK_ExplicitInstantiationDeclaration)
|
||||
NewFunction->setTemplateSpecializationKind(
|
||||
TSK, Info->getPointOfInstantiation());
|
||||
Function = NewFunction;
|
||||
}
|
||||
} else {
|
||||
for (FunctionDecl *F : Function->redecls()) {
|
||||
MemberSpecializationInfo *Info = F->getMemberSpecializationInfo();
|
||||
if (!Info)
|
||||
break;
|
||||
// Avoid friend member declarations, as they are never definitions
|
||||
// themselves and may not be declared in a template context compatible
|
||||
// with it.
|
||||
if (Info->getTemplateSpecializationKind() != TSK_FriendDeclaration) {
|
||||
Function = F;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(Function->getTemplateSpecializationKind() !=
|
||||
TSK_FriendDeclaration &&
|
||||
"Expected to find an instantiation");
|
||||
DeclContext *DC = Function->getLexicalDeclContext();
|
||||
std::optional<ArrayRef<TemplateArgument>> Innermost;
|
||||
if (auto *Primary = Function->getPrimaryTemplate();
|
||||
Primary &&
|
||||
!isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function) &&
|
||||
Function->getTemplateSpecializationKind() !=
|
||||
TSK_ExplicitSpecialization) {
|
||||
auto It = llvm::find_if(Primary->redecls(),
|
||||
[](const RedeclarableTemplateDecl *RTD) {
|
||||
return cast<FunctionTemplateDecl>(RTD)
|
||||
->isCompatibleWithDefinition();
|
||||
});
|
||||
assert(It != Primary->redecls().end() &&
|
||||
"Should't get here without a definition");
|
||||
if (FunctionDecl *Def = cast<FunctionTemplateDecl>(*It)
|
||||
->getTemplatedDecl()
|
||||
->getDefinition())
|
||||
DC = Def->getLexicalDeclContext();
|
||||
else
|
||||
DC = (*It)->getLexicalDeclContext();
|
||||
Innermost.emplace(Function->getTemplateSpecializationArgs()->asArray());
|
||||
}
|
||||
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
|
||||
Function, /*Innermost=*/std::nullopt,
|
||||
/*NumLevels=*/PatternDecl->getTemplateDepth(),
|
||||
/*SkipInnerNonInstantiated=*/true);
|
||||
Function, DC, /*Final=*/false, Innermost, false, PatternDecl);
|
||||
|
||||
// Substitute into the qualifier; we can get a substitution failure here
|
||||
// through evil use of alias templates.
|
||||
// FIXME: Is CurContext correct for this? Should we go to the (instantiation
|
||||
// of the) lexical context of the pattern?
|
||||
SubstQualifier(*this, PatternDecl, Function, TemplateArgs);
|
||||
|
||||
ActOnStartOfFunctionDef(nullptr, Function);
|
||||
|
||||
|
|
@ -6426,8 +6291,6 @@ void Sema::InstantiateVariableInitializer(
|
|||
void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
||||
VarDecl *Var, bool Recursive,
|
||||
bool DefinitionRequired, bool AtEndOfTU) {
|
||||
assert(Var->getTemplateDepth() == 0 && "variable not already instantiated");
|
||||
|
||||
if (Var->isInvalidDecl())
|
||||
return;
|
||||
|
||||
|
|
@ -6445,9 +6308,8 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
|||
// Find the pattern and the arguments to substitute into it.
|
||||
VarDecl *PatternDecl = Var->getTemplateInstantiationPattern();
|
||||
assert(PatternDecl && "no pattern for templated variable");
|
||||
MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(
|
||||
Var, /*Innermost=*/std::nullopt,
|
||||
/*NumLevels=*/PatternDecl->getTemplateDepth());
|
||||
MultiLevelTemplateArgumentList TemplateArgs =
|
||||
getTemplateInstantiationArgs(Var);
|
||||
|
||||
VarTemplateSpecializationDecl *VarSpec =
|
||||
dyn_cast<VarTemplateSpecializationDecl>(Var);
|
||||
|
|
@ -6608,6 +6470,15 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
|||
TemplateDeclInstantiator Instantiator(*this, Var->getDeclContext(),
|
||||
TemplateArgs);
|
||||
|
||||
TemplateArgumentListInfo TemplateArgInfo;
|
||||
if (const ASTTemplateArgumentListInfo *ArgInfo =
|
||||
VarSpec->getTemplateArgsAsWritten()) {
|
||||
TemplateArgInfo.setLAngleLoc(ArgInfo->getLAngleLoc());
|
||||
TemplateArgInfo.setRAngleLoc(ArgInfo->getRAngleLoc());
|
||||
for (const TemplateArgumentLoc &Arg : ArgInfo->arguments())
|
||||
TemplateArgInfo.addArgument(Arg);
|
||||
}
|
||||
|
||||
VarTemplateSpecializationDecl *VTSD =
|
||||
Instantiator.VisitVarTemplateSpecializationDecl(
|
||||
VarSpec->getSpecializedTemplate(), Def,
|
||||
|
|
@ -6615,13 +6486,7 @@ void Sema::InstantiateVariableDefinition(SourceLocation PointOfInstantiation,
|
|||
Var = VTSD;
|
||||
|
||||
if (Var) {
|
||||
if (const auto *Info = VarSpec->getExplicitInstantiationInfo())
|
||||
VTSD->setExplicitInstantiationInfo(Info->ExternKeywordLoc,
|
||||
Info->TemplateKeywordLoc,
|
||||
Info->TemplateArgsAsWritten);
|
||||
else if (const auto *Info = VarSpec->getExplicitSpecializationInfo())
|
||||
VTSD->setExplicitSpecializationInfo(Info->TemplateParams,
|
||||
Info->TemplateArgsAsWritten);
|
||||
VTSD->setTemplateArgsAsWritten(TemplateArgInfo);
|
||||
|
||||
llvm::PointerUnion<VarTemplateDecl *,
|
||||
VarTemplatePartialSpecializationDecl *> PatternPtr =
|
||||
|
|
@ -7411,7 +7276,6 @@ void Sema::PerformPendingInstantiations(bool LocalOnly, bool AtEndOfTU) {
|
|||
if (Var != Var->getMostRecentDecl())
|
||||
continue;
|
||||
break;
|
||||
case TSK_FriendDeclaration:
|
||||
case TSK_ImplicitInstantiation:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -905,10 +905,9 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {
|
|||
if (Record.readInt()) { // hasExtInfo
|
||||
auto *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo();
|
||||
Record.readQualifierInfo(*Info);
|
||||
Expr *ConstraintExpr = Record.readExpr();
|
||||
UnsignedOrNone ArgPackSubstIndex = Record.readUnsignedOrNone();
|
||||
Info->TrailingRequiresClause =
|
||||
AssociatedConstraint(ConstraintExpr, ArgPackSubstIndex);
|
||||
Info->TrailingRequiresClause = AssociatedConstraint(
|
||||
Record.readExpr(),
|
||||
UnsignedOrNone::fromInternalRepresentation(Record.readUInt32()));
|
||||
DD->DeclInfo = Info;
|
||||
}
|
||||
QualType TSIType = Record.readType();
|
||||
|
|
@ -950,9 +949,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
SmallVector<TemplateArgument, 8> TemplArgs;
|
||||
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
|
||||
|
||||
const TemplateParameterList *TemplateParams =
|
||||
Record.readBool() ? Record.readTemplateParameterList() : nullptr;
|
||||
|
||||
// Template args as written.
|
||||
TemplateArgumentListInfo TemplArgsWritten;
|
||||
bool HasTemplateArgumentsAsWritten = Record.readBool();
|
||||
|
|
@ -977,7 +973,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
|
||||
FunctionTemplateSpecializationInfo *FTInfo =
|
||||
FunctionTemplateSpecializationInfo::Create(
|
||||
C, FD, Template, TSK, TemplArgList, TemplateParams,
|
||||
C, FD, Template, TSK, TemplArgList,
|
||||
HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr, POI,
|
||||
MSInfo);
|
||||
FD->TemplateOrSpecialization = FTInfo;
|
||||
|
|
@ -1012,9 +1008,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
while (NumCandidates--)
|
||||
Candidates.addDecl(readDeclAs<NamedDecl>());
|
||||
|
||||
const TemplateParameterList *TemplateParams =
|
||||
Record.readBool() ? Record.readTemplateParameterList() : nullptr;
|
||||
|
||||
// Templates args.
|
||||
TemplateArgumentListInfo TemplArgsWritten;
|
||||
bool HasTemplateArgumentsAsWritten = Record.readBool();
|
||||
|
|
@ -1022,7 +1015,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
|
|||
Record.readTemplateArgumentListInfo(TemplArgsWritten);
|
||||
|
||||
FD->setDependentTemplateSpecialization(
|
||||
Reader.getContext(), Candidates, TemplateParams,
|
||||
Reader.getContext(), Candidates,
|
||||
HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr);
|
||||
// These are not merged; we don't need to merge redeclarations of dependent
|
||||
// template friends.
|
||||
|
|
@ -2563,20 +2556,6 @@ RedeclarableResult ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
|||
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
|
||||
D->StrictPackMatch = Record.readBool();
|
||||
|
||||
// extern/template keyword locations for explicit instantiations
|
||||
if (auto K = D->SpecializationKind;
|
||||
K == TSK_ExplicitInstantiationDeclaration ||
|
||||
K == TSK_ExplicitInstantiationDefinition) {
|
||||
SourceLocation ExternKeywordLoc = readSourceLocation();
|
||||
SourceLocation TemplateKeywordLoc = readSourceLocation();
|
||||
D->setExplicitInstantiationInfo(ExternKeywordLoc, TemplateKeywordLoc,
|
||||
Record.readASTTemplateArgumentListInfo());
|
||||
} else if (K == TSK_ExplicitSpecialization) {
|
||||
auto *TemplateParams = Record.readTemplateParameterList();
|
||||
D->setExplicitSpecializationInfo(TemplateParams,
|
||||
Record.readASTTemplateArgumentListInfo());
|
||||
}
|
||||
|
||||
bool writtenAsCanonicalDecl = Record.readInt();
|
||||
if (writtenAsCanonicalDecl) {
|
||||
auto *CanonPattern = readDeclAs<ClassTemplateDecl>();
|
||||
|
|
@ -2607,11 +2586,27 @@ RedeclarableResult ASTDeclReader::VisitClassTemplateSpecializationDeclImpl(
|
|||
}
|
||||
}
|
||||
|
||||
// extern/template keyword locations for explicit instantiations
|
||||
if (Record.readBool()) {
|
||||
auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
|
||||
ExplicitInfo->ExternKeywordLoc = readSourceLocation();
|
||||
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
|
||||
D->ExplicitInfo = ExplicitInfo;
|
||||
}
|
||||
|
||||
if (Record.readBool())
|
||||
D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
|
||||
|
||||
return Redecl;
|
||||
}
|
||||
|
||||
void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
|
||||
ClassTemplatePartialSpecializationDecl *D) {
|
||||
ClassTemplatePartialSpecializationDecl *D) {
|
||||
// We need to read the template params first because redeclarable is going to
|
||||
// need them for profiling
|
||||
TemplateParameterList *Params = Record.readTemplateParameterList();
|
||||
D->TemplateParams = Params;
|
||||
|
||||
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
|
||||
|
||||
// These are read/set from/to the first declaration.
|
||||
|
|
@ -2657,6 +2652,17 @@ RedeclarableResult ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|||
}
|
||||
}
|
||||
|
||||
// extern/template keyword locations for explicit instantiations
|
||||
if (Record.readBool()) {
|
||||
auto *ExplicitInfo = new (C) ExplicitInstantiationInfo;
|
||||
ExplicitInfo->ExternKeywordLoc = readSourceLocation();
|
||||
ExplicitInfo->TemplateKeywordLoc = readSourceLocation();
|
||||
D->ExplicitInfo = ExplicitInfo;
|
||||
}
|
||||
|
||||
if (Record.readBool())
|
||||
D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo());
|
||||
|
||||
SmallVector<TemplateArgument, 8> TemplArgs;
|
||||
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
|
||||
D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs);
|
||||
|
|
@ -2664,20 +2670,6 @@ RedeclarableResult ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|||
D->SpecializationKind = (TemplateSpecializationKind)Record.readInt();
|
||||
D->IsCompleteDefinition = Record.readInt();
|
||||
|
||||
// extern/template keyword locations for explicit instantiations
|
||||
if (auto K = D->SpecializationKind;
|
||||
K == TSK_ExplicitInstantiationDeclaration ||
|
||||
K == TSK_ExplicitInstantiationDefinition) {
|
||||
SourceLocation ExternKeywordLoc = readSourceLocation();
|
||||
SourceLocation TemplateKeywordLoc = readSourceLocation();
|
||||
D->setExplicitInstantiationInfo(ExternKeywordLoc, TemplateKeywordLoc,
|
||||
Record.readASTTemplateArgumentListInfo());
|
||||
} else if (K == TSK_ExplicitSpecialization) {
|
||||
auto *TemplateParams = Record.readTemplateParameterList();
|
||||
D->setExplicitSpecializationInfo(TemplateParams,
|
||||
Record.readASTTemplateArgumentListInfo());
|
||||
}
|
||||
|
||||
RedeclarableResult Redecl = VisitVarDeclImpl(D);
|
||||
|
||||
bool writtenAsCanonicalDecl = Record.readInt();
|
||||
|
|
@ -2708,6 +2700,9 @@ RedeclarableResult ASTDeclReader::VisitVarTemplateSpecializationDeclImpl(
|
|||
/// using Template(Partial)SpecializationDecl as input type.
|
||||
void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
|
||||
VarTemplatePartialSpecializationDecl *D) {
|
||||
TemplateParameterList *Params = Record.readTemplateParameterList();
|
||||
D->TemplateParams = Params;
|
||||
|
||||
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
|
||||
|
||||
// These are read/set from/to the first declaration.
|
||||
|
|
|
|||
|
|
@ -805,10 +805,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
// Template arguments.
|
||||
Record.AddTemplateArgumentList(FTSInfo->TemplateArguments);
|
||||
|
||||
Record.push_back(FTSInfo->TemplateParameters != nullptr);
|
||||
if (FTSInfo->TemplateParameters)
|
||||
Record.AddTemplateParameterList(FTSInfo->TemplateParameters);
|
||||
|
||||
// Template args as written.
|
||||
Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr);
|
||||
if (FTSInfo->TemplateArgumentsAsWritten)
|
||||
|
|
@ -843,10 +839,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
for (FunctionTemplateDecl *FTD : DFTSInfo->getCandidates())
|
||||
Record.AddDeclRef(FTD);
|
||||
|
||||
Record.push_back(DFTSInfo->TemplateParameters != nullptr);
|
||||
if (DFTSInfo->TemplateParameters)
|
||||
Record.AddTemplateParameterList(DFTSInfo->TemplateParameters);
|
||||
|
||||
// Templates args.
|
||||
Record.push_back(DFTSInfo->TemplateArgumentsAsWritten != nullptr);
|
||||
if (DFTSInfo->TemplateArgumentsAsWritten)
|
||||
|
|
@ -1754,7 +1746,6 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
|
|||
if (FTSInfo->TemplateArguments->size() == 1) {
|
||||
const TemplateArgument &TA = FTSInfo->TemplateArguments->get(0);
|
||||
if (TA.getKind() == TemplateArgument::Type &&
|
||||
!FTSInfo->TemplateParameters &&
|
||||
!FTSInfo->TemplateArgumentsAsWritten &&
|
||||
!FTSInfo->getMemberSpecializationInfo())
|
||||
AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind());
|
||||
|
|
@ -1763,8 +1754,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) {
|
|||
FunctionDecl::TK_DependentFunctionTemplateSpecialization) {
|
||||
DependentFunctionTemplateSpecializationInfo *DFTSInfo =
|
||||
D->getDependentSpecializationInfo();
|
||||
if (!DFTSInfo->TemplateArgumentsAsWritten &&
|
||||
!DFTSInfo->TemplateParameters)
|
||||
if (!DFTSInfo->TemplateArgumentsAsWritten)
|
||||
AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind());
|
||||
}
|
||||
}
|
||||
|
|
@ -1951,36 +1941,29 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
|
|||
Record.AddSourceLocation(D->getPointOfInstantiation());
|
||||
Record.push_back(D->getSpecializationKind());
|
||||
Record.push_back(D->hasStrictPackMatch());
|
||||
|
||||
switch (D->getSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
assert(!D->getExplicitSpecializationInfo());
|
||||
assert(!D->getExplicitInstantiationInfo());
|
||||
break;
|
||||
case TSK_ExplicitSpecialization: {
|
||||
const auto *Info = D->getExplicitSpecializationInfo();
|
||||
Record.AddTemplateParameterList(Info->TemplateParams);
|
||||
Record.AddASTTemplateArgumentListInfo(Info->TemplateArgsAsWritten);
|
||||
break;
|
||||
}
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition: {
|
||||
const auto *Info = D->getExplicitInstantiationInfo();
|
||||
Record.AddSourceLocation(Info->ExternKeywordLoc);
|
||||
Record.AddSourceLocation(Info->TemplateKeywordLoc);
|
||||
Record.AddASTTemplateArgumentListInfo(Info->TemplateArgsAsWritten);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Record.push_back(D->isCanonicalDecl());
|
||||
|
||||
if (D->isCanonicalDecl()) {
|
||||
// When reading, we'll add it to the folding set of the following template.
|
||||
Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl());
|
||||
}
|
||||
|
||||
bool ExplicitInstantiation =
|
||||
D->getTemplateSpecializationKind() ==
|
||||
TSK_ExplicitInstantiationDeclaration ||
|
||||
D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
|
||||
Record.push_back(ExplicitInstantiation);
|
||||
if (ExplicitInstantiation) {
|
||||
Record.AddSourceLocation(D->getExternKeywordLoc());
|
||||
Record.AddSourceLocation(D->getTemplateKeywordLoc());
|
||||
}
|
||||
|
||||
const ASTTemplateArgumentListInfo *ArgsWritten =
|
||||
D->getTemplateArgsAsWritten();
|
||||
Record.push_back(!!ArgsWritten);
|
||||
if (ArgsWritten)
|
||||
Record.AddASTTemplateArgumentListInfo(ArgsWritten);
|
||||
|
||||
// Mention the implicitly generated C++ deduction guide to make sure the
|
||||
// deduction guide will be rewritten as expected.
|
||||
//
|
||||
|
|
@ -2002,7 +1985,9 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl(
|
|||
}
|
||||
|
||||
void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl(
|
||||
ClassTemplatePartialSpecializationDecl *D) {
|
||||
ClassTemplatePartialSpecializationDecl *D) {
|
||||
Record.AddTemplateParameterList(D->getTemplateParameters());
|
||||
|
||||
VisitClassTemplateSpecializationDecl(D);
|
||||
|
||||
// These are read/set from/to the first declaration.
|
||||
|
|
@ -2035,34 +2020,27 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
|
|||
Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs());
|
||||
}
|
||||
|
||||
bool ExplicitInstantiation =
|
||||
D->getTemplateSpecializationKind() ==
|
||||
TSK_ExplicitInstantiationDeclaration ||
|
||||
D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition;
|
||||
Record.push_back(ExplicitInstantiation);
|
||||
if (ExplicitInstantiation) {
|
||||
Record.AddSourceLocation(D->getExternKeywordLoc());
|
||||
Record.AddSourceLocation(D->getTemplateKeywordLoc());
|
||||
}
|
||||
|
||||
const ASTTemplateArgumentListInfo *ArgsWritten =
|
||||
D->getTemplateArgsAsWritten();
|
||||
Record.push_back(!!ArgsWritten);
|
||||
if (ArgsWritten)
|
||||
Record.AddASTTemplateArgumentListInfo(ArgsWritten);
|
||||
|
||||
Record.AddTemplateArgumentList(&D->getTemplateArgs());
|
||||
Record.AddSourceLocation(D->getPointOfInstantiation());
|
||||
Record.push_back(D->getSpecializationKind());
|
||||
Record.push_back(D->IsCompleteDefinition);
|
||||
|
||||
switch (D->getSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
assert(!D->getExplicitSpecializationInfo());
|
||||
assert(!D->getExplicitInstantiationInfo());
|
||||
break;
|
||||
case TSK_ExplicitSpecialization: {
|
||||
const auto *Info = D->getExplicitSpecializationInfo();
|
||||
Record.AddTemplateParameterList(Info->TemplateParams);
|
||||
Record.AddASTTemplateArgumentListInfo(Info->TemplateArgsAsWritten);
|
||||
break;
|
||||
}
|
||||
case TSK_ExplicitInstantiationDeclaration:
|
||||
case TSK_ExplicitInstantiationDefinition: {
|
||||
const auto *Info = D->getExplicitInstantiationInfo();
|
||||
Record.AddSourceLocation(Info->ExternKeywordLoc);
|
||||
Record.AddSourceLocation(Info->TemplateKeywordLoc);
|
||||
Record.AddASTTemplateArgumentListInfo(Info->TemplateArgsAsWritten);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VisitVarDecl(D);
|
||||
|
||||
Record.push_back(D->isCanonicalDecl());
|
||||
|
|
@ -2081,6 +2059,8 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl(
|
|||
|
||||
void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
|
||||
VarTemplatePartialSpecializationDecl *D) {
|
||||
Record.AddTemplateParameterList(D->getTemplateParameters());
|
||||
|
||||
VisitVarTemplateSpecializationDecl(D);
|
||||
|
||||
// These are read/set from/to the first declaration.
|
||||
|
|
@ -2457,7 +2437,6 @@ getFunctionDeclAbbrev(serialization::DeclCode Code) {
|
|||
Abv->Add(
|
||||
BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template Argument Type
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is Defaulted
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TemplateParams
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation
|
||||
Abv->Add(BitCodeAbbrevOp(0));
|
||||
|
|
@ -2467,7 +2446,6 @@ getFunctionDeclAbbrev(serialization::DeclCode Code) {
|
|||
TK_DependentFunctionTemplateSpecialization) {
|
||||
// Candidates of specialization
|
||||
Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TemplateParams
|
||||
Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten
|
||||
} else {
|
||||
llvm_unreachable("Unknown templated kind?");
|
||||
|
|
|
|||
|
|
@ -166,6 +166,55 @@ bool BugSuppression::isSuppressed(const BugReport &R) {
|
|||
isSuppressed(UniqueingLocation, DeclWithIssue, {});
|
||||
}
|
||||
|
||||
static const ClassTemplateDecl *
|
||||
walkInstantiatedFromChain(const ClassTemplateDecl *Tmpl) {
|
||||
// For nested member templates (e.g., S2 inside S1<T>), getInstantiatedFrom
|
||||
// may return the member template as instantiated within an outer
|
||||
// specialization (e.g., S2 as it appears in S1<int>). That instantiated
|
||||
// member template has no definition redeclaration itself; we need to walk
|
||||
// up the member template chain to reach the primary template definition.
|
||||
// \code
|
||||
// template <class> struct S1 {
|
||||
// template <class> struct S2 {
|
||||
// int i;
|
||||
// template <class T> int m(const S2<T>& s2) {
|
||||
// return s2.i;
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// /code
|
||||
const ClassTemplateDecl *MemberTmpl;
|
||||
while ((MemberTmpl = Tmpl->getInstantiatedFromMemberTemplate())) {
|
||||
if (Tmpl->isMemberSpecialization())
|
||||
break;
|
||||
Tmpl = MemberTmpl;
|
||||
}
|
||||
return Tmpl;
|
||||
}
|
||||
|
||||
static const ClassTemplatePartialSpecializationDecl *walkInstantiatedFromChain(
|
||||
const ClassTemplatePartialSpecializationDecl *PartialSpec) {
|
||||
const ClassTemplatePartialSpecializationDecl *MemberPS;
|
||||
while ((MemberPS = PartialSpec->getInstantiatedFromMember())) {
|
||||
if (PartialSpec->isMemberSpecialization())
|
||||
break;
|
||||
PartialSpec = MemberPS;
|
||||
}
|
||||
return PartialSpec;
|
||||
}
|
||||
|
||||
template <class T> static const T *chooseDefinitionRedecl(const T *Tmpl) {
|
||||
static_assert(llvm::is_one_of<T, ClassTemplateDecl,
|
||||
ClassTemplatePartialSpecializationDecl>::value);
|
||||
for (const auto *Redecl : Tmpl->redecls()) {
|
||||
if (const T *D = cast<T>(Redecl); D->isThisDeclarationADefinition()) {
|
||||
return D;
|
||||
}
|
||||
}
|
||||
assert(false && "This template must have a redecl that is a definition");
|
||||
return Tmpl;
|
||||
}
|
||||
|
||||
// For template specializations, returns the primary template definition or
|
||||
// partial specialization that was used to instantiate the specialization.
|
||||
// This ensures suppression attributes on templates apply to their
|
||||
|
|
@ -180,19 +229,41 @@ bool BugSuppression::isSuppressed(const BugReport &R) {
|
|||
// attribute.
|
||||
//
|
||||
// The function handles specializations (and partial specializations) of
|
||||
// class templates.
|
||||
// For any other decl, it returns the input unchanged.
|
||||
// class and function templates.
|
||||
// For any other decl, it returns the input unchagned.
|
||||
static const Decl *
|
||||
preferTemplateDefinitionForTemplateSpecializations(const Decl *D) {
|
||||
const auto *RD = dyn_cast<CXXRecordDecl>(D);
|
||||
if (!RD)
|
||||
// For function template specializations (including instantiated friend
|
||||
// function templates), map back to the primary template's FunctionDecl so
|
||||
// that the lexical parent chain walk reaches the class where the template
|
||||
// was defined inline.
|
||||
//
|
||||
// This handles the case where a friend function template is defined inline
|
||||
// inside a [[clang::suppress]]-annotated class but was pre-declared at
|
||||
// namespace scope. In that case the instantiation's lexical DC is the
|
||||
// namespace (from the pre-declaration), not the class. Walking back to the
|
||||
// primary template FunctionDecl — whose lexical DC IS the class — lets the
|
||||
// existing parent-chain walk find the suppression attribute.
|
||||
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
if (const FunctionDecl *Pattern = FD->getTemplateInstantiationPattern())
|
||||
return Pattern->getDefinition();
|
||||
}
|
||||
|
||||
const auto *SpecializationDecl = dyn_cast<ClassTemplateSpecializationDecl>(D);
|
||||
if (!SpecializationDecl)
|
||||
return D;
|
||||
if (const CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern())
|
||||
RD = Pattern;
|
||||
RD = RD->getDefinitionOrSelf();
|
||||
if (const auto *CTD = RD->getDescribedClassTemplate())
|
||||
return CTD;
|
||||
return RD;
|
||||
|
||||
auto InstantiatedFrom = SpecializationDecl->getInstantiatedFrom();
|
||||
if (!InstantiatedFrom)
|
||||
return D;
|
||||
|
||||
if (const auto *Tmpl = InstantiatedFrom.dyn_cast<ClassTemplateDecl *>()) {
|
||||
// Interestingly, the source template might be a forward declaration, so we
|
||||
// need to find the definition redeclaration.
|
||||
return chooseDefinitionRedecl(walkInstantiatedFromChain(Tmpl));
|
||||
}
|
||||
return chooseDefinitionRedecl(walkInstantiatedFromChain(
|
||||
cast<ClassTemplatePartialSpecializationDecl *>(InstantiatedFrom)));
|
||||
}
|
||||
|
||||
bool BugSuppression::isSuppressed(const PathDiagnosticLocation &Location,
|
||||
|
|
|
|||
|
|
@ -726,14 +726,14 @@ public:
|
|||
TraverseClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *C) {
|
||||
if (!RecursiveASTVisitor::TraverseClassTemplateSpecializationDecl(C))
|
||||
return false;
|
||||
const auto *Info = C->getExplicitInstantiationInfo();
|
||||
if (!Info)
|
||||
if (C->isExplicitSpecialization())
|
||||
return true; // we are only interested in explicit instantiations.
|
||||
auto *Declaration =
|
||||
cast<syntax::SimpleDeclaration>(handleFreeStandingTagDecl(C));
|
||||
foldExplicitTemplateInstantiation(
|
||||
Builder.getTemplateRange(C), Builder.findToken(Info->ExternKeywordLoc),
|
||||
Builder.findToken(Info->TemplateKeywordLoc), Declaration, C);
|
||||
Builder.getTemplateRange(C),
|
||||
Builder.findToken(C->getExternKeywordLoc()),
|
||||
Builder.findToken(C->getTemplateKeywordLoc()), Declaration, C);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -778,9 +778,8 @@ public:
|
|||
foldTemplateDeclaration(R, TemplateKW, DeclarationRange, nullptr);
|
||||
DeclarationRange = R;
|
||||
};
|
||||
if (auto *S = dyn_cast<ClassTemplateSpecializationDecl>(C))
|
||||
if (const auto *Info = S->getExplicitSpecializationInfo())
|
||||
ConsumeTemplateParameters(*Info->TemplateParams);
|
||||
if (auto *S = dyn_cast<ClassTemplatePartialSpecializationDecl>(C))
|
||||
ConsumeTemplateParameters(*S->getTemplateParameters());
|
||||
for (TemplateParameterList *TPL : C->getTemplateParameterLists())
|
||||
ConsumeTemplateParameters(*TPL);
|
||||
return Result;
|
||||
|
|
|
|||
|
|
@ -32,12 +32,11 @@ namespace TestFunctionRedecl {
|
|||
// CHECK-LABEL: Dumping TestFunctionRedecl:
|
||||
// CHECK: |-FunctionTemplateDecl 0x[[TestFunctionRedecl_T1:[^ ]+]] <line:[[@LINE-4]]:{{.+}} f external-linkage
|
||||
// CHECK: | |-FunctionDecl 0x[[TestFunctionRedecl_D1:[^ ]+]] {{.+}} f 'void ()'
|
||||
// CHECK: | |-FunctionDecl {{.+}} prev 0x[[TestFunctionRedecl_S1:[^ ]+]] <col:22, col:32> col:27 f 'void ()' explicit_instantiation_definition instantiated_from 0x[[TestFunctionRedecl_D1]] external-linkage
|
||||
// CHECK: | `-FunctionDecl 0x[[TestFunctionRedecl_S1]] {{.+}} f 'void ()' explicit_instantiation_definition instantiated_from 0x[[TestFunctionRedecl_D2:[^ ]+]] external-linkage
|
||||
// CHECK: |-FunctionTemplateDecl 0x[[TestFunctionRedecl_T2:[^ ]+]] prev 0x[[TestFunctionRedecl_T1]] <line:[[@LINE-7]]:{{.+}} f external-linkage
|
||||
// CHECK: | `-FunctionDecl 0x[[TestFunctionRedecl_S1:[^ ]+]] {{.+}} f 'void ()' explicit_instantiation_definition instantiated_from 0x[[TestFunctionRedecl_D2:[^ ]+]] external-linkage
|
||||
// CHECK: |-FunctionTemplateDecl 0x[[TestFunctionRedecl_T2:[^ ]+]] prev 0x[[TestFunctionRedecl_T1]] <line:[[@LINE-6]]:{{.+}} f external-linkage
|
||||
// CHECK: | |-FunctionDecl 0x[[TestFunctionRedecl_D2]] prev 0x[[TestFunctionRedecl_D1]] {{.+}} f 'void ()'
|
||||
// CHECK: | `-Function 0x[[TestFunctionRedecl_S1]] 'f' 'void ()'
|
||||
// CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-9]]:{{.+}} 'f'
|
||||
// CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-8]]:{{.+}} 'f'
|
||||
// CHECK: |-Function 0x[[TestFunctionRedecl_S1]] 'f' 'void ()'
|
||||
// CHECK: |-FunctionProtoTypeLoc {{.+}} 'void ()' cdecl
|
||||
// CHECK: | `-BuiltinTypeLoc {{.+}} 'void'
|
||||
|
|
@ -77,15 +76,15 @@ namespace TestNestedClassRedecl {
|
|||
// CHECK: | | `-ClassTemplateDecl 0x[[TestNestedClassRedecl_B_T1:[^ ]+]] <line:[[@LINE-8]]:{{.+}} B external-linkage
|
||||
// CHECK: | | `-CXXRecordDecl 0x[[TestNestedClassRedecl_B_D1:[^ ]+]] {{.+}} struct B
|
||||
// CHECK: | `-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_A_S1:[^ ]+]] <line:[[@LINE-8]]:{{.+}} line:[[@LINE-11]]:{{.+}} struct A definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_A_D2:[^ ]+]] implicit_instantiation
|
||||
// CHECK: | |-ClassTemplateDecl 0x{{.+}} <line:[[@LINE-11]]:{{.+}} B external-linkage
|
||||
// CHECK: | | |-CXXRecordDecl 0x{{.+}} struct B
|
||||
// CHECK: | | `-ClassTemplateSpecialization 0x[[TestNestedClassRedecl_B_S1:[^ ]+]] 'B'
|
||||
// CHECK: | `-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_B_S1]] <line:[[@LINE-10]]:{{.+}} struct B definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_B_D1]] explicit_instantiation_definition
|
||||
// CHECK: |-ClassTemplateDecl 0x{{.+}} prev 0x[[TestNestedClassRedecl_A_T1]] <line:[[@LINE-13]]:{{.+}} A external-linkage
|
||||
// CHECK: | `-ClassTemplateDecl 0x{{.+}} <line:[[@LINE-11]]:{{.+}} B external-linkage
|
||||
// CHECK: | |-CXXRecordDecl 0x{{.+}} struct B
|
||||
// CHECK: | `-ClassTemplateSpecialization 0x[[TestNestedClassRedecl_B_S1:[^ ]+]] 'B'
|
||||
// CHECK: |-ClassTemplateDecl 0x{{.+}} prev 0x[[TestNestedClassRedecl_A_T1]] <line:[[@LINE-12]]:{{.+}} A external-linkage
|
||||
// CHECK: | |-CXXRecordDecl 0x[[TestNestedClassRedecl_A_D2]] prev 0x[[TestNestedClassRedecl_A_D1]] {{.+}} struct A
|
||||
// CHECK: | `-ClassTemplateSpecialization 0x[[TestNestedClassRedecl_A_S1]] 'A'
|
||||
// CHECK: |-ClassTemplateDecl 0x{{.+}} parent 0x[[TestNestedClassRedecl_A_D1]] prev 0x[[TestNestedClassRedecl_B_T1]] <line:[[@LINE-15]]:{{.+}} B external-linkage
|
||||
// CHECK: |-ClassTemplateDecl 0x{{.+}} parent 0x[[TestNestedClassRedecl_A_D1]] prev 0x[[TestNestedClassRedecl_B_T1]] <line:[[@LINE-14]]:{{.+}} B external-linkage
|
||||
// CHECK: | `-CXXRecordDecl 0x[[TestNestedClassRedecl_B_D2:[^ ]+]] parent 0x[[TestNestedClassRedecl_A_D1]] prev 0x[[TestNestedClassRedecl_B_D1]] {{.+}} struct B definition
|
||||
// CHECK: |-ClassTemplateSpecializationDecl 0x[[TestNestedClassRedecl_B_S1]] parent 0x[[TestNestedClassRedecl_A_S1]] <line:[[@LINE-15]]:{{.+}} struct B definition external-linkage instantiated_from 0x[[TestNestedClassRedecl_B_D1]] explicit_instantiation_definition
|
||||
// CHECK: `-ExplicitInstantiationDecl {{.+}} <line:[[@LINE-16]]:{{.+}} 'B'
|
||||
// CHECK: |-NestedNameSpecifier TypeSpec {{.+}}
|
||||
// CHECK: |-ClassTemplateSpecialization 0x[[TestNestedClassRedecl_B_S1]] 'B'
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace MemberSpecialization {
|
|||
struct A {
|
||||
template<bool B>
|
||||
void f() noexcept(B);
|
||||
// FIXME expected-note@-1 {{previous declaration is here}}
|
||||
|
||||
template<bool B>
|
||||
void g() noexcept(B); // expected-note {{previous declaration is here}}
|
||||
|
|
@ -13,6 +14,7 @@ namespace MemberSpecialization {
|
|||
template<>
|
||||
template<bool B>
|
||||
void A<int>::f() noexcept(B);
|
||||
// FIXME expected-error@-1 {{exception specification in declaration does not match previous declaration}}
|
||||
|
||||
template<>
|
||||
template<bool B>
|
||||
|
|
|
|||
|
|
@ -283,20 +283,16 @@ auto e = [] {
|
|||
namespace cwg1821 { // cwg1821: 2.9
|
||||
struct A {
|
||||
template <typename> struct B {
|
||||
void f(); // #cwg1821-B-f
|
||||
void f();
|
||||
};
|
||||
template <typename T> void B<T>::f(){};
|
||||
// expected-error@-1 {{non-friend class member 'f' cannot have a qualified name}}
|
||||
// expected-error@-2 {{class member cannot be redeclared}}
|
||||
// expected-note@#cwg1821-B-f {{previous declaration is here}}
|
||||
|
||||
struct C {
|
||||
void f(); // #cwg1821-C-f
|
||||
void f();
|
||||
};
|
||||
void C::f() {}
|
||||
// expected-error@-1 {{non-friend class member 'f' cannot have a qualified name}}
|
||||
// expected-error@-2 {{class member cannot be redeclared}}
|
||||
// expected-note@#cwg1821-C-f {{previous declaration is here}}
|
||||
};
|
||||
} // namespace cwg1821
|
||||
|
||||
|
|
|
|||
|
|
@ -138,8 +138,7 @@ namespace cwg727 { // cwg727: partial
|
|||
// expected-note@#cwg727-C {{explicitly specialized declaration is here}}
|
||||
template<> void A::f<double>();
|
||||
// expected-error@-1 {{non-friend class member 'f' cannot have a qualified name}}
|
||||
// expected-error@-2 {{function template specialization of 'f' not in class 'A' or an enclosing namespace}}
|
||||
// expected-note@#cwg727-f {{explicitly specialized declaration is here}}
|
||||
// expected-error@-2 {{no function template matches function template specialization 'f'}}
|
||||
template<> int A::N<double>;
|
||||
// expected-error@-1 {{non-friend class member 'N' cannot have a qualified name}}
|
||||
// expected-error@-2 {{variable template specialization of 'N' not in class 'A' or an enclosing namespace}}
|
||||
|
|
|
|||
|
|
@ -73,15 +73,18 @@ template <class> struct S {};
|
|||
template<template<True T> typename Wrapper>
|
||||
using Test = Wrapper<int>;
|
||||
|
||||
template<template<False T> typename Wrapper>
|
||||
using Test = Wrapper<int>;
|
||||
template<template<False T> typename Wrapper> // #TTP-Wrapper
|
||||
using Test = Wrapper<int>; // expected-error {{constraints not satisfied for template template parameter 'Wrapper' [with T = int]}}
|
||||
|
||||
// expected-note@#TTP-Wrapper {{'int' does not satisfy 'False'}}
|
||||
// expected-note@#False {{evaluated to false}}
|
||||
|
||||
template <typename U, template<False> typename T>
|
||||
void foo(T<U>); // #foo
|
||||
|
||||
void bar() {
|
||||
// FIXME: CWG2980: There is no way to check the constraints on the template template parameter.
|
||||
foo<int>(S<int>{});
|
||||
foo<int>(S<int>{}); // expected-error {{no matching function for call to 'foo'}}
|
||||
// expected-note@#foo {{substitution failure [with U = int]: constraints not satisfied for template template parameter 'T' [with $0 = int]}}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
template<typename T>
|
||||
concept D = true;
|
||||
|
||||
template<typename T>
|
||||
struct A {
|
||||
struct A { // expected-note {{defined here}}
|
||||
template<typename U, bool V>
|
||||
void f() requires V;
|
||||
|
||||
|
|
@ -17,6 +16,7 @@ struct A {
|
|||
|
||||
template<typename U, bool V> requires V
|
||||
struct B;
|
||||
// expected-note@-2 {{previous template declaration is here}}
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
struct B<U*, V>;
|
||||
|
|
@ -26,12 +26,14 @@ struct A {
|
|||
|
||||
template<D U>
|
||||
struct C;
|
||||
// expected-note@-2 {{previous template declaration is here}}
|
||||
|
||||
template<D U>
|
||||
struct C<U*>;
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
static int x;
|
||||
// expected-note@-2 {{previous template declaration is here}}
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
static int x<U*, V>;
|
||||
|
|
@ -41,6 +43,7 @@ struct A {
|
|||
|
||||
template<D U>
|
||||
static int y;
|
||||
// expected-note@-2 {{previous template declaration is here}}
|
||||
|
||||
template<D U>
|
||||
static int y<U*>;
|
||||
|
|
@ -94,9 +97,11 @@ template<typename T>
|
|||
template<D U>
|
||||
int A<T>::y<U*> = 0;
|
||||
|
||||
// FIXME: This should be accepted.
|
||||
template<>
|
||||
template<typename U, bool V>
|
||||
void A<short>::f() requires V;
|
||||
// expected-error@-1 {{out-of-line declaration of 'f' does not match any declaration in 'A<short>'}}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
|
|
@ -110,9 +115,11 @@ template<>
|
|||
template<D U>
|
||||
void A<short>::g();
|
||||
|
||||
// FIXME: This should be accepted.
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
struct A<int>::B;
|
||||
// expected-error@-2 {{requires clause differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
|
|
@ -130,9 +137,11 @@ template<>
|
|||
template<typename U, bool V> requires V
|
||||
struct A<int>::B<U&, V>;
|
||||
|
||||
// FIXME: This should be accepted.
|
||||
template<>
|
||||
template<D U>
|
||||
struct A<int>::C;
|
||||
// expected-error@-2 {{type constraint differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<D U>
|
||||
|
|
@ -142,9 +151,11 @@ template<>
|
|||
template<D U>
|
||||
struct A<int>::C<U&>;
|
||||
|
||||
// FIXME: This should be accepted.
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
int A<long>::x;
|
||||
// expected-error@-2 {{requires clause differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<>
|
||||
|
|
@ -162,9 +173,11 @@ template<>
|
|||
template<typename U, bool V> requires V
|
||||
int A<long>::x<U&, V>;
|
||||
|
||||
// FIXME: This should be accepted.
|
||||
template<>
|
||||
template<D U>
|
||||
int A<long>::y;
|
||||
// expected-error@-2 {{type constraint differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<D U>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
|
|
|
|||
|
|
@ -180,20 +180,28 @@ namespace Defined {
|
|||
namespace Constrained {
|
||||
template<typename T>
|
||||
struct A {
|
||||
// FIXME expected-note@-1 2{{defined here}}
|
||||
template<typename U, bool V> requires V
|
||||
static constexpr int f(); // expected-note {{declared here}}
|
||||
// FIXME expected-note@-1 {{declared here}}
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
static const int x; // expected-note {{declared here}}
|
||||
// FIXME expected-note@-2 2{{previous template declaration is here}}
|
||||
// FIXME expected-note@-2 {{declared here}}
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
static const int x<U*, V>; // expected-note {{declared here}}
|
||||
// FIXME expected-note@-1 {{partial specialization matches}}
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
struct B; // expected-note {{template is declared here}}
|
||||
// FIXME expected-note@-2 2{{previous template declaration is here}}
|
||||
// FIXME expected-note@-2 {{template is declared here}}
|
||||
|
||||
template<typename U, bool V> requires V
|
||||
struct B<U*, V>; // expected-note {{template is declared here}}
|
||||
// FIXME expected-note@-1 {{partial specialization matches}}
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -201,36 +209,43 @@ namespace Constrained {
|
|||
constexpr int A<short>::f() {
|
||||
return A<long>::f<U, V>();
|
||||
}
|
||||
// FIXME expected-error@-3 {{out-of-line definition of 'f' does not match any declaration in 'Constrained::A<short>'}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
constexpr int A<short>::x = A<long>::x<U, V>;
|
||||
// FIXME expected-error@-2 {{requires clause differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
constexpr int A<short>::x<U*, V> = A<long>::x<U*, V>;
|
||||
// FIXME expected-note@-1 {{partial specialization matches}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
struct A<short>::B<U*, V> {
|
||||
static constexpr int y = A<long>::B<U*, V>::y;
|
||||
};
|
||||
// FIXME expected-note@-3 {{partial specialization matches}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
struct A<short>::B {
|
||||
static constexpr int y = A<long>::B<U, V>::y;
|
||||
};
|
||||
// FIXME expected-error@-4 {{requires clause differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
constexpr int A<long>::f() {
|
||||
return 1;
|
||||
}
|
||||
// FIXME expected-error@-3 {{out-of-line definition of 'f' does not match any declaration in 'Constrained::A<long>'}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
constexpr int A<long>::x = 1;
|
||||
// FIXME expected-error@-2 {{requires clause differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
|
|
@ -241,6 +256,7 @@ namespace Constrained {
|
|||
struct A<long>::B {
|
||||
static constexpr int y = 1;
|
||||
};
|
||||
// FIXME expected-error@-4 {{requires clause differs in template redeclaration}}
|
||||
|
||||
template<>
|
||||
template<typename U, bool V> requires V
|
||||
|
|
@ -258,10 +274,17 @@ namespace Constrained {
|
|||
static_assert(A<int>::B<int*, true>::y == 0); // expected-error {{implicit instantiation of undefined template 'Constrained::A<int>::B<int *, true>'}}
|
||||
|
||||
static_assert(A<short>::f<int, true>() == 1);
|
||||
// FIXME expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
||||
// FIXME expected-note@-2 {{undefined function 'f<int, true>' cannot be used in a constant expression}}
|
||||
static_assert(A<short>::x<int, true> == 1);
|
||||
// FIXME expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
||||
// FIXME expected-note@-2 {{initializer of 'x<int, true>' is unknown}}
|
||||
static_assert(A<short>::x<int*, true> == 2);
|
||||
// FIXME expected-error@-1 {{ambiguous partial specializations of 'x'}}
|
||||
static_assert(A<short>::B<int, true>::y == 1);
|
||||
// FIXME expected-error@-1 {{implicit instantiation of undefined template 'Constrained::A<short>::B<int, true>'}}
|
||||
static_assert(A<short>::B<int*, true>::y == 2);
|
||||
// FIXME expected-error@-1 {{ambiguous partial specializations of 'B<int *, true>'}}
|
||||
} // namespace Constrained
|
||||
|
||||
namespace Dependent {
|
||||
|
|
|
|||
|
|
@ -85,15 +85,3 @@ void f4() {
|
|||
// CHECK: call void @_Z2g4ii(i32 noundef 5, i32 noundef 7)
|
||||
g4();
|
||||
}
|
||||
|
||||
namespace LambdaTemplateRedecl1 {
|
||||
struct A {
|
||||
template <class T> A(T) {}
|
||||
};
|
||||
template <class> void f(A = []{});
|
||||
void t1() { f<int>(); }
|
||||
template <class> void f(A);
|
||||
void t2() { f<int>(); }
|
||||
// CHECK-LABEL: define internal void @"_ZN21LambdaTemplateRedecl11AC1IZNS_1fIiEEvS0_E3$_0EET_"
|
||||
// CHECK-LABEL: define internal void @"_ZN21LambdaTemplateRedecl11AC2IZNS_1fIiEEvS0_E3$_0EET_"
|
||||
} // namespace LambdaTemplateRedecl1
|
||||
|
|
|
|||
|
|
@ -171,13 +171,6 @@ void use() {
|
|||
}
|
||||
}
|
||||
|
||||
namespace Redecl1 {
|
||||
template <class> void f();
|
||||
template void f<int>();
|
||||
template <class> void f() {}
|
||||
// CHECK-LABEL: define weak_odr void @_ZN7Redecl11fIiEEvv
|
||||
} // namespace Redecl1
|
||||
|
||||
namespace DefaultedMembers {
|
||||
struct B { B(); B(const B&); ~B(); };
|
||||
template<typename T> struct A : B {
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: mkdir -p %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: cd %t
|
||||
//
|
||||
// RUN: %clang_cc1 -std=c++20 -emit-module-interface B.cppm -o B.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -fmodule-file=B=B.pcm -fsyntax-only C.cpp
|
||||
|
||||
//--- A.h
|
||||
struct deduced {
|
||||
template<typename = void> auto operator()() const {}
|
||||
};
|
||||
|
||||
//--- B.cppm
|
||||
module;
|
||||
|
||||
#include "A.h"
|
||||
|
||||
export module B;
|
||||
|
||||
export template<class> void b() {
|
||||
deduced()();
|
||||
}
|
||||
|
||||
//--- C.cpp
|
||||
#include "A.h"
|
||||
import B;
|
||||
template void b<void>();
|
||||
|
|
@ -6,6 +6,5 @@ constexpr void gh195416() {
|
|||
static constexpr S S::bar;
|
||||
// expected-error@-1 {{non-friend class member 'bar' cannot have a qualified name}}
|
||||
// expected-error@-2 {{static data member 'bar' not allowed in local struct 'S'}}
|
||||
// expected-error@-3 {{no member named 'bar' in 'gh195416()::U::S'}}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1466,10 +1466,3 @@ constexpr bool missingCase() {
|
|||
1u: return false; // expected-error {{expected 'case' keyword before expression}}
|
||||
}
|
||||
}
|
||||
|
||||
namespace GH202106 {
|
||||
template <typename T> constexpr int foo(T);
|
||||
template int foo<int>(int);
|
||||
template <typename T> constexpr int foo(T) {}
|
||||
// cxx14_20-error@-1 {{no return statement in constexpr function}}
|
||||
} // namespace GH202106
|
||||
|
|
|
|||
|
|
@ -792,29 +792,3 @@ auto f() {
|
|||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
namespace TemplateRedecl1 {
|
||||
template <class> auto f();
|
||||
template <class T> void g() { (void)+f<T>(); };
|
||||
template <class> auto f() { return 0; }
|
||||
template auto f<int>();
|
||||
template void g<int>();
|
||||
} // namespace TemplateRedecl1
|
||||
|
||||
namespace TemplateRedecl2 {
|
||||
struct A {
|
||||
template <class> auto f() const;
|
||||
};
|
||||
template <class T> void g() { (void)+A().f<T>(); };
|
||||
template <class> auto A::f() const { return 0; }
|
||||
template auto A::f<int>() const;
|
||||
template void g<int>();
|
||||
} // namespace TemplateRedecl2
|
||||
|
||||
namespace TemplateRedecl3 {
|
||||
template <class> auto f() __attribute__((cdecl));
|
||||
template <class T> void g() { (void)+f<T>(); };
|
||||
template <class> auto f() { return 0; }
|
||||
template auto f<int>();
|
||||
template void g<int>();
|
||||
} // namespace TemplateRedecl3
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
|
||||
|
||||
struct rdar9677163 {
|
||||
struct Y { ~Y(); }; // expected-note {{previous declaration is here}}
|
||||
struct Y { ~Y(); };
|
||||
struct Z { ~Z(); };
|
||||
Y::~Y() { } // expected-error{{non-friend class member '~Y' cannot have a qualified name}}
|
||||
// expected-error@-1 {{destructor cannot be redeclared}}
|
||||
~Z(); // expected-error{{expected the class name after '~' to name the enclosing class}}
|
||||
};
|
||||
|
||||
|
|
@ -80,20 +79,3 @@ struct Z2 {
|
|||
};
|
||||
|
||||
}
|
||||
|
||||
namespace GH202109 {
|
||||
struct C {
|
||||
template <class> struct S {
|
||||
template <class> struct I;
|
||||
};
|
||||
|
||||
template <class X> template <class Y> struct S<X>::I {
|
||||
void f(X, Y); // expected-note {{previous declaration is here}}
|
||||
};
|
||||
// expected-error@-3 {{non-friend class member 'I' cannot have a qualified name}}
|
||||
|
||||
template <class X> template <class Y> void S<X>::I<Y>::f(X, Y) {}
|
||||
// expected-error@-1 {{non-friend class member 'f' cannot have a qualified name}}
|
||||
// expected-error@-2 {{class member cannot be redeclared}}
|
||||
};
|
||||
} // namespace GH202109
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
// RUN: %clang_cc1 -verify %s
|
||||
|
||||
template <class> void foo(int = 0;
|
||||
// expected-error@-1 {{expected ')'}}
|
||||
// expected-note@-2 {{to match this '('}}
|
||||
|
||||
void bar();
|
||||
|
||||
#include "dadfoksbdsdldfafszcf.h"
|
||||
// expected-error@-1 {{file not found}}
|
||||
|
||||
void baz() { foo<int>(); }
|
||||
|
|
@ -840,7 +840,7 @@ namespace PackIndexExpr1 {
|
|||
template <int... T>
|
||||
concept C = true;
|
||||
|
||||
template <typename...> struct TplClass {
|
||||
template <typename...> struct TplClass { // #PackIndexExpr1-TplClassDef
|
||||
template <int... Ts>
|
||||
requires C<Ts...[0]>
|
||||
static auto buggy() -> void;
|
||||
|
|
@ -850,6 +850,9 @@ template <>
|
|||
template <int... Ts>
|
||||
requires C<Ts...[0]>
|
||||
auto TplClass<int>::buggy() -> void {}
|
||||
// FIXME: These shouldn't diagnose, but are a result of a revert: #193558
|
||||
// expected-error@-2{{does not match any declaration in}}
|
||||
// expected-note@#PackIndexExpr1-TplClassDef{{TplClass defined here}}
|
||||
} // namespace PackIndexExpr1
|
||||
|
||||
namespace PackIndexExpr2 {
|
||||
|
|
@ -900,16 +903,18 @@ namespace FuncTemplateInClass {
|
|||
template <int T> concept C = true;
|
||||
|
||||
namespace t1 {
|
||||
template <int> struct TplClass {
|
||||
template <int> struct TplClass { // expected-note {{defined here}}
|
||||
template <int Ts>
|
||||
requires C<Ts>
|
||||
static auto buggy() -> void;
|
||||
};
|
||||
|
||||
// FIXME: This should be accepted.
|
||||
template <>
|
||||
template <int Ts>
|
||||
requires C<Ts>
|
||||
auto TplClass<0>::buggy() -> void {}
|
||||
// expected-error@-1 {{out-of-line definition of 'buggy' does not match any declaration}}
|
||||
} //namespace t1
|
||||
namespace t2 {
|
||||
template <int> struct TplClass { // expected-note {{defined here}}
|
||||
|
|
|
|||
|
|
@ -338,11 +338,3 @@ class Foo {
|
|||
bool aux;
|
||||
};
|
||||
}
|
||||
|
||||
namespace GH101330 {
|
||||
template <class T> struct A {
|
||||
template <int N> friend void f() noexcept(N == 0);
|
||||
};
|
||||
template <int N> void f() noexcept(N == 0) {}
|
||||
template struct A<int>;
|
||||
} // namespace GH101330
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ template<typename ...T> struct X {
|
|||
|
||||
template<typename T, typename U> using A = T;
|
||||
|
||||
// FIXME: These definitions are not OK, X<A<T, decltype(...)>...> is not equivalent to X<T...>.
|
||||
// These definitions are OK, X<A<T, decltype(...)>...> is equivalent to X<T...>
|
||||
// so this defines the member of the primary template.
|
||||
template<typename ...T>
|
||||
void X<A<T, decltype(f(T()))>...>::f(int) {}
|
||||
void X<A<T, decltype(f(T()))>...>::f(int) {} // expected-error {{undeclared}}
|
||||
|
||||
template<typename ...T>
|
||||
int X<A<T, decltype(f(T()))>...>::n = 0; // expected-error {{undeclared}}
|
||||
|
|
@ -22,7 +23,8 @@ void g() {
|
|||
X<Y>().f(0);
|
||||
X<Y>::n = 1;
|
||||
|
||||
// FIXME: There should be no substitutiton failure since the out-of-line definitions were not valid.
|
||||
X<void>().f(0);
|
||||
// Error, substitution fails; this should not be treated as a SFINAE-able
|
||||
// condition, so we don't select X<void>::f(...).
|
||||
X<void>().f(0); // expected-note {{instantiation of}}
|
||||
X<void>::n = 1; // expected-note {{instantiation of}}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,77 +10,64 @@ int main()
|
|||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+foo$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
//
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+foo$}}
|
||||
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+foo$}}
|
||||
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
//
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'foo<int>'$}}
|
||||
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'foo<int>'$}}
|
||||
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
//
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+foo$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+foo$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
//
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+b$}}
|
||||
// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:12'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+b$}}
|
||||
// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:12'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
//
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'foo<int>'$}}
|
||||
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'foo<int>'$}}
|
||||
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-default-func-arg.cpp:3:6'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:85:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-default-func-arg.cpp:72:3'$}}
|
||||
foo<int>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -207,18 +207,6 @@ template <bool = true> void d(int = 0) { d(); }
|
|||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:171:42'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:171:42'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:171:42'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'unnamed function parameter 0 of d<true>'$}}
|
||||
// CHECK: {{^kind:[ ]+DefaultFunctionArgumentInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
|
|
@ -237,41 +225,41 @@ void e() {
|
|||
}
|
||||
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:235:3\)'$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
|
||||
// CHECK: {{^kind:[ ]+Memoization$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:236:5'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:235:3\)'$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
|
||||
// CHECK: {{^kind:[ ]+Memoization$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:236:5'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:235:3\)'$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
|
||||
// CHECK: {{^kind:[ ]+Memoization$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:236:5'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:235:3\)'$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
|
||||
// CHECK: {{^kind:[ ]+Memoization$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:236:5'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:235:3\)'$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
|
||||
// CHECK: {{^kind:[ ]+Memoization$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:235:3\)'$}}
|
||||
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
|
||||
// CHECK: {{^kind:[ ]+Memoization$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:235:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
|
||||
|
||||
|
||||
template <template<typename> class>
|
||||
|
|
@ -287,71 +275,71 @@ void foo() {
|
|||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:278:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
|
||||
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:277:35'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
|
||||
// CHECK: {{^poi:[ ]+''$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
|
||||
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:277:35'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
|
||||
// CHECK: {{^poi:[ ]+''$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
|
||||
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:277:35'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:5'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:5'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
|
||||
// CHECK: {{^kind:[ ]+PartialOrderingTTP$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:277:35'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:5'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:5'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:278:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:278:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:278:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'d<C>'$}}
|
||||
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:278:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+'d<C>'$}}
|
||||
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:278:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+Begin$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
// CHECK-LABEL: {{^---$}}
|
||||
// CHECK: {{^name:[ ]+d$}}
|
||||
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
|
||||
// CHECK: {{^event:[ ]+End$}}
|
||||
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:283:3'$}}
|
||||
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
|
||||
|
|
|
|||
|
|
@ -732,7 +732,6 @@ bool CursorVisitor::VisitClassTemplateSpecializationDecl(
|
|||
switch (D->getSpecializationKind()) {
|
||||
case TSK_Undeclared:
|
||||
case TSK_ImplicitInstantiation:
|
||||
case TSK_FriendDeclaration:
|
||||
// Nothing to visit
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -5299,13 +5299,11 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportTemplateParameterLists) {
|
|||
Decl *FromTU = getTuDecl(Code, Lang_CXX03);
|
||||
auto *FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU,
|
||||
functionDecl(hasName("f"), isExplicitTemplateSpecialization()));
|
||||
ASSERT_EQ(FromD->getTemplateSpecializationInfo()->TemplateParameters->size(),
|
||||
0u);
|
||||
ASSERT_EQ(FromD->getTemplateParameterLists().size(), 1u);
|
||||
|
||||
auto *ToD = Import(FromD, Lang_CXX03);
|
||||
// The template parameter list should exist.
|
||||
ASSERT_EQ(ToD->getTemplateSpecializationInfo()->TemplateParameters->size(),
|
||||
0u);
|
||||
EXPECT_EQ(ToD->getTemplateParameterLists().size(), 1u);
|
||||
}
|
||||
|
||||
const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl>
|
||||
|
|
|
|||
|
|
@ -6071,14 +6071,14 @@ public:
|
|||
FunDecl);
|
||||
|
||||
ExpectCorrectResult("ForCallable first",
|
||||
callExpr(forCallable(declaresSameEntityAsNode(FunDecl)),
|
||||
callExpr(forCallable(equalsNode(FunDecl)),
|
||||
callee(cxxMethodDecl().bind("callee")))
|
||||
.bind("call"),
|
||||
FunDecl);
|
||||
|
||||
ExpectCorrectResult("ForCallable second",
|
||||
callExpr(callee(cxxMethodDecl().bind("callee")),
|
||||
forCallable(declaresSameEntityAsNode(FunDecl)))
|
||||
forCallable(equalsNode(FunDecl)))
|
||||
.bind("call"),
|
||||
FunDecl);
|
||||
|
||||
|
|
|
|||
|
|
@ -1154,7 +1154,9 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"libc++ std::chrono::sys_seconds summary provider",
|
||||
"^std::__[[:alnum:]]+::chrono::time_point<"
|
||||
"std::__[[:alnum:]]+::chrono::system_clock, "
|
||||
"std::__[[:alnum:]]+::chrono::duration<[^,]*> >$",
|
||||
"std::__[[:alnum:]]+::chrono::duration<.*, "
|
||||
"std::__[[:alnum:]]+::ratio<1, 1> "
|
||||
"> >$",
|
||||
eTypeOptionHideChildren | eTypeOptionHideValue |
|
||||
eTypeOptionCascade,
|
||||
true);
|
||||
|
|
@ -1164,7 +1166,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"^std::__[[:alnum:]]+::chrono::time_point<"
|
||||
"std::__[[:alnum:]]+::chrono::system_clock, "
|
||||
"std::__[[:alnum:]]+::chrono::duration<int, "
|
||||
"std::__[[:alnum:]]+::ratio<86400> "
|
||||
"std::__[[:alnum:]]+::ratio<86400, 1> "
|
||||
"> >$",
|
||||
eTypeOptionHideChildren | eTypeOptionHideValue |
|
||||
eTypeOptionCascade,
|
||||
|
|
@ -1176,7 +1178,9 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"libc++ std::chrono::local_seconds summary provider",
|
||||
"^std::__[[:alnum:]]+::chrono::time_point<"
|
||||
"std::__[[:alnum:]]+::chrono::local_t, "
|
||||
"std::__[[:alnum:]]+::chrono::duration<[^,]*> >$",
|
||||
"std::__[[:alnum:]]+::chrono::duration<.*, "
|
||||
"std::__[[:alnum:]]+::ratio<1, 1> "
|
||||
"> >$",
|
||||
eTypeOptionHideChildren | eTypeOptionHideValue | eTypeOptionCascade,
|
||||
true);
|
||||
AddCXXSummary(cpp_category_sp,
|
||||
|
|
@ -1185,7 +1189,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
|
|||
"^std::__[[:alnum:]]+::chrono::time_point<"
|
||||
"std::__[[:alnum:]]+::chrono::local_t, "
|
||||
"std::__[[:alnum:]]+::chrono::duration<int, "
|
||||
"std::__[[:alnum:]]+::ratio<86400> "
|
||||
"std::__[[:alnum:]]+::ratio<86400, 1> "
|
||||
"> >$",
|
||||
eTypeOptionHideChildren | eTypeOptionHideValue |
|
||||
eTypeOptionCascade,
|
||||
|
|
|
|||
|
|
@ -1449,11 +1449,8 @@ void TypeSystemClang::CreateFunctionTemplateSpecializationInfo(
|
|||
TemplateArgumentList *template_args_ptr = TemplateArgumentList::CreateCopy(
|
||||
func_decl->getASTContext(), infos.GetArgs());
|
||||
|
||||
func_decl->setFunctionTemplateSpecialization(
|
||||
func_decl->getASTContext(), func_tmpl_decl, template_args_ptr,
|
||||
/*InsertPos=*/nullptr, TSK_ImplicitInstantiation,
|
||||
/*TemplateParams=*/nullptr, /*TemplateArgsAsWritten=*/nullptr,
|
||||
/*PointOfInstantiation=*/SourceLocation(), /*AddSpecialization=*/true);
|
||||
func_decl->setFunctionTemplateSpecialization(func_tmpl_decl,
|
||||
template_args_ptr, nullptr);
|
||||
}
|
||||
|
||||
/// Returns true if the given template parameter can represent the given value.
|
||||
|
|
@ -1652,40 +1649,6 @@ TypeSystemClang::CreateTemplateTemplateParmDecl(const char *template_name) {
|
|||
template_param_list);
|
||||
}
|
||||
|
||||
static const ASTTemplateArgumentListInfo *getTrivialTemplateArgumentListInfo(
|
||||
ASTContext &ast, ArrayRef<TemplateArgument> args, SourceLocation Loc) {
|
||||
TemplateArgumentListInfo Args(/*LAngleLoc=*/Loc, /*RAngleLoc=*/Loc);
|
||||
for (const auto &arg : args) {
|
||||
if (arg.getIsDefaulted())
|
||||
break;
|
||||
switch (arg.getKind()) {
|
||||
case TemplateArgument::Type:
|
||||
Args.addArgument(TemplateArgumentLoc(
|
||||
arg.getAsType(), ast.getTrivialTypeSourceInfo(arg.getAsType(), Loc)));
|
||||
break;
|
||||
case TemplateArgument::Expression:
|
||||
Args.addArgument(TemplateArgumentLoc(arg, arg.getAsExpr()));
|
||||
break;
|
||||
case TemplateArgument::Template:
|
||||
case TemplateArgument::TemplateExpansion:
|
||||
Args.addArgument(
|
||||
TemplateArgumentLoc(ast, arg, Loc, NestedNameSpecifierLoc(), Loc));
|
||||
break;
|
||||
case TemplateArgument::Declaration:
|
||||
case TemplateArgument::Integral:
|
||||
case TemplateArgument::NullPtr:
|
||||
case TemplateArgument::Pack:
|
||||
case TemplateArgument::StructuralValue:
|
||||
Args.addArgument(
|
||||
TemplateArgumentLoc(arg, TemplateArgumentLocInfo(ast, Loc)));
|
||||
break;
|
||||
case TemplateArgument::Null:
|
||||
llvm_unreachable("unexpected null template argument");
|
||||
}
|
||||
}
|
||||
return ASTTemplateArgumentListInfo::Create(ast, Args);
|
||||
}
|
||||
|
||||
ClassTemplateSpecializationDecl *
|
||||
TypeSystemClang::CreateClassTemplateSpecializationDecl(
|
||||
DeclContext *decl_ctx, OptionalClangModuleID owning_module,
|
||||
|
|
@ -1728,13 +1691,6 @@ TypeSystemClang::CreateClassTemplateSpecializationDecl(
|
|||
|
||||
class_template_specialization_decl->setSpecializationKind(
|
||||
TSK_ExplicitSpecialization);
|
||||
SourceLocation FakeLoc = class_template_specialization_decl->getLocation();
|
||||
auto *TemplateParams = TemplateParameterList::Create(
|
||||
ast, /*TemplateLoc=*/FakeLoc, /*LAngleLoc=*/FakeLoc,
|
||||
/*Params=*/ArrayRef<NamedDecl *>(), /*RAngleLoc=*/FakeLoc,
|
||||
/*RequiresClause=*/nullptr);
|
||||
class_template_specialization_decl->setExplicitSpecializationInfo(
|
||||
TemplateParams, ::getTrivialTemplateArgumentListInfo(ast, args, FakeLoc));
|
||||
|
||||
return class_template_specialization_decl;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue