mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-15 20:51:35 +00:00
Keep track of the template arguments deduced when matching a class
template partial specialization. Then, use those template arguments when instantiating members of that class template partial specialization. Fixes PR4607. llvm-svn: 77925
This commit is contained in:
parent
bbb772ace9
commit
9dc8bd327f
@ -869,8 +869,23 @@ enum TemplateSpecializationKind {
|
||||
/// \endcode
|
||||
class ClassTemplateSpecializationDecl
|
||||
: public CXXRecordDecl, public llvm::FoldingSetNode {
|
||||
|
||||
/// \brief Structure that stores information about a class template
|
||||
/// specialization that was instantiated from a class template partial
|
||||
/// specialization.
|
||||
struct SpecializedPartialSpecialization {
|
||||
/// \brief The class template partial specialization from which this
|
||||
/// class template specialization was instantiated.
|
||||
ClassTemplatePartialSpecializationDecl *PartialSpecialization;
|
||||
|
||||
/// \brief The template argument list deduced for the class template
|
||||
/// partial specialization itself.
|
||||
TemplateArgumentList *TemplateArgs;
|
||||
};
|
||||
|
||||
/// \brief The template that this specialization specializes
|
||||
ClassTemplateDecl *SpecializedTemplate;
|
||||
llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
|
||||
SpecializedTemplate;
|
||||
|
||||
/// \brief The template arguments used to describe this specialization.
|
||||
TemplateArgumentList TemplateArgs;
|
||||
@ -893,11 +908,13 @@ public:
|
||||
TemplateArgumentListBuilder &Builder,
|
||||
ClassTemplateSpecializationDecl *PrevDecl);
|
||||
|
||||
/// \brief Retrieve the template that this specialization specializes.
|
||||
ClassTemplateDecl *getSpecializedTemplate() const {
|
||||
return SpecializedTemplate;
|
||||
}
|
||||
virtual void Destroy(ASTContext& C);
|
||||
|
||||
/// \brief Retrieve the template that this specialization specializes.
|
||||
ClassTemplateDecl *getSpecializedTemplate() const;
|
||||
|
||||
/// \brief Retrieve the template arguments of the class template
|
||||
/// specialization.
|
||||
const TemplateArgumentList &getTemplateArgs() const {
|
||||
return TemplateArgs;
|
||||
}
|
||||
@ -912,6 +929,56 @@ public:
|
||||
SpecializationKind = TSK;
|
||||
}
|
||||
|
||||
/// \brief If this class template specialization is an instantiation of
|
||||
/// a template (rather than an explicit specialization), return the
|
||||
/// class template or class template partial specialization from which it
|
||||
/// was instantiated.
|
||||
llvm::PointerUnion<ClassTemplateDecl *,
|
||||
ClassTemplatePartialSpecializationDecl *>
|
||||
getInstantiatedFrom() const {
|
||||
if (getSpecializationKind() != TSK_ImplicitInstantiation &&
|
||||
getSpecializationKind() != TSK_ExplicitInstantiation)
|
||||
return (ClassTemplateDecl*)0;
|
||||
|
||||
if (SpecializedPartialSpecialization *PartialSpec
|
||||
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
||||
return PartialSpec->PartialSpecialization;
|
||||
|
||||
return const_cast<ClassTemplateDecl*>(
|
||||
SpecializedTemplate.get<ClassTemplateDecl*>());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the set of template arguments that should be used
|
||||
/// to instantiate members of the class template or class template partial
|
||||
/// specialization from which this class template specialization was
|
||||
/// instantiated.
|
||||
///
|
||||
/// \returns For a class template specialization instantiated from the primary
|
||||
/// template, this function will return the same template arguments as
|
||||
/// getTemplateArgs(). For a class template specialization instantiated from
|
||||
/// a class template partial specialization, this function will return the
|
||||
/// deduced template arguments for the class template partial specialization
|
||||
/// itself.
|
||||
const TemplateArgumentList &getTemplateInstantiationArgs() const {
|
||||
if (SpecializedPartialSpecialization *PartialSpec
|
||||
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
||||
return *PartialSpec->TemplateArgs;
|
||||
|
||||
return getTemplateArgs();
|
||||
}
|
||||
|
||||
/// \brief Note that this class template specialization is actually an
|
||||
/// instantiation of the given class template partial specialization whose
|
||||
/// template arguments have been deduced.
|
||||
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
|
||||
TemplateArgumentList *TemplateArgs) {
|
||||
SpecializedPartialSpecialization *PS
|
||||
= new (getASTContext()) SpecializedPartialSpecialization();
|
||||
PS->PartialSpecialization = PartialSpec;
|
||||
PS->TemplateArgs = TemplateArgs;
|
||||
SpecializedTemplate = PS;
|
||||
}
|
||||
|
||||
/// \brief Sets the type of this specialization as it was written by
|
||||
/// the user. This will be a class template specialization type.
|
||||
void setTypeAsWritten(QualType T) {
|
||||
|
@ -415,6 +415,22 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context,
|
||||
return Result;
|
||||
}
|
||||
|
||||
void ClassTemplateSpecializationDecl::Destroy(ASTContext &C) {
|
||||
if (SpecializedPartialSpecialization *PartialSpec
|
||||
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
||||
C.Deallocate(PartialSpec);
|
||||
|
||||
CXXRecordDecl::Destroy(C);
|
||||
}
|
||||
|
||||
ClassTemplateDecl *
|
||||
ClassTemplateSpecializationDecl::getSpecializedTemplate() const {
|
||||
if (SpecializedPartialSpecialization *PartialSpec
|
||||
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
||||
return PartialSpec->PartialSpecialization->getSpecializedTemplate();
|
||||
return SpecializedTemplate.get<ClassTemplateDecl*>();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ClassTemplatePartialSpecializationDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -32,7 +32,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
|
||||
// Template arguments for a class template specialization.
|
||||
if (ClassTemplateSpecializationDecl *Spec
|
||||
= dyn_cast<ClassTemplateSpecializationDecl>(D))
|
||||
return Spec->getTemplateArgs();
|
||||
return Spec->getTemplateInstantiationArgs();
|
||||
|
||||
// Template arguments for a function template specialization.
|
||||
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D))
|
||||
@ -50,7 +50,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) {
|
||||
|
||||
ClassTemplateSpecializationDecl *EnclosingTemplate
|
||||
= cast<ClassTemplateSpecializationDecl>(EnclosingTemplateCtx);
|
||||
return EnclosingTemplate->getTemplateArgs();
|
||||
return EnclosingTemplate->getTemplateInstantiationArgs();
|
||||
}
|
||||
|
||||
Sema::InstantiatingTemplate::
|
||||
@ -1011,6 +1011,7 @@ Sema::InstantiateClassTemplateSpecialization(
|
||||
// instantiation is generated from that specialization.
|
||||
Pattern = Matched[0].first;
|
||||
TemplateArgs = Matched[0].second;
|
||||
ClassTemplateSpec->setInstantiationOf(Matched[0].first, Matched[0].second);
|
||||
} else if (Matched.size() > 1) {
|
||||
// -- If more than one matching specialization is found, the
|
||||
// partial order rules (14.5.4.2) are used to determine
|
||||
|
20
clang/test/SemaTemplate/partial-spec-instantiate.cpp
Normal file
20
clang/test/SemaTemplate/partial-spec-instantiate.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// RUN: clang-cc -fsyntax-only %s
|
||||
|
||||
// PR4607
|
||||
template <class T> struct X {};
|
||||
|
||||
template <> struct X<char>
|
||||
{
|
||||
static char* g();
|
||||
};
|
||||
|
||||
template <class T> struct X2 {};
|
||||
|
||||
template <class U>
|
||||
struct X2<U*> {
|
||||
static void f() {
|
||||
X<U>::g();
|
||||
}
|
||||
};
|
||||
|
||||
void a(char *a, char *b) {X2<char*>::f();}
|
Loading…
x
Reference in New Issue
Block a user