Skip to content

[clang] remove ClassScopeFunctionSpecializationDecl #66636

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions clang-tools-extra/clang-tidy/modernize/UseEmplaceCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()->isFunctionTemplateSpecialization())
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();
}
Expand Down
9 changes: 0 additions & 9 deletions clang-tools-extra/clangd/SemanticHighlighting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
5 changes: 5 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ C++ Specific Potentially Breaking Changes
(`#49884 <https://github.com/llvm/llvm-project/issues/49884>`_), and
(`#61273 <https://github.com/llvm/llvm-project/issues/61273>`_)

- The `ClassScopeFunctionSpecializationDecl` AST node has been removed. Dependent class scope
explicit function template specializations now use `DependentFunctionTemplateSpecializationInfo`
to store candidate primary templates and explicit template arguments. This should not impact users
of Clang as a compiler, but it may break assumptions in Clang-based tools iterating over the AST.

ABI Changes in This Version
---------------------------
- Following the SystemV ABI for x86-64, ``__int128`` arguments will no longer
Expand Down
11 changes: 5 additions & 6 deletions clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,12 @@ class ASTNodeTraverser
}

void VisitFunctionDecl(const FunctionDecl *D) {
if (const auto *FTSI = D->getTemplateSpecializationInfo())
if (FunctionTemplateSpecializationInfo *FTSI =
D->getTemplateSpecializationInfo())
dumpTemplateArgumentList(*FTSI->TemplateArguments);
else if (DependentFunctionTemplateSpecializationInfo *DFTSI =
D->getDependentSpecializationInfo())
dumpASTTemplateArgumentListInfo(DFTSI->TemplateArgumentsAsWritten);

if (D->param_begin())
for (const auto *Parameter : D->parameters())
Expand Down Expand Up @@ -578,11 +582,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) {
Expand Down
10 changes: 4 additions & 6 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2845,9 +2845,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.
Expand Down Expand Up @@ -2930,9 +2928,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;
Expand Down
150 changes: 26 additions & 124 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down Expand Up @@ -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};
}
};

Expand Down Expand Up @@ -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.
///
Expand Down
17 changes: 7 additions & 10 deletions clang/include/clang/AST/RecursiveASTVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, {})
Expand Down Expand Up @@ -2154,6 +2144,13 @@ bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
TALI->NumTemplateArgs));
}
}
} 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
Expand Down
1 change: 0 additions & 1 deletion clang/include/clang/Basic/DeclNodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5240,11 +5240,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<
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8451,9 +8451,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,
Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Sema/Template.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 0 additions & 4 deletions clang/include/clang/Serialization/ASTBitCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1475,10 +1475,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,

Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Serialization/ASTRecordReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ class ASTRecordReader
/// Reads a TemplateArgumentLoc, advancing Idx.
TemplateArgumentLoc readTemplateArgumentLoc();

void readTemplateArgumentListInfo(TemplateArgumentListInfo &Result);

const ASTTemplateArgumentListInfo*
readASTTemplateArgumentListInfo();

Expand Down
Loading