Skip to content

Commit 39744e6

Browse files
committed
[clang] remove ClassScopeFunctionSpecializationDecl
1 parent 7050ff4 commit 39744e6

33 files changed

+312
-459
lines changed

clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp

+3-5
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,9 @@ AST_MATCHER_P(CallExpr, hasLastArgument,
6767
// function had parameters defined (this is useful to check if there is only one
6868
// variadic argument).
6969
AST_MATCHER(CXXMemberCallExpr, hasSameNumArgsAsDeclNumParams) {
70-
if (Node.getMethodDecl()->isFunctionTemplateSpecialization())
71-
return Node.getNumArgs() == Node.getMethodDecl()
72-
->getPrimaryTemplate()
73-
->getTemplatedDecl()
74-
->getNumParams();
70+
if (const FunctionTemplateDecl *Primary =
71+
Node.getMethodDecl()->getPrimaryTemplate())
72+
return Node.getNumArgs() == Primary->getTemplatedDecl()->getNumParams();
7573

7674
return Node.getNumArgs() == Node.getMethodDecl()->getNumParams();
7775
}

clang-tools-extra/clangd/SemanticHighlighting.cpp

-9
Original file line numberDiff line numberDiff line change
@@ -715,13 +715,6 @@ class CollectExtraHighlightings
715715
return true;
716716
}
717717

718-
bool VisitClassScopeFunctionSpecializationDecl(
719-
ClassScopeFunctionSpecializationDecl *D) {
720-
if (auto *Args = D->getTemplateArgsAsWritten())
721-
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
722-
return true;
723-
}
724-
725718
bool VisitDeclRefExpr(DeclRefExpr *E) {
726719
H.addAngleBracketTokens(E->getLAngleLoc(), E->getRAngleLoc());
727720
return true;
@@ -752,8 +745,6 @@ class CollectExtraHighlightings
752745
}
753746
if (auto *Args = D->getTemplateSpecializationArgsAsWritten())
754747
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
755-
if (auto *I = D->getDependentSpecializationInfo())
756-
H.addAngleBracketTokens(I->getLAngleLoc(), I->getRAngleLoc());
757748
return true;
758749
}
759750

clang/docs/ReleaseNotes.rst

+5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ C++ Specific Potentially Breaking Changes
7171
(`#49884 <https://github.com/llvm/llvm-project/issues/49884>`_), and
7272
(`#61273 <https://github.com/llvm/llvm-project/issues/61273>`_)
7373

74+
- The `ClassScopeFunctionSpecializationDecl` AST node has been removed. Dependent class scope
75+
explicit function template specializations now use `DependentFunctionTemplateSpecializationInfo`
76+
to store candidate primary templates and explicit template arguments. This should not impact users
77+
of Clang as a compiler, but it may break assumptions in Clang-based tools iterating over the AST.
78+
7479
ABI Changes in This Version
7580
---------------------------
7681
- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer

clang/include/clang/AST/ASTNodeTraverser.h

+5-6
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,12 @@ class ASTNodeTraverser
426426
}
427427

428428
void VisitFunctionDecl(const FunctionDecl *D) {
429-
if (const auto *FTSI = D->getTemplateSpecializationInfo())
429+
if (FunctionTemplateSpecializationInfo *FTSI =
430+
D->getTemplateSpecializationInfo())
430431
dumpTemplateArgumentList(*FTSI->TemplateArguments);
432+
else if (DependentFunctionTemplateSpecializationInfo *DFTSI =
433+
D->getDependentSpecializationInfo())
434+
dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten);
431435

432436
if (D->param_begin())
433437
for (const auto *Parameter : D->parameters())
@@ -578,11 +582,6 @@ class ASTNodeTraverser
578582
dumpTemplateParameters(D->getTemplateParameters());
579583
}
580584

581-
void VisitClassScopeFunctionSpecializationDecl(
582-
const ClassScopeFunctionSpecializationDecl *D) {
583-
Visit(D->getSpecialization());
584-
dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten());
585-
}
586585
void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); }
587586

588587
void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {

clang/include/clang/AST/Decl.h

+4-6
Original file line numberDiff line numberDiff line change
@@ -2845,9 +2845,7 @@ class FunctionDecl : public DeclaratorDecl,
28452845

28462846
/// Determine whether this function is a function template
28472847
/// specialization.
2848-
bool isFunctionTemplateSpecialization() const {
2849-
return getPrimaryTemplate() != nullptr;
2850-
}
2848+
bool isFunctionTemplateSpecialization() const;
28512849

28522850
/// If this function is actually a function template specialization,
28532851
/// retrieve information about this function template specialization.
@@ -2930,9 +2928,9 @@ class FunctionDecl : public DeclaratorDecl,
29302928

29312929
/// Specifies that this function declaration is actually a
29322930
/// dependent function template specialization.
2933-
void setDependentTemplateSpecialization(ASTContext &Context,
2934-
const UnresolvedSetImpl &Templates,
2935-
const TemplateArgumentListInfo &TemplateArgs);
2931+
void setDependentTemplateSpecialization(
2932+
ASTContext &Context, const UnresolvedSetImpl &Templates,
2933+
const TemplateArgumentListInfo *TemplateArgs);
29362934

29372935
DependentFunctionTemplateSpecializationInfo *
29382936
getDependentSpecializationInfo() const;

clang/include/clang/AST/DeclTemplate.h

+26-124
Original file line numberDiff line numberDiff line change
@@ -583,7 +583,7 @@ class FunctionTemplateSpecializationInfo final
583583
/// \code
584584
/// template<typename> struct A {
585585
/// template<typename> void f();
586-
/// template<> void f<int>(); // ClassScopeFunctionSpecializationDecl
586+
/// template<> void f<int>();
587587
/// };
588588
/// \endcode
589589
///
@@ -682,82 +682,48 @@ class MemberSpecializationInfo {
682682
/// Provides information about a dependent function-template
683683
/// specialization declaration.
684684
///
685-
/// Since explicit function template specialization and instantiation
686-
/// declarations can only appear in namespace scope, and you can only
687-
/// specialize a member of a fully-specialized class, the only way to
688-
/// get one of these is in a friend declaration like the following:
685+
/// This is used for function templates explicit specializations declared
686+
/// within class templates:
687+
///
688+
/// \code
689+
/// template<typename> struct A {
690+
/// template<typename> void f();
691+
/// template<> void f<int>(); // DependentFunctionTemplateSpecializationInfo
692+
/// };
693+
/// \endcode
694+
///
695+
/// As well as dependent friend declarations naming function template
696+
/// specializations declared within class templates:
689697
///
690698
/// \code
691699
/// template \<class T> void foo(T);
692700
/// template \<class T> class A {
693-
/// friend void foo<>(T);
701+
/// friend void foo<>(T); // DependentFunctionTemplateSpecializationInfo
694702
/// };
695703
/// \endcode
696704
class DependentFunctionTemplateSpecializationInfo final
697705
: private llvm::TrailingObjects<DependentFunctionTemplateSpecializationInfo,
698-
TemplateArgumentLoc,
699706
FunctionTemplateDecl *> {
700-
/// The number of potential template candidates.
701-
unsigned NumTemplates;
702-
703-
/// The number of template arguments.
704-
unsigned NumArgs;
705-
706-
/// The locations of the left and right angle brackets.
707-
SourceRange AngleLocs;
707+
friend TrailingObjects;
708708

709-
size_t numTrailingObjects(OverloadToken<TemplateArgumentLoc>) const {
710-
return NumArgs;
711-
}
712-
size_t numTrailingObjects(OverloadToken<FunctionTemplateDecl *>) const {
713-
return NumTemplates;
714-
}
709+
/// The number of candidates for the primary template.
710+
unsigned NumCandidates;
715711

716712
DependentFunctionTemplateSpecializationInfo(
717-
const UnresolvedSetImpl &Templates,
718-
const TemplateArgumentListInfo &TemplateArgs);
713+
const UnresolvedSetImpl &Candidates,
714+
const ASTTemplateArgumentListInfo *TemplateArgsWritten);
719715

720716
public:
721-
friend TrailingObjects;
717+
/// The template arguments as written in the sources, if provided.
718+
const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten;
722719

723720
static DependentFunctionTemplateSpecializationInfo *
724-
Create(ASTContext &Context, const UnresolvedSetImpl &Templates,
725-
const TemplateArgumentListInfo &TemplateArgs);
726-
727-
/// Returns the number of function templates that this might
728-
/// be a specialization of.
729-
unsigned getNumTemplates() const { return NumTemplates; }
721+
Create(ASTContext &Context, const UnresolvedSetImpl &Candidates,
722+
const TemplateArgumentListInfo *TemplateArgs);
730723

731-
/// Returns the i'th template candidate.
732-
FunctionTemplateDecl *getTemplate(unsigned I) const {
733-
assert(I < getNumTemplates() && "template index out of range");
734-
return getTrailingObjects<FunctionTemplateDecl *>()[I];
735-
}
736-
737-
/// Returns the explicit template arguments that were given.
738-
const TemplateArgumentLoc *getTemplateArgs() const {
739-
return getTrailingObjects<TemplateArgumentLoc>();
740-
}
741-
742-
/// Returns the number of explicit template arguments that were given.
743-
unsigned getNumTemplateArgs() const { return NumArgs; }
744-
745-
llvm::ArrayRef<TemplateArgumentLoc> arguments() const {
746-
return llvm::ArrayRef(getTemplateArgs(), getNumTemplateArgs());
747-
}
748-
749-
/// Returns the nth template argument.
750-
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
751-
assert(I < getNumTemplateArgs() && "template arg index out of range");
752-
return getTemplateArgs()[I];
753-
}
754-
755-
SourceLocation getLAngleLoc() const {
756-
return AngleLocs.getBegin();
757-
}
758-
759-
SourceLocation getRAngleLoc() const {
760-
return AngleLocs.getEnd();
724+
/// Returns the candidates for the primary function template.
725+
ArrayRef<FunctionTemplateDecl *> getCandidates() const {
726+
return {getTrailingObjects<FunctionTemplateDecl *>(), NumCandidates};
761727
}
762728
};
763729

@@ -2613,70 +2579,6 @@ class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
26132579
static bool classofKind(Kind K) { return K == TypeAliasTemplate; }
26142580
};
26152581

2616-
/// Declaration of a function specialization at template class scope.
2617-
///
2618-
/// For example:
2619-
/// \code
2620-
/// template <class T>
2621-
/// class A {
2622-
/// template <class U> void foo(U a) { }
2623-
/// template<> void foo(int a) { }
2624-
/// }
2625-
/// \endcode
2626-
///
2627-
/// "template<> foo(int a)" will be saved in Specialization as a normal
2628-
/// CXXMethodDecl. Then during an instantiation of class A, it will be
2629-
/// transformed into an actual function specialization.
2630-
///
2631-
/// FIXME: This is redundant; we could store the same information directly on
2632-
/// the CXXMethodDecl as a DependentFunctionTemplateSpecializationInfo.
2633-
class ClassScopeFunctionSpecializationDecl : public Decl {
2634-
CXXMethodDecl *Specialization;
2635-
const ASTTemplateArgumentListInfo *TemplateArgs;
2636-
2637-
ClassScopeFunctionSpecializationDecl(
2638-
DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
2639-
const ASTTemplateArgumentListInfo *TemplArgs)
2640-
: Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
2641-
Specialization(FD), TemplateArgs(TemplArgs) {}
2642-
2643-
ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
2644-
: Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
2645-
2646-
virtual void anchor();
2647-
2648-
public:
2649-
friend class ASTDeclReader;
2650-
friend class ASTDeclWriter;
2651-
2652-
CXXMethodDecl *getSpecialization() const { return Specialization; }
2653-
bool hasExplicitTemplateArgs() const { return TemplateArgs; }
2654-
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
2655-
return TemplateArgs;
2656-
}
2657-
2658-
static ClassScopeFunctionSpecializationDecl *
2659-
Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD,
2660-
bool HasExplicitTemplateArgs,
2661-
const TemplateArgumentListInfo &TemplateArgs) {
2662-
return new (C, DC) ClassScopeFunctionSpecializationDecl(
2663-
DC, Loc, FD,
2664-
HasExplicitTemplateArgs
2665-
? ASTTemplateArgumentListInfo::Create(C, TemplateArgs)
2666-
: nullptr);
2667-
}
2668-
2669-
static ClassScopeFunctionSpecializationDecl *
2670-
CreateDeserialized(ASTContext &Context, unsigned ID);
2671-
2672-
// Implement isa/cast/dyncast/etc.
2673-
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
2674-
2675-
static bool classofKind(Kind K) {
2676-
return K == Decl::ClassScopeFunctionSpecialization;
2677-
}
2678-
};
2679-
26802582
/// Represents a variable template specialization, which refers to
26812583
/// a variable template with a given set of template arguments.
26822584
///

clang/include/clang/AST/RecursiveASTVisitor.h

+7-10
Original file line numberDiff line numberDiff line change
@@ -1563,16 +1563,6 @@ DEF_TRAVERSE_DECL(FriendTemplateDecl, {
15631563
}
15641564
})
15651565

1566-
DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
1567-
TRY_TO(TraverseDecl(D->getSpecialization()));
1568-
1569-
if (D->hasExplicitTemplateArgs()) {
1570-
TRY_TO(TraverseTemplateArgumentLocsHelper(
1571-
D->getTemplateArgsAsWritten()->getTemplateArgs(),
1572-
D->getTemplateArgsAsWritten()->NumTemplateArgs));
1573-
}
1574-
})
1575-
15761566
DEF_TRAVERSE_DECL(LinkageSpecDecl, {})
15771567

15781568
DEF_TRAVERSE_DECL(ExportDecl, {})
@@ -2154,6 +2144,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
21542144
TALI->NumTemplateArgs));
21552145
}
21562146
}
2147+
} else if (const DependentFunctionTemplateSpecializationInfo *DFSI =
2148+
D->getDependentSpecializationInfo()) {
2149+
if (const ASTTemplateArgumentListInfo *TALI =
2150+
DFSI->TemplateArgumentsAsWritten) {
2151+
TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
2152+
TALI->NumTemplateArgs));
2153+
}
21572154
}
21582155

21592156
// Visit the function type itself, which can be either

clang/include/clang/Basic/DeclNodes.td

-1
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ def FriendTemplate : DeclNode<Decl>;
102102
def StaticAssert : DeclNode<Decl>;
103103
def Block : DeclNode<Decl, "blocks">, DeclContext;
104104
def Captured : DeclNode<Decl>, DeclContext;
105-
def ClassScopeFunctionSpecialization : DeclNode<Decl>;
106105
def Import : DeclNode<Decl>;
107106
def OMPThreadPrivate : DeclNode<Decl>;
108107
def OMPAllocate : DeclNode<Decl>;

clang/include/clang/Basic/DiagnosticSemaKinds.td

+4-4
Original file line numberDiff line numberDiff line change
@@ -5240,11 +5240,11 @@ def err_explicit_specialization_inconsistent_storage_class : Error<
52405240
"'%select{none|extern|static|__private_extern__|auto|register}0'">;
52415241
def err_dependent_function_template_spec_no_match : Error<
52425242
"no candidate function template was found for dependent"
5243-
" friend function template specialization">;
5243+
" %select{member|friend}0 function template specialization">;
52445244
def note_dependent_function_template_spec_discard_reason : Note<
5245-
"candidate ignored: %select{not a function template"
5246-
"|not a member of the enclosing namespace;"
5247-
" did you mean to explicitly qualify the specialization?}0">;
5245+
"candidate ignored: %select{not a function template|"
5246+
"not a member of the enclosing %select{class template|"
5247+
"namespace; did you mean to explicitly qualify the specialization?}1}0">;
52485248

52495249
// C++ class template specializations and out-of-line definitions
52505250
def err_template_spec_needs_header : Error<

clang/include/clang/Sema/Sema.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -8451,9 +8451,9 @@ class Sema final {
84518451
SourceLocation PrevPtOfInstantiation,
84528452
bool &SuppressNew);
84538453

8454-
bool CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD,
8455-
const TemplateArgumentListInfo &ExplicitTemplateArgs,
8456-
LookupResult &Previous);
8454+
bool CheckDependentFunctionTemplateSpecialization(
8455+
FunctionDecl *FD, const TemplateArgumentListInfo *ExplicitTemplateArgs,
8456+
LookupResult &Previous);
84578457

84588458
bool CheckFunctionTemplateSpecialization(
84598459
FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs,

clang/include/clang/Sema/Template.h

-2
Original file line numberDiff line numberDiff line change
@@ -630,8 +630,6 @@ enum class TemplateSubstitutionKind : char {
630630
// A few supplemental visitor functions.
631631
Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
632632
TemplateParameterList *TemplateParams,
633-
std::optional<const ASTTemplateArgumentListInfo *>
634-
ClassScopeSpecializationArgs = std::nullopt,
635633
RewriteKind RK = RewriteKind::None);
636634
Decl *VisitFunctionDecl(FunctionDecl *D,
637635
TemplateParameterList *TemplateParams,

clang/include/clang/Serialization/ASTBitCodes.h

-4
Original file line numberDiff line numberDiff line change
@@ -1475,10 +1475,6 @@ enum DeclCode {
14751475
/// template template parameter pack.
14761476
DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK,
14771477

1478-
/// A ClassScopeFunctionSpecializationDecl record a class scope
1479-
/// function specialization. (Microsoft extension).
1480-
DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION,
1481-
14821478
/// An ImportDecl recording a module import.
14831479
DECL_IMPORT,
14841480

clang/include/clang/Serialization/ASTRecordReader.h

+2
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ class ASTRecordReader
155155
/// Reads a TemplateArgumentLoc, advancing Idx.
156156
TemplateArgumentLoc readTemplateArgumentLoc();
157157

158+
void readTemplateArgumentListInfo(TemplateArgumentListInfo &Result);
159+
158160
const ASTTemplateArgumentListInfo*
159161
readASTTemplateArgumentListInfo();
160162

0 commit comments

Comments
 (0)