[clang-tools-extra] [clang] remove ClassScopeFunctionSpecializationDecl (PR #66636)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 19 02:21:22 PDT 2023
https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/66636
>From d11d546f3190936ba45c57b4825073026d817878 Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 25 Aug 2023 14:07:32 -0400
Subject: [PATCH 1/2] [clang] remove ClassScopeFunctionSpecializationDecl
---
.../clang-tidy/modernize/UseEmplaceCheck.cpp | 2 +-
.../clangd/SemanticHighlighting.cpp | 9 --
clang/include/clang/AST/ASTNodeTraverser.h | 7 +-
clang/include/clang/AST/Decl.h | 10 +-
clang/include/clang/AST/DeclTemplate.h | 150 +++---------------
clang/include/clang/AST/RecursiveASTVisitor.h | 19 ++-
clang/include/clang/Basic/DeclNodes.td | 1 -
.../clang/Basic/DiagnosticSemaKinds.td | 8 +-
clang/include/clang/Sema/Sema.h | 6 +-
clang/include/clang/Sema/Template.h | 2 -
.../include/clang/Serialization/ASTBitCodes.h | 4 -
.../clang/Serialization/ASTRecordReader.h | 2 +
clang/lib/AST/ASTImporter.cpp | 26 ++-
clang/lib/AST/Decl.cpp | 71 ++++++---
clang/lib/AST/DeclBase.cpp | 2 -
clang/lib/AST/DeclTemplate.cpp | 13 --
clang/lib/AST/ODRHash.cpp | 4 +
clang/lib/CodeGen/CGDecl.cpp | 1 -
clang/lib/Index/IndexSymbol.cpp | 1 -
clang/lib/Sema/SemaDecl.cpp | 112 ++++++-------
clang/lib/Sema/SemaTemplate.cpp | 14 +-
.../lib/Sema/SemaTemplateInstantiateDecl.cpp | 121 +++++++-------
clang/lib/Serialization/ASTCommon.cpp | 1 -
clang/lib/Serialization/ASTReader.cpp | 19 ++-
clang/lib/Serialization/ASTReaderDecl.cpp | 59 ++-----
clang/lib/Serialization/ASTWriter.cpp | 1 -
clang/lib/Serialization/ASTWriterDecl.cpp | 42 ++---
.../Checkers/SmartPtrModeling.cpp | 2 +-
clang/test/AST/ast-dump-decl.cpp | 9 +-
clang/test/CXX/drs/dr7xx.cpp | 5 +
.../test/SemaTemplate/instantiate-method.cpp | 7 +-
clang/tools/libclang/CIndex.cpp | 1 -
32 files changed, 290 insertions(+), 441 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
index 554abcd900e329c..06ae1f4e257528f 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -67,7 +67,7 @@ AST_MATCHER_P(CallExpr, hasLastArgument,
// function had parameters defined (this is useful to check if there is only one
// variadic argument).
AST_MATCHER(CXXMemberCallExpr, hasSameNumArgsAsDeclNumParams) {
- if (Node.getMethodDecl()->isFunctionTemplateSpecialization())
+ if (Node.getMethodDecl()->getPrimaryTemplate())
return Node.getNumArgs() == Node.getMethodDecl()
->getPrimaryTemplate()
->getTemplatedDecl()
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 45c01634e2e38d1..7649e37e1f96663 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -715,13 +715,6 @@ class CollectExtraHighlightings
return true;
}
- bool VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D) {
- if (auto *Args = D->getTemplateArgsAsWritten())
- H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
- return true;
- }
-
bool VisitDeclRefExpr(DeclRefExpr *E) {
H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
return true;
@@ -752,8 +745,6 @@ class CollectExtraHighlightings
}
if (auto *Args = D->getTemplateSpecializationArgsAsWritten())
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
- if (auto *I = D->getDependentSpecializationInfo())
- H.addAngleBracketTokens(I->getLAngleLoc(), I->getRAngleLoc());
return true;
}
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index 1151a756ff377b6..c3d233d3ab4a259 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -428,6 +428,8 @@ class ASTNodeTraverser
void VisitFunctionDecl(const FunctionDecl *D) {
if (const auto *FTSI = D->getTemplateSpecializationInfo())
dumpTemplateArgumentList(*FTSI->TemplateArguments);
+ else if (const auto *DFTSI = D->getDependentSpecializationInfo())
+ dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten);
if (D->param_begin())
for (const auto *Parameter : D->parameters())
@@ -578,11 +580,6 @@ class ASTNodeTraverser
dumpTemplateParameters(D->getTemplateParameters());
}
- void VisitClassScopeFunctionSpecializationDecl(
- const ClassScopeFunctionSpecializationDecl *D) {
- Visit(D->getSpecialization());
- dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
- }
void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); }
void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index c51b33c9e594a81..3d0f144d2337c6b 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -2813,9 +2813,7 @@ class FunctionDecl : public DeclaratorDecl,
/// Determine whether this function is a function template
/// specialization.
- bool isFunctionTemplateSpecialization() const {
- return getPrimaryTemplate() != nullptr;
- }
+ bool isFunctionTemplateSpecialization() const;
/// If this function is actually a function template specialization,
/// retrieve information about this function template specialization.
@@ -2898,9 +2896,9 @@ class FunctionDecl : public DeclaratorDecl,
/// Specifies that this function declaration is actually a
/// dependent function template specialization.
- void setDependentTemplateSpecialization(ASTContext &Context,
- const UnresolvedSetImpl &Templates,
- const TemplateArgumentListInfo &TemplateArgs);
+ void setDependentTemplateSpecialization(
+ ASTContext &Context, const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo *TemplateArgs);
DependentFunctionTemplateSpecializationInfo *
getDependentSpecializationInfo() const;
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 6264f15d6ffb961..54d28227a4ae91b 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -583,7 +583,7 @@ class FunctionTemplateSpecializationInfo final
/// \code
/// template<typename> struct A {
/// template<typename> void f();
- /// template<> void f<int>(); // ClassScopeFunctionSpecializationDecl
+ /// template<> void f<int>();
/// };
/// \endcode
///
@@ -682,82 +682,48 @@ class MemberSpecializationInfo {
/// Provides information about a dependent function-template
/// specialization declaration.
///
-/// Since explicit function template specialization and instantiation
-/// declarations can only appear in namespace scope, and you can only
-/// specialize a member of a fully-specialized class, the only way to
-/// get one of these is in a friend declaration like the following:
+/// This is used for function templates explicit specializations declared
+/// within class templates:
+///
+/// \code
+/// template<typename> struct A {
+/// template<typename> void f();
+/// template<> void f<int>(); // DependentFunctionTemplateSpecializationInfo
+/// };
+/// \endcode
+///
+/// As well as dependent friend declarations naming function template
+/// specializations declared within class templates:
///
/// \code
/// template \<class T> void foo(T);
/// template \<class T> class A {
-/// friend void foo<>(T);
+/// friend void foo<>(T); // DependentFunctionTemplateSpecializationInfo
/// };
/// \endcode
class DependentFunctionTemplateSpecializationInfo final
: private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
- TemplateArgumentLoc,
FunctionTemplateDecl *> {
- /// The number of potential template candidates.
- unsigned NumTemplates;
-
- /// The number of template arguments.
- unsigned NumArgs;
-
- /// The locations of the left and right angle brackets.
- SourceRange AngleLocs;
+ friend TrailingObjects;
- size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
- return NumArgs;
- }
- size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
- return NumTemplates;
- }
+ /// The number of candidates for the primary template.
+ unsigned NumCandidates;
DependentFunctionTemplateSpecializationInfo(
- const UnresolvedSetImpl &Templates,
- const TemplateArgumentListInfo &TemplateArgs);
+ const UnresolvedSetImpl &Candidates,
+ const ASTTemplateArgumentListInfo *TemplateArgsWritten);
public:
- friend TrailingObjects;
+ /// The template arguments as written in the sources, if provided.
+ const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
static DependentFunctionTemplateSpecializationInfo *
- Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
- const TemplateArgumentListInfo &TemplateArgs);
-
- /// Returns the number of function templates that this might
- /// be a specialization of.
- unsigned getNumTemplates() const { return NumTemplates; }
+ Create(ASTContext &Context, const UnresolvedSetImpl &Candidates,
+ const TemplateArgumentListInfo *TemplateArgs);
- /// Returns the i'th template candidate.
- FunctionTemplateDecl *getTemplate(unsigned I) const {
- assert(I < getNumTemplates() && "template index out of range");
- return getTrailingObjects<FunctionTemplateDecl *>()[I];
- }
-
- /// Returns the explicit template arguments that were given.
- const TemplateArgumentLoc *getTemplateArgs() const {
- return getTrailingObjects<TemplateArgumentLoc>();
- }
-
- /// Returns the number of explicit template arguments that were given.
- unsigned getNumTemplateArgs() const { return NumArgs; }
-
- llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
- return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
- }
-
- /// Returns the nth template argument.
- const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
- assert(I < getNumTemplateArgs() && "template arg index out of range");
- return getTemplateArgs()[I];
- }
-
- SourceLocation getLAngleLoc() const {
- return AngleLocs.getBegin();
- }
-
- SourceLocation getRAngleLoc() const {
- return AngleLocs.getEnd();
+ /// Returns the candidates for the primary function template.
+ ArrayRef<FunctionTemplateDecl *> getCandidates() const {
+ return {getTrailingObjects<FunctionTemplateDecl *>(), NumCandidates};
}
};
@@ -2613,70 +2579,6 @@ class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
};
-/// Declaration of a function specialization at template class scope.
-///
-/// For example:
-/// \code
-/// template <class T>
-/// class A {
-/// template <class U> void foo(U a) { }
-/// template<> void foo(int a) { }
-/// }
-/// \endcode
-///
-/// "template<> foo(int a)" will be saved in Specialization as a normal
-/// CXXMethodDecl. Then during an instantiation of class A, it will be
-/// transformed into an actual function specialization.
-///
-/// FIXME: This is redundant; we could store the same information directly on
-/// the CXXMethodDecl as a DependentFunctionTemplateSpecializationInfo.
-class ClassScopeFunctionSpecializationDecl : public Decl {
- CXXMethodDecl *Specialization;
- const ASTTemplateArgumentListInfo *TemplateArgs;
-
- ClassScopeFunctionSpecializationDecl(
- DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
- const ASTTemplateArgumentListInfo *TemplArgs)
- : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
- Specialization(FD), TemplateArgs(TemplArgs) {}
-
- ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
- : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
-
- virtual void anchor();
-
-public:
- friend class ASTDeclReader;
- friend class ASTDeclWriter;
-
- CXXMethodDecl *getSpecialization() const { return Specialization; }
- bool hasExplicitTemplateArgs() const { return TemplateArgs; }
- const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
- return TemplateArgs;
- }
-
- static ClassScopeFunctionSpecializationDecl *
- Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
- bool HasExplicitTemplateArgs,
- const TemplateArgumentListInfo &TemplateArgs) {
- return new (C, DC) ClassScopeFunctionSpecializationDecl(
- DC, Loc, FD,
- HasExplicitTemplateArgs
- ? ASTTemplateArgumentListInfo::Create(C, TemplateArgs)
- : nullptr);
- }
-
- static ClassScopeFunctionSpecializationDecl *
- CreateDeserialized(ASTContext &Context, unsigned ID);
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) { return classofKind(D->getKind()); }
-
- static bool classofKind(Kind K) {
- return K == Decl::ClassScopeFunctionSpecialization;
- }
-};
-
/// Represents a variable template specialization, which refers to
/// a variable template with a given set of template arguments.
///
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index d4146d52893ffb1..70fe4ac273ae57c 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -1563,16 +1563,6 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
}
})
-DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
- TRY_TO(TraverseDecl(D->getSpecialization()));
-
- if (D->hasExplicitTemplateArgs()) {
- TRY_TO(TraverseTemplateArgumentLocsHelper(
- D->getTemplateArgsAsWritten()->getTemplateArgs(),
- D->getTemplateArgsAsWritten()->NumTemplateArgs));
- }
-})
-
DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
DEF_TRAVERSE_DECL(ExportDecl, {})
@@ -2154,6 +2144,15 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
TALI->NumTemplateArgs));
}
}
+ // FIXME: Do we want to traverse the explicit template arguments for
+ // dependent friend function template specializations?
+ } else if (const DependentFunctionTemplateSpecializationInfo *DFSI =
+ D->getDependentSpecializationInfo()) {
+ if (const ASTTemplateArgumentListInfo *TALI =
+ DFSI->TemplateArgumentsAsWritten) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
+ TALI->NumTemplateArgs));
+ }
}
// Visit the function type itself, which can be either
diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td
index 5e726c1bdf8fa5c..8b1f415dd5fe2cb 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -102,7 +102,6 @@ def FriendTemplate : DeclNode<Decl>;
def StaticAssert : DeclNode<Decl>;
def Block : DeclNode<Decl, "blocks">, DeclContext;
def Captured : DeclNode<Decl>, DeclContext;
-def ClassScopeFunctionSpecialization : DeclNode<Decl>;
def Import : DeclNode<Decl>;
def OMPThreadPrivate : DeclNode<Decl>;
def OMPAllocate : DeclNode<Decl>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0ac4df8edb242f6..a34ee0c1f8638ed 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5210,11 +5210,11 @@ def err_explicit_specialization_inconsistent_storage_class : Error<
"'%select{none|extern|static|__private_extern__|auto|register}0'">;
def err_dependent_function_template_spec_no_match : Error<
"no candidate function template was found for dependent"
- " friend function template specialization">;
+ " %select{member|friend}0 function template specialization">;
def note_dependent_function_template_spec_discard_reason : Note<
- "candidate ignored: %select{not a function template"
- "|not a member of the enclosing namespace;"
- " did you mean to explicitly qualify the specialization?}0">;
+ "candidate ignored: %select{not a function template|"
+ "not a member of the enclosing %select{class template|"
+ "namespace; did you mean to explicitly qualify the specialization?}1}0">;
// C++ class template specializations and out-of-line definitions
def err_template_spec_needs_header : Error<
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 47379e00a7445e3..3dae60c83a06929 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8427,9 +8427,9 @@ class Sema final {
SourceLocation PrevPtOfInstantiation,
bool &SuppressNew);
- bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
- const TemplateArgumentListInfo &ExplicitTemplateArgs,
- LookupResult &Previous);
+ bool CheckDependentFunctionTemplateSpecialization(
+ FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous);
bool CheckFunctionTemplateSpecialization(
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 1de2cc6917b424a..28d603bf115950a 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -630,8 +630,6 @@ enum class TemplateSubstitutionKind : char {
// A few supplemental visitor functions.
Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateParameterList *TemplateParams,
- std::optional<const ASTTemplateArgumentListInfo *>
- ClassScopeSpecializationArgs = std::nullopt,
RewriteKind RK = RewriteKind::None);
Decl *VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams,
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 9e115f2a5cce3f9..3141283667466c8 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1481,10 +1481,6 @@ enum DeclCode {
/// template template parameter pack.
DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
- /// A ClassScopeFunctionSpecializationDecl record a class scope
- /// function specialization. (Microsoft extension).
- DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
-
/// An ImportDecl recording a module import.
DECL_IMPORT,
diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h
index ca85163e0f21c6d..d643e54e3d923a7 100644
--- a/clang/include/clang/Serialization/ASTRecordReader.h
+++ b/clang/include/clang/Serialization/ASTRecordReader.h
@@ -155,6 +155,8 @@ class ASTRecordReader
/// Reads a TemplateArgumentLoc, advancing Idx.
TemplateArgumentLoc readTemplateArgumentLoc();
+ void readTemplateArgumentListInfo(TemplateArgumentListInfo &Result);
+
const ASTTemplateArgumentListInfo*
readASTTemplateArgumentListInfo();
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index c7c2aecc8b179a4..1a6c49f0bdbd8e9 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -3342,27 +3342,25 @@ Error ASTNodeImporter::ImportTemplateInformation(
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
auto *FromInfo = FromFD->getDependentSpecializationInfo();
- UnresolvedSet<8> TemplDecls;
- unsigned NumTemplates = FromInfo->getNumTemplates();
- for (unsigned I = 0; I < NumTemplates; I++) {
- if (Expected<FunctionTemplateDecl *> ToFTDOrErr =
- import(FromInfo->getTemplate(I)))
- TemplDecls.addDecl(*ToFTDOrErr);
+ UnresolvedSet<8> Candidates;
+ for (FunctionTemplateDecl *FTD : FromInfo->getCandidates()) {
+ if (Expected<FunctionTemplateDecl *> ToFTDOrErr = import(FTD))
+ Candidates.addDecl(*ToFTDOrErr);
else
return ToFTDOrErr.takeError();
}
// Import TemplateArgumentListInfo.
TemplateArgumentListInfo ToTAInfo;
- if (Error Err = ImportTemplateArgumentListInfo(
- FromInfo->getLAngleLoc(), FromInfo->getRAngleLoc(),
- llvm::ArrayRef(FromInfo->getTemplateArgs(),
- FromInfo->getNumTemplateArgs()),
- ToTAInfo))
- return Err;
+ const auto *FromTAArgsAsWritten = FromInfo->TemplateArgumentsAsWritten;
+ if (FromTAArgsAsWritten)
+ if (Error Err =
+ ImportTemplateArgumentListInfo(*FromTAArgsAsWritten, ToTAInfo))
+ return Err;
- ToFD->setDependentTemplateSpecialization(Importer.getToContext(),
- TemplDecls, ToTAInfo);
+ ToFD->setDependentTemplateSpecialization(
+ Importer.getToContext(), Candidates,
+ FromTAArgsAsWritten ? &ToTAInfo : nullptr);
return Error::success();
}
}
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 08ae2087cfe70eb..a49751d04414a4c 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3961,6 +3961,12 @@ void FunctionDecl::setDescribedFunctionTemplate(
TemplateOrSpecialization = Template;
}
+bool FunctionDecl::isFunctionTemplateSpecialization() const {
+ return TemplateOrSpecialization.is<FunctionTemplateSpecializationInfo *>() ||
+ TemplateOrSpecialization
+ .is<DependentFunctionTemplateSpecializationInfo *>();
+}
+
void FunctionDecl::setInstantiatedFromDecl(FunctionDecl *FD) {
assert(TemplateOrSpecialization.isNull() &&
"Function is already a specialization");
@@ -4095,6 +4101,11 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const {
.dyn_cast<FunctionTemplateSpecializationInfo*>()) {
return Info->TemplateArgumentsAsWritten;
}
+ if (DependentFunctionTemplateSpecializationInfo *Info =
+ TemplateOrSpecialization
+ .dyn_cast<DependentFunctionTemplateSpecializationInfo *>()) {
+ return Info->TemplateArgumentsAsWritten;
+ }
return nullptr;
}
@@ -4123,10 +4134,9 @@ FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C,
Template->addSpecialization(Info, InsertPos);
}
-void
-FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context,
- const UnresolvedSetImpl &Templates,
- const TemplateArgumentListInfo &TemplateArgs) {
+void FunctionDecl::setDependentTemplateSpecialization(
+ ASTContext &Context, const UnresolvedSetImpl &Templates,
+ const TemplateArgumentListInfo *TemplateArgs) {
assert(TemplateOrSpecialization.isNull());
DependentFunctionTemplateSpecializationInfo *Info =
DependentFunctionTemplateSpecializationInfo::Create(Context, Templates,
@@ -4142,28 +4152,26 @@ FunctionDecl::getDependentSpecializationInfo() const {
DependentFunctionTemplateSpecializationInfo *
DependentFunctionTemplateSpecializationInfo::Create(
- ASTContext &Context, const UnresolvedSetImpl &Ts,
- const TemplateArgumentListInfo &TArgs) {
- void *Buffer = Context.Allocate(
- totalSizeToAlloc<TemplateArgumentLoc, FunctionTemplateDecl *>(
- TArgs.size(), Ts.size()));
- return new (Buffer) DependentFunctionTemplateSpecializationInfo(Ts, TArgs);
+ ASTContext &Context, const UnresolvedSetImpl &Candidates,
+ const TemplateArgumentListInfo *TArgs) {
+ const auto *TArgsWritten =
+ TArgs ? ASTTemplateArgumentListInfo::Create(Context, *TArgs) : nullptr;
+ return new (Context.Allocate(
+ totalSizeToAlloc<FunctionTemplateDecl *>(Candidates.size())))
+ DependentFunctionTemplateSpecializationInfo(Candidates, TArgsWritten);
}
DependentFunctionTemplateSpecializationInfo::
-DependentFunctionTemplateSpecializationInfo(const UnresolvedSetImpl &Ts,
- const TemplateArgumentListInfo &TArgs)
- : AngleLocs(TArgs.getLAngleLoc(), TArgs.getRAngleLoc()) {
- NumTemplates = Ts.size();
- NumArgs = TArgs.size();
-
- FunctionTemplateDecl **TsArray = getTrailingObjects<FunctionTemplateDecl *>();
- for (unsigned I = 0, E = Ts.size(); I != E; ++I)
- TsArray[I] = cast<FunctionTemplateDecl>(Ts[I]->getUnderlyingDecl());
-
- TemplateArgumentLoc *ArgsArray = getTrailingObjects<TemplateArgumentLoc>();
- for (unsigned I = 0, E = TArgs.size(); I != E; ++I)
- new (&ArgsArray[I]) TemplateArgumentLoc(TArgs[I]);
+ DependentFunctionTemplateSpecializationInfo(
+ const UnresolvedSetImpl &Candidates,
+ const ASTTemplateArgumentListInfo *TemplateArgsWritten)
+ : TemplateArgumentsAsWritten(TemplateArgsWritten),
+ NumCandidates(Candidates.size()) {
+ std::transform(Candidates.begin(), Candidates.end(),
+ getTrailingObjects<FunctionTemplateDecl *>(),
+ [](NamedDecl *ND) {
+ return cast<FunctionTemplateDecl>(ND->getUnderlyingDecl());
+ });
}
TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
@@ -4178,6 +4186,13 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSInfo->getTemplateSpecializationKind();
+ // A dependent function template specialization is an explicit specialization,
+ // except when it's a friend declaration.
+ if (TemplateOrSpecialization
+ .is<DependentFunctionTemplateSpecializationInfo *>() &&
+ getFriendObjectKind() == FOK_None)
+ return TSK_ExplicitSpecialization;
+
return TSK_Undeclared;
}
@@ -4192,6 +4207,11 @@ FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
// template<> void f<int>() {}
// };
//
+ // Within the templated CXXRecordDecl, A<T>::f<int> is a dependent function
+ // template specialization; both getTemplateSpecializationKind() and
+ // getTemplateSpecializationKindForInstantiation() will return
+ // TSK_ExplicitSpecialization.
+ //
// For A<int>::f<int>():
// * getTemplateSpecializationKind() will return TSK_ExplicitSpecialization
// * getTemplateSpecializationKindForInstantiation() will return
@@ -4212,6 +4232,11 @@ FunctionDecl::getTemplateSpecializationKindForInstantiation() const {
TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo *>())
return MSInfo->getTemplateSpecializationKind();
+ if (TemplateOrSpecialization
+ .is<DependentFunctionTemplateSpecializationInfo *>() &&
+ getFriendObjectKind() == FOK_None)
+ return TSK_ExplicitSpecialization;
+
return TSK_Undeclared;
}
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 834beef49a44417..6048718854d6988 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -862,7 +862,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case BuiltinTemplate:
case ClassTemplateSpecialization:
case ClassTemplatePartialSpecialization:
- case ClassScopeFunctionSpecialization:
case VarTemplateSpecialization:
case VarTemplatePartialSpecialization:
case ObjCImplementation:
@@ -1004,7 +1003,6 @@ bool Decl::AccessDeclContextCheck() const {
// FIXME: a ClassTemplateSpecialization or CXXRecordDecl can have
// AS_none as access specifier.
isa<CXXRecordDecl>(this) ||
- isa<ClassScopeFunctionSpecializationDecl>(this) ||
isa<LifetimeExtendedTemporaryDecl>(this))
return true;
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 5e2742b4949f260..be385ca1152546e 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -1195,19 +1195,6 @@ TypeAliasTemplateDecl::newCommon(ASTContext &C) const {
return CommonPtr;
}
-//===----------------------------------------------------------------------===//
-// ClassScopeFunctionSpecializationDecl Implementation
-//===----------------------------------------------------------------------===//
-
-void ClassScopeFunctionSpecializationDecl::anchor() {}
-
-ClassScopeFunctionSpecializationDecl *
-ClassScopeFunctionSpecializationDecl::CreateDeserialized(ASTContext &C,
- unsigned ID) {
- return new (C, ID) ClassScopeFunctionSpecializationDecl(
- nullptr, SourceLocation(), nullptr, nullptr);
-}
-
//===----------------------------------------------------------------------===//
// VarTemplateDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 5eab315793b4113..7f9b5eb52e367eb 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -658,6 +658,10 @@ void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
if (F->isFunctionTemplateSpecialization()) {
if (!isa<CXXMethodDecl>(DC)) return;
if (DC->getLexicalParent()->isFileContext()) return;
+ // Skip class scope explicit function template specializations,
+ // as they have not yet been instantiated.
+ if (F->getDependentSpecializationInfo())
+ return;
// Inline method specializations are the only supported
// specialization for now.
}
diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp
index 99b94588f56f0a5..4d4c94d008c9dfc 100644
--- a/clang/lib/CodeGen/CGDecl.cpp
+++ b/clang/lib/CodeGen/CGDecl.cpp
@@ -96,7 +96,6 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::FriendTemplate:
case Decl::Block:
case Decl::Captured:
- case Decl::ClassScopeFunctionSpecialization:
case Decl::UsingShadow:
case Decl::ConstructorUsingShadow:
case Decl::ObjCTypeParam:
diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp
index d7316538f606141..cfdffeed834e687 100644
--- a/clang/lib/Index/IndexSymbol.cpp
+++ b/clang/lib/Index/IndexSymbol.cpp
@@ -346,7 +346,6 @@ SymbolInfo index::getSymbolInfo(const Decl *D) {
}
break;
case Decl::ClassTemplatePartialSpecialization:
- case Decl::ClassScopeFunctionSpecialization:
case Decl::ClassTemplateSpecialization:
case Decl::CXXRecord:
case Decl::Enum:
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7d92e93188610c0..0e9717e6293b4ca 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9774,7 +9774,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
bool isMemberSpecialization = false;
bool isFunctionTemplateSpecialization = false;
- bool isDependentClassScopeExplicitSpecialization = false;
bool HasExplicitTemplateArgs = false;
TemplateArgumentListInfo TemplateArgs;
@@ -10414,12 +10413,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
HasExplicitTemplateArgs = false;
- } else {
- assert((isFunctionTemplateSpecialization ||
- D.getDeclSpec().isFriendSpecified()) &&
- "should have a 'template<>' for this decl");
+ } else if (isFriend) {
// "friend void foo<>(int);" is an implicit specialization decl.
isFunctionTemplateSpecialization = true;
+ } else {
+ assert(isFunctionTemplateSpecialization &&
+ "should have a 'template<>' for this decl");
}
} else if (isFriend && isFunctionTemplateSpecialization) {
// This combination is only possible in a recovery case; the user
@@ -10442,32 +10441,54 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (getLangOpts().CUDA && !isFunctionTemplateSpecialization)
maybeAddCUDAHostDeviceAttrs(NewFD, Previous);
- // If it's a friend (and only if it's a friend), it's possible
- // that either the specialized function type or the specialized
- // template is dependent, and therefore matching will fail. In
- // this case, don't check the specialization yet.
- if (isFunctionTemplateSpecialization && isFriend &&
- (NewFD->getType()->isDependentType() || DC->isDependentContext() ||
- TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
- TemplateArgs.arguments()))) {
- assert(HasExplicitTemplateArgs &&
- "friend function specialization without template args");
- if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
- Previous))
- NewFD->setInvalidDecl();
- } else if (isFunctionTemplateSpecialization) {
- if (CurContext->isDependentContext() && CurContext->isRecord()
- && !isFriend) {
- isDependentClassScopeExplicitSpecialization = true;
- } else if (!NewFD->isInvalidDecl() &&
- CheckFunctionTemplateSpecialization(
- NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
- Previous))
- NewFD->setInvalidDecl();
+ // Handle explict specializations of function templates
+ // and friend function declarations with an explicit
+ // template argument list.
+ if (isFunctionTemplateSpecialization) {
+ bool isDependentSpecialization = false;
+ if (isFriend) {
+ // For friend function specializations, this is a dependent
+ // specialization if its semantic context is dependent, its
+ // type is dependent, or if its template-id is dependent.
+ isDependentSpecialization =
+ DC->isDependentContext() || NewFD->getType()->isDependentType() ||
+ (HasExplicitTemplateArgs &&
+ TemplateSpecializationType::
+ anyInstantiationDependentTemplateArguments(
+ TemplateArgs.arguments()));
+ assert(!isDependentSpecialization ||
+ (HasExplicitTemplateArgs == isDependentSpecialization) &&
+ "dependent friend function specialization without template "
+ "args");
+ } else {
+ // For class-scope explicit specializations of function templates,
+ // if the lexical context is dependent, then the specialization
+ // is dependent.
+ isDependentSpecialization =
+ CurContext->isRecord() && CurContext->isDependentContext();
+ }
+
+ TemplateArgumentListInfo *ExplicitTemplateArgs =
+ HasExplicitTemplateArgs ? &TemplateArgs : nullptr;
+ if (isDependentSpecialization) {
+ // If it's a dependent specialization, it may not be possible
+ // to determine the primary template (for explicit specializations)
+ // or befriended declaration (for friends) until the enclosing
+ // template is instantiated. In such cases, we store the declarations
+ // found by name lookup and defer resolution until instantiation.
+ if (CheckDependentFunctionTemplateSpecialization(
+ NewFD, ExplicitTemplateArgs, Previous))
+ NewFD->setInvalidDecl();
+ } else if (!NewFD->isInvalidDecl()) {
+ if (CheckFunctionTemplateSpecialization(NewFD, ExplicitTemplateArgs,
+ Previous))
+ NewFD->setInvalidDecl();
+ }
// C++ [dcl.stc]p1:
// A storage-class-specifier shall not be specified in an explicit
// specialization (14.7.3)
+ // FIXME: We should be checking this for dependent specializations.
FunctionTemplateSpecializationInfo *Info =
NewFD->getTemplateSpecializationInfo();
if (Info && SC != SC_None) {
@@ -10490,21 +10511,19 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
// Perform semantic checking on the function declaration.
- if (!isDependentClassScopeExplicitSpecialization) {
- if (!NewFD->isInvalidDecl() && NewFD->isMain())
- CheckMain(NewFD, D.getDeclSpec());
+ if (!NewFD->isInvalidDecl() && NewFD->isMain())
+ CheckMain(NewFD, D.getDeclSpec());
- if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
- CheckMSVCRTEntryPoint(NewFD);
+ if (!NewFD->isInvalidDecl() && NewFD->isMSVCRTEntryPoint())
+ CheckMSVCRTEntryPoint(NewFD);
- if (!NewFD->isInvalidDecl())
- D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
- isMemberSpecialization,
- D.isFunctionDefinition()));
- else if (!Previous.empty())
- // Recover gracefully from an invalid redeclaration.
- D.setRedeclaration(true);
- }
+ if (!NewFD->isInvalidDecl())
+ D.setRedeclaration(CheckFunctionDeclaration(S, NewFD, Previous,
+ isMemberSpecialization,
+ D.isFunctionDefinition()));
+ else if (!Previous.empty())
+ // Recover gracefully from an invalid redeclaration.
+ D.setRedeclaration(true);
assert((NewFD->isInvalidDecl() || NewFD->isMultiVersion() ||
!D.isRedeclaration() ||
@@ -10816,19 +10835,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
}
}
- // Here we have an function template explicit specialization at class scope.
- // The actual specialization will be postponed to template instatiation
- // time via the ClassScopeFunctionSpecializationDecl node.
- if (isDependentClassScopeExplicitSpecialization) {
- ClassScopeFunctionSpecializationDecl *NewSpec =
- ClassScopeFunctionSpecializationDecl::Create(
- Context, CurContext, NewFD->getLocation(),
- cast<CXXMethodDecl>(NewFD),
- HasExplicitTemplateArgs, TemplateArgs);
- CurContext->addDecl(NewSpec);
- AddToScope = false;
- }
-
// Diagnose availability attributes. Availability cannot be used on functions
// that are run during load/unload.
if (const auto *attr = NewFD->getAttr<AvailabilityAttr>()) {
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 994d89e25b3848e..66688e0fed440c0 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -9327,10 +9327,9 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
///
/// There really isn't any useful analysis we can do here, so we
/// just store the information.
-bool
-Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
- const TemplateArgumentListInfo &ExplicitTemplateArgs,
- LookupResult &Previous) {
+bool Sema::CheckDependentFunctionTemplateSpecialization(
+ FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
+ LookupResult &Previous) {
// Remove anything from Previous that isn't a function template in
// the correct context.
DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext();
@@ -9354,13 +9353,14 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
}
F.done();
+ bool isFriend = FD->getFriendObjectKind() != Decl::FOK_None;
if (Previous.empty()) {
- Diag(FD->getLocation(),
- diag::err_dependent_function_template_spec_no_match);
+ Diag(FD->getLocation(), diag::err_dependent_function_template_spec_no_match)
+ << isFriend;
for (auto &P : DiscardedCandidates)
Diag(P.second->getLocation(),
diag::note_dependent_function_template_spec_discard_reason)
- << P.first;
+ << P.first << isFriend;
return true;
}
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 37a7d6204413a38..085e885e294a626 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -2239,42 +2239,46 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
D->isLocalExternDecl() ? Sema::ForExternalRedeclaration
: SemaRef.forRedeclarationInCurContext());
- if (DependentFunctionTemplateSpecializationInfo *Info
- = D->getDependentSpecializationInfo()) {
- assert(isFriend && "non-friend has dependent specialization info?");
+ if (DependentFunctionTemplateSpecializationInfo *DFTSI =
+ D->getDependentSpecializationInfo()) {
+ assert(isFriend && "dependent specialization info on "
+ "non-member non-friend function?");
// Instantiate the explicit template arguments.
- TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
- Info->getRAngleLoc());
- if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
- ExplicitArgs))
- return nullptr;
-
- // Map the candidate templates to their instantiations.
- for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
- Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
- Info->getTemplate(I),
- TemplateArgs);
- if (!Temp) return nullptr;
+ TemplateArgumentListInfo ExplicitArgs;
+ if (const auto *ArgsWritten = DFTSI->TemplateArgumentsAsWritten) {
+ ExplicitArgs.setLAngleLoc(ArgsWritten->getLAngleLoc());
+ ExplicitArgs.setRAngleLoc(ArgsWritten->getRAngleLoc());
+ if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
+ ExplicitArgs))
+ return nullptr;
+ }
- Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
+ // Map the candidates for the primary template to their instantiations.
+ for (FunctionTemplateDecl *FTD : DFTSI->getCandidates()) {
+ if (NamedDecl *ND =
+ SemaRef.FindInstantiatedDecl(D->getLocation(), FTD, TemplateArgs))
+ Previous.addDecl(ND);
+ else
+ return nullptr;
}
- if (SemaRef.CheckFunctionTemplateSpecialization(Function,
- &ExplicitArgs,
- Previous))
+ if (SemaRef.CheckFunctionTemplateSpecialization(
+ Function,
+ DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
+ Previous))
Function->setInvalidDecl();
IsExplicitSpecialization = true;
- } else if (const ASTTemplateArgumentListInfo *Info =
+ } else if (const ASTTemplateArgumentListInfo *ArgsWritten =
D->getTemplateSpecializationArgsAsWritten()) {
// The name of this function was written as a template-id.
SemaRef.LookupQualifiedName(Previous, DC);
// Instantiate the explicit template arguments.
- TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
- Info->getRAngleLoc());
- if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
+ TemplateArgumentListInfo ExplicitArgs(ArgsWritten->getLAngleLoc(),
+ ArgsWritten->getRAngleLoc());
+ if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
ExplicitArgs))
return nullptr;
@@ -2396,8 +2400,6 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(
Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
CXXMethodDecl *D, TemplateParameterList *TemplateParams,
- std::optional<const ASTTemplateArgumentListInfo *>
- ClassScopeSpecializationArgs,
RewriteKind FunctionRewriteKind) {
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
if (FunctionTemplate && !TemplateParams) {
@@ -2627,41 +2629,41 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
// If the name of this function was written as a template-id, instantiate
// the explicit template arguments.
- if (DependentFunctionTemplateSpecializationInfo *Info
- = D->getDependentSpecializationInfo()) {
- assert(isFriend && "non-friend has dependent specialization info?");
-
+ if (DependentFunctionTemplateSpecializationInfo *DFTSI =
+ D->getDependentSpecializationInfo()) {
// Instantiate the explicit template arguments.
- TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
- Info->getRAngleLoc());
- if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
- ExplicitArgs))
- return nullptr;
-
- // Map the candidate templates to their instantiations.
- for (unsigned I = 0, E = Info->getNumTemplates(); I != E; ++I) {
- Decl *Temp = SemaRef.FindInstantiatedDecl(D->getLocation(),
- Info->getTemplate(I),
- TemplateArgs);
- if (!Temp) return nullptr;
+ TemplateArgumentListInfo ExplicitArgs;
+ if (const auto *ArgsWritten = DFTSI->TemplateArgumentsAsWritten) {
+ ExplicitArgs.setLAngleLoc(ArgsWritten->getLAngleLoc());
+ ExplicitArgs.setRAngleLoc(ArgsWritten->getRAngleLoc());
+ if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
+ ExplicitArgs))
+ return nullptr;
+ }
- Previous.addDecl(cast<FunctionTemplateDecl>(Temp));
+ // Map the candidates for the primary template to their instantiations.
+ for (FunctionTemplateDecl *FTD : DFTSI->getCandidates()) {
+ if (NamedDecl *ND =
+ SemaRef.FindInstantiatedDecl(D->getLocation(), FTD, TemplateArgs))
+ Previous.addDecl(ND);
+ else
+ return nullptr;
}
- if (SemaRef.CheckFunctionTemplateSpecialization(Method,
- &ExplicitArgs,
- Previous))
+ if (SemaRef.CheckFunctionTemplateSpecialization(
+ Method, DFTSI->TemplateArgumentsAsWritten ? &ExplicitArgs : nullptr,
+ Previous))
Method->setInvalidDecl();
IsExplicitSpecialization = true;
- } else if (const ASTTemplateArgumentListInfo *Info =
- ClassScopeSpecializationArgs.value_or(
- D->getTemplateSpecializationArgsAsWritten())) {
+ } else if (const ASTTemplateArgumentListInfo *ArgsWritten =
+ D->getTemplateSpecializationArgsAsWritten()) {
SemaRef.LookupQualifiedName(Previous, DC);
- TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
- Info->getRAngleLoc());
- if (SemaRef.SubstTemplateArguments(Info->arguments(), TemplateArgs,
+ TemplateArgumentListInfo ExplicitArgs(ArgsWritten->getLAngleLoc(),
+ ArgsWritten->getRAngleLoc());
+
+ if (SemaRef.SubstTemplateArguments(ArgsWritten->arguments(), TemplateArgs,
ExplicitArgs))
return nullptr;
@@ -2670,14 +2672,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
Previous))
Method->setInvalidDecl();
- IsExplicitSpecialization = true;
- } else if (ClassScopeSpecializationArgs) {
- // Class-scope explicit specialization written without explicit template
- // arguments.
- SemaRef.LookupQualifiedName(Previous, DC);
- if (SemaRef.CheckFunctionTemplateSpecialization(Method, nullptr, Previous))
- Method->setInvalidDecl();
-
IsExplicitSpecialization = true;
} else if (!FunctionTemplate || TemplateParams || isFriend) {
SemaRef.LookupQualifiedName(Previous, Record);
@@ -3502,13 +3496,6 @@ Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) {
return NewD;
}
-Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *Decl) {
- CXXMethodDecl *OldFD = Decl->getSpecialization();
- return cast_or_null<CXXMethodDecl>(
- VisitCXXMethodDecl(OldFD, nullptr, Decl->getTemplateArgsAsWritten()));
-}
-
Decl *TemplateDeclInstantiator::VisitOMPThreadPrivateDecl(
OMPThreadPrivateDecl *D) {
SmallVector<Expr *, 5> Vars;
@@ -4086,7 +4073,7 @@ FunctionDecl *Sema::SubstSpaceshipAsEqualEqual(CXXRecordDecl *RD,
Decl *R;
if (auto *MD = dyn_cast<CXXMethodDecl>(Spaceship)) {
R = Instantiator.VisitCXXMethodDecl(
- MD, nullptr, std::nullopt,
+ MD, nullptr,
TemplateDeclInstantiator::RewriteKind::RewriteSpaceshipAsEqualEqual);
} else {
assert(Spaceship->getFriendObjectKind() &&
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 72e582107480976..6110e287b7fb50f 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -424,7 +424,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
case Decl::StaticAssert:
case Decl::Block:
case Decl::Captured:
- case Decl::ClassScopeFunctionSpecialization:
case Decl::Import:
case Decl::OMPThreadPrivate:
case Decl::OMPAllocate:
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 0952244d037a77c..4b4b3b8e2bcbeae 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -7383,15 +7383,20 @@ TemplateArgumentLoc ASTRecordReader::readTemplateArgumentLoc() {
return TemplateArgumentLoc(Arg, readTemplateArgumentLocInfo(Arg.getKind()));
}
-const ASTTemplateArgumentListInfo *
-ASTRecordReader::readASTTemplateArgumentListInfo() {
- SourceLocation LAngleLoc = readSourceLocation();
- SourceLocation RAngleLoc = readSourceLocation();
+void ASTRecordReader::readTemplateArgumentListInfo(
+ TemplateArgumentListInfo &Result) {
+ Result.setLAngleLoc(readSourceLocation());
+ Result.setRAngleLoc(readSourceLocation());
unsigned NumArgsAsWritten = readInt();
- TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
for (unsigned i = 0; i != NumArgsAsWritten; ++i)
- TemplArgsInfo.addArgument(readTemplateArgumentLoc());
- return ASTTemplateArgumentListInfo::Create(getContext(), TemplArgsInfo);
+ Result.addArgument(readTemplateArgumentLoc());
+}
+
+const ASTTemplateArgumentListInfo *
+ASTRecordReader::readASTTemplateArgumentListInfo() {
+ TemplateArgumentListInfo Result;
+ readTemplateArgumentListInfo(Result);
+ return ASTTemplateArgumentListInfo::Create(getContext(), Result);
}
Decl *ASTReader::GetExternalDecl(uint32_t ID) {
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 88cb54a0365e62b..0a1ff254fd57d23 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -359,8 +359,6 @@ namespace clang {
void VisitClassTemplatePartialSpecializationDecl(
ClassTemplatePartialSpecializationDecl *D);
- void VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
RedeclarableResult
VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D);
@@ -950,27 +948,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true);
// Template args as written.
- SmallVector<TemplateArgumentLoc, 8> TemplArgLocs;
- SourceLocation LAngleLoc, RAngleLoc;
- bool HasTemplateArgumentsAsWritten = Record.readInt();
- if (HasTemplateArgumentsAsWritten) {
- unsigned NumTemplateArgLocs = Record.readInt();
- TemplArgLocs.reserve(NumTemplateArgLocs);
- for (unsigned i = 0; i != NumTemplateArgLocs; ++i)
- TemplArgLocs.push_back(Record.readTemplateArgumentLoc());
-
- LAngleLoc = readSourceLocation();
- RAngleLoc = readSourceLocation();
- }
+ TemplateArgumentListInfo TemplArgsWritten;
+ bool HasTemplateArgumentsAsWritten = Record.readBool();
+ if (HasTemplateArgumentsAsWritten)
+ Record.readTemplateArgumentListInfo(TemplArgsWritten);
SourceLocation POI = readSourceLocation();
ASTContext &C = Reader.getContext();
TemplateArgumentList *TemplArgList
= TemplateArgumentList::CreateCopy(C, TemplArgs);
- TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc);
- for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i)
- TemplArgsInfo.addArgument(TemplArgLocs[i]);
MemberSpecializationInfo *MSInfo = nullptr;
if (Record.readInt()) {
@@ -985,7 +972,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FunctionTemplateSpecializationInfo *FTInfo =
FunctionTemplateSpecializationInfo::Create(
C, FD, Template, TSK, TemplArgList,
- HasTemplateArgumentsAsWritten ? &TemplArgsInfo : nullptr, POI,
+ HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr, POI,
MSInfo);
FD->TemplateOrSpecialization = FTInfo;
@@ -1016,21 +1003,20 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
}
case FunctionDecl::TK_DependentFunctionTemplateSpecialization: {
// Templates.
- UnresolvedSet<8> TemplDecls;
- unsigned NumTemplates = Record.readInt();
- while (NumTemplates--)
- TemplDecls.addDecl(readDeclAs<NamedDecl>());
+ UnresolvedSet<8> Candidates;
+ unsigned NumCandidates = Record.readInt();
+ while (NumCandidates--)
+ Candidates.addDecl(readDeclAs<NamedDecl>());
// Templates args.
- TemplateArgumentListInfo TemplArgs;
- unsigned NumArgs = Record.readInt();
- while (NumArgs--)
- TemplArgs.addArgument(Record.readTemplateArgumentLoc());
- TemplArgs.setLAngleLoc(readSourceLocation());
- TemplArgs.setRAngleLoc(readSourceLocation());
-
- FD->setDependentTemplateSpecialization(Reader.getContext(),
- TemplDecls, TemplArgs);
+ TemplateArgumentListInfo TemplArgsWritten;
+ bool HasTemplateArgumentsAsWritten = Record.readBool();
+ if (HasTemplateArgumentsAsWritten)
+ Record.readTemplateArgumentListInfo(TemplArgsWritten);
+
+ FD->setDependentTemplateSpecialization(
+ Reader.getContext(), Candidates,
+ HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr);
// These are not merged; we don't need to merge redeclarations of dependent
// template friends.
break;
@@ -2521,14 +2507,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
}
}
-void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D) {
- VisitDecl(D);
- D->Specialization = readDeclAs<CXXMethodDecl>();
- if (Record.readInt())
- D->TemplateArgs = Record.readASTTemplateArgumentListInfo();
-}
-
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
@@ -3877,9 +3855,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) {
case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION:
D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID);
break;
- case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION:
- D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID);
- break;
case DECL_FUNCTION_TEMPLATE:
D = FunctionTemplateDecl::CreateDeserialized(Context, ID);
break;
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 65bee806d2c5571..2d3a126cabbafd1 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1029,7 +1029,6 @@ void ASTWriter::WriteBlockInfoBlock() {
RECORD(DECL_INDIRECTFIELD);
RECORD(DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK);
RECORD(DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK);
- RECORD(DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION);
RECORD(DECL_IMPORT);
RECORD(DECL_OMP_THREADPRIVATE);
RECORD(DECL_EMPTY);
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 4426f5c22277ed1..78ddf00cf3e1370 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -81,8 +81,6 @@ namespace clang {
void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D);
void VisitVarTemplatePartialSpecializationDecl(
VarTemplatePartialSpecializationDecl *D);
- void VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D);
void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D);
void VisitValueDecl(ValueDecl *D);
void VisitEnumConstantDecl(EnumConstantDecl *D);
@@ -617,15 +615,9 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
// Template args as written.
Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr);
- if (FTSInfo->TemplateArgumentsAsWritten) {
- Record.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs);
- for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs;
- i!=e; ++i)
- Record.AddTemplateArgumentLoc(
- (*FTSInfo->TemplateArgumentsAsWritten)[i]);
- Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc);
- Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc);
- }
+ if (FTSInfo->TemplateArgumentsAsWritten)
+ Record.AddASTTemplateArgumentListInfo(
+ FTSInfo->TemplateArgumentsAsWritten);
Record.AddSourceLocation(FTSInfo->getPointOfInstantiation());
@@ -650,17 +642,16 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) {
DependentFunctionTemplateSpecializationInfo *
DFTSInfo = D->getDependentSpecializationInfo();
- // Templates.
- Record.push_back(DFTSInfo->getNumTemplates());
- for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i)
- Record.AddDeclRef(DFTSInfo->getTemplate(i));
+ // Candidates.
+ Record.push_back(DFTSInfo->getCandidates().size());
+ for (FunctionTemplateDecl *FTD : DFTSInfo->getCandidates())
+ Record.AddDeclRef(FTD);
// Templates args.
- Record.push_back(DFTSInfo->getNumTemplateArgs());
- for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i)
- Record.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i));
- Record.AddSourceLocation(DFTSInfo->getLAngleLoc());
- Record.AddSourceLocation(DFTSInfo->getRAngleLoc());
+ Record.push_back(DFTSInfo->TemplateArgumentsAsWritten != nullptr);
+ if (DFTSInfo->TemplateArgumentsAsWritten)
+ Record.AddASTTemplateArgumentListInfo(
+ DFTSInfo->TemplateArgumentsAsWritten);
break;
}
}
@@ -1746,17 +1737,6 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl(
Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
}
-void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
- ClassScopeFunctionSpecializationDecl *D) {
- VisitDecl(D);
- Record.AddDeclRef(D->getSpecialization());
- Record.push_back(D->hasExplicitTemplateArgs());
- if (D->hasExplicitTemplateArgs())
- Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
- Code = serialization::DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION;
-}
-
-
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D);
diff --git a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
index a20d24db158f50b..66e9a501c348eb5 100644
--- a/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp
@@ -202,7 +202,7 @@ static QualType getInnerPointerType(CheckerContext C, const CXXRecordDecl *RD) {
static QualType getPointerTypeFromTemplateArg(const CallEvent &Call,
CheckerContext &C) {
const auto *FD = dyn_cast_or_null<FunctionDecl>(Call.getDecl());
- if (!FD || !FD->isFunctionTemplateSpecialization())
+ if (!FD || !FD->getPrimaryTemplate())
return {};
const auto &TemplateArgs = FD->getTemplateSpecializationArgs()->asArray();
if (TemplateArgs.size() == 0)
diff --git a/clang/test/AST/ast-dump-decl.cpp b/clang/test/AST/ast-dump-decl.cpp
index 6848a2b01da2c91..017e640aeaea6d7 100644
--- a/clang/test/AST/ast-dump-decl.cpp
+++ b/clang/test/AST/ast-dump-decl.cpp
@@ -645,11 +645,16 @@ class TestClassScopeFunctionSpecialization {
template<class U> void foo(U a) { }
template<> void foo<int>(int a) { }
};
-// CHECK: ClassScopeFunctionSpecializationDecl
-// CHECK-NEXT: CXXMethod{{.*}} foo 'void (int)'
+// CHECK: FunctionTemplateDecl{{.*}} foo
+// CHECK-NEXT: TemplateTypeParmDecl{{.*}} referenced class depth 1 index 0 U
+// CHECK-NEXT: CXXMethodDecl{{.*}} foo 'void (U)' implicit-inline
// CHECK-NEXT: ParmVarDecl
// CHECK-NEXT: CompoundStmt
+// CHECK-NEXT: CXXMethodDecl{{.*}} foo 'void (int)' explicit_specialization implicit-inline
// CHECK-NEXT: TemplateArgument{{.*}} 'int'
+// CHECK-NEXT: BuiltinType{{.*}} 'int'
+// CHECK-NEXT: ParmVarDecl
+// CHECK-NEXT: CompoundStmt
namespace TestTemplateTypeParmDecl {
template<typename ... T, class U = int> void foo();
diff --git a/clang/test/CXX/drs/dr7xx.cpp b/clang/test/CXX/drs/dr7xx.cpp
index f6a2e5923bedb5d..11901b80d646225 100644
--- a/clang/test/CXX/drs/dr7xx.cpp
+++ b/clang/test/CXX/drs/dr7xx.cpp
@@ -111,6 +111,11 @@ namespace dr727 { // dr727: partial
template<typename T> struct C<T*> {};
template<typename T> static const int N<T*>;
+
+ template<typename>
+ struct E {
+ template<> void f<void>() {} // expected-error {{no candidate function template}}
+ };
};
void d(D<int> di) {
diff --git a/clang/test/SemaTemplate/instantiate-method.cpp b/clang/test/SemaTemplate/instantiate-method.cpp
index 9cd668dacf5c9c5..666c8aea87aabd7 100644
--- a/clang/test/SemaTemplate/instantiate-method.cpp
+++ b/clang/test/SemaTemplate/instantiate-method.cpp
@@ -185,14 +185,11 @@ namespace SameSignatureAfterInstantiation {
namespace PR22040 {
template <typename T> struct Foobar {
- template <> void bazqux(typename T::type) {} // expected-error 2{{cannot be used prior to '::' because it has no members}}
+ template <> void bazqux(T) {} // expected-error {{no candidate function template was found for dependent member function template specialization}}
};
void test() {
- // FIXME: we should suppress the "no member" errors
- Foobar<void>::bazqux(); // expected-error{{no member named 'bazqux' in }} expected-note{{in instantiation of template class }}
- Foobar<int>::bazqux(); // expected-error{{no member named 'bazqux' in }} expected-note{{in instantiation of template class }}
- Foobar<int>::bazqux(3); // expected-error{{no member named 'bazqux' in }}
+ Foobar<int>::bazqux(1);
}
}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index f0c8ecfcb6264fb..4766561f5d4bd24 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -6847,7 +6847,6 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
case Decl::Captured:
case Decl::OMPCapturedExpr:
case Decl::Label: // FIXME: Is this right??
- case Decl::ClassScopeFunctionSpecialization:
case Decl::CXXDeductionGuide:
case Decl::Import:
case Decl::OMPThreadPrivate:
>From d9f14d1fbc987c90406c4dd7be221cde3a43966d Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Tue, 19 Sep 2023 05:19:52 -0400
Subject: [PATCH 2/2] [FOLD]
---
.../clang-tidy/modernize/UseEmplaceCheck.cpp | 8 +++----
clang/include/clang/AST/ASTNodeTraverser.h | 6 +++--
.../test/SemaTemplate/instantiate-method.cpp | 22 ++++++++++---------
3 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
index 06ae1f4e257528f..b85dde5644d313f 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
@@ -67,11 +67,9 @@ AST_MATCHER_P(CallExpr, hasLastArgument,
// function had parameters defined (this is useful to check if there is only one
// variadic argument).
AST_MATCHER(CXXMemberCallExpr, hasSameNumArgsAsDeclNumParams) {
- if (Node.getMethodDecl()->getPrimaryTemplate())
- return Node.getNumArgs() == Node.getMethodDecl()
- ->getPrimaryTemplate()
- ->getTemplatedDecl()
- ->getNumParams();
+ if (const FunctionTemplateDecl *Primary =
+ Node.getMethodDecl()->getPrimaryTemplate())
+ return Node.getNumArgs() == Primary->getTemplatedDecl()->getNumParams();
return Node.getNumArgs() == Node.getMethodDecl()->getNumParams();
}
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index c3d233d3ab4a259..cc8dab97f8b010f 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -426,9 +426,11 @@ class ASTNodeTraverser
}
void VisitFunctionDecl(const FunctionDecl *D) {
- if (const auto *FTSI = D->getTemplateSpecializationInfo())
+ if (FunctionTemplateSpecializationInfo *FTSI =
+ D->getTemplateSpecializationInfo())
dumpTemplateArgumentList(*FTSI->TemplateArguments);
- else if (const auto *DFTSI = D->getDependentSpecializationInfo())
+ else if (DependentFunctionTemplateSpecializationInfo *DFTSI =
+ D->getDependentSpecializationInfo())
dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten);
if (D->param_begin())
diff --git a/clang/test/SemaTemplate/instantiate-method.cpp b/clang/test/SemaTemplate/instantiate-method.cpp
index 666c8aea87aabd7..60889a4cffe46ae 100644
--- a/clang/test/SemaTemplate/instantiate-method.cpp
+++ b/clang/test/SemaTemplate/instantiate-method.cpp
@@ -45,7 +45,7 @@ class HasDestructor {
virtual ~HasDestructor() = 0;
};
-int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
+int i = sizeof(HasDestructor<int>); // FIXME: forces instantiation, but
// the code below should probably instantiate by itself.
int abstract_destructor[__is_abstract(HasDestructor<int>)? 1 : -1];
@@ -94,7 +94,7 @@ struct X0 : X0Base {
template<typename U>
struct X1 : X0<U> {
- int &f2() {
+ int &f2() {
return X0Base::f();
}
};
@@ -129,19 +129,19 @@ namespace test1 {
}
namespace PR6947 {
- template< class T >
+ template< class T >
struct X {
- int f0( )
+ int f0( )
{
typedef void ( X::*impl_fun_ptr )( );
impl_fun_ptr pImpl = &X::template
f0_impl1<int>;
}
- private:
+ private:
int f1() {
}
- template< class Processor>
- void f0_impl1( )
+ template< class Processor>
+ void f0_impl1( )
{
}
};
@@ -154,7 +154,7 @@ namespace PR6947 {
}
namespace PR7022 {
- template <typename >
+ template <typename >
struct X1
{
typedef int state_t( );
@@ -185,11 +185,13 @@ namespace SameSignatureAfterInstantiation {
namespace PR22040 {
template <typename T> struct Foobar {
- template <> void bazqux(T) {} // expected-error {{no candidate function template was found for dependent member function template specialization}}
+ template <> void bazqux(typename T::type) {} // expected-error {{no candidate function template was found for dependent member function template specialization}}
};
void test() {
- Foobar<int>::bazqux(1);
+ Foobar<void>::bazqux();
+ Foobar<int>::bazqux();
+ Foobar<int>::bazqux(3); // expected-error{{no member named 'bazqux' in }}
}
}
More information about the cfe-commits
mailing list