forked from OSchip/llvm-project
Reimplement RedeclarableTemplateDecl in terms of
Redeclarable<RedeclarableTemplateDecl>, eliminating a bunch of redeclaration-chain logic both in RedeclarableTemplateDecl and especially in its (de-)serialization. As part of this, eliminate the RedeclarableTemplate<> class template, which was an abstraction that didn't actually save anything. llvm-svn: 148181
This commit is contained in:
parent
f55694af01
commit
68444de354
|
@ -15,6 +15,7 @@
|
||||||
#define LLVM_CLANG_AST_DECLTEMPLATE_H
|
#define LLVM_CLANG_AST_DECLTEMPLATE_H
|
||||||
|
|
||||||
#include "clang/AST/DeclCXX.h"
|
#include "clang/AST/DeclCXX.h"
|
||||||
|
#include "clang/AST/Redeclarable.h"
|
||||||
#include "clang/AST/TemplateBase.h"
|
#include "clang/AST/TemplateBase.h"
|
||||||
#include "llvm/ADT/PointerUnion.h"
|
#include "llvm/ADT/PointerUnion.h"
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -478,23 +479,12 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Declaration of a redeclarable template.
|
/// Declaration of a redeclarable template.
|
||||||
class RedeclarableTemplateDecl : public TemplateDecl {
|
class RedeclarableTemplateDecl : public TemplateDecl,
|
||||||
|
public Redeclarable<RedeclarableTemplateDecl>
|
||||||
RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
|
{
|
||||||
return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
|
typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base;
|
||||||
}
|
virtual RedeclarableTemplateDecl *getNextRedeclaration() {
|
||||||
|
return RedeclLink.getNext();
|
||||||
RedeclarableTemplateDecl *getCanonicalDeclImpl();
|
|
||||||
|
|
||||||
void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
|
|
||||||
|
|
||||||
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
|
|
||||||
return getCommonPtr()->InstantiatedFromMember.getPointer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
|
|
||||||
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
|
|
||||||
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -564,15 +554,12 @@ protected:
|
||||||
/// was explicitly specialized.
|
/// was explicitly specialized.
|
||||||
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
|
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
|
||||||
InstantiatedFromMember;
|
InstantiatedFromMember;
|
||||||
|
|
||||||
/// \brief The latest declaration of this template.
|
|
||||||
RedeclarableTemplateDecl *Latest;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A pointer to the previous declaration (if this is a redeclaration)
|
/// \brief Pointer to the common data shared by all declarations of this
|
||||||
/// or to the data that is common to all declarations of this template.
|
/// template.
|
||||||
llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev;
|
CommonBase *Common;
|
||||||
|
|
||||||
/// \brief Retrieves the "common" pointer shared by all (re-)declarations of
|
/// \brief Retrieves the "common" pointer shared by all (re-)declarations of
|
||||||
/// the same template. Calling this routine may implicitly allocate memory
|
/// the same template. Calling this routine may implicitly allocate memory
|
||||||
/// for the common pointer.
|
/// for the common pointer.
|
||||||
|
@ -584,53 +571,15 @@ protected:
|
||||||
RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||||
DeclarationName Name, TemplateParameterList *Params,
|
DeclarationName Name, TemplateParameterList *Params,
|
||||||
NamedDecl *Decl)
|
NamedDecl *Decl)
|
||||||
: TemplateDecl(DK, DC, L, Name, Params, Decl),
|
: TemplateDecl(DK, DC, L, Name, Params, Decl), Common() { }
|
||||||
CommonOrPrev((CommonBase*)0) { }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <class decl_type> friend class RedeclarableTemplate;
|
template <class decl_type> friend class RedeclarableTemplate;
|
||||||
|
|
||||||
RedeclarableTemplateDecl *getCanonicalDecl() {
|
/// Retrieves the canonical declaration of this template.
|
||||||
return getCanonicalDeclImpl();
|
RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); }
|
||||||
}
|
const RedeclarableTemplateDecl *getCanonicalDecl() const {
|
||||||
|
return getFirstDeclaration();
|
||||||
/// \brief Retrieve the previous declaration of this template, or
|
|
||||||
/// NULL if no such declaration exists.
|
|
||||||
RedeclarableTemplateDecl *getPreviousDeclaration() {
|
|
||||||
return getPreviousDeclarationImpl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this template, or
|
|
||||||
/// NULL if no such declaration exists.
|
|
||||||
const RedeclarableTemplateDecl *getPreviousDeclaration() const {
|
|
||||||
return
|
|
||||||
const_cast<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the first declaration of this template, or itself
|
|
||||||
/// if this the first one.
|
|
||||||
RedeclarableTemplateDecl *getFirstDeclaration() {
|
|
||||||
return getCanonicalDecl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the first declaration of this template, or itself
|
|
||||||
/// if this the first one.
|
|
||||||
const RedeclarableTemplateDecl *getFirstDeclaration() const {
|
|
||||||
return
|
|
||||||
const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the most recent declaration of this template, or itself
|
|
||||||
/// if this the most recent one.
|
|
||||||
RedeclarableTemplateDecl *getMostRecentDeclaration() {
|
|
||||||
return getCommonPtr()->Latest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the most recent declaration of this template, or itself
|
|
||||||
/// if this the most recent one.
|
|
||||||
const RedeclarableTemplateDecl *getMostRecentDeclaration() const {
|
|
||||||
return
|
|
||||||
const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Determines whether this template was a specialization of a
|
/// \brief Determines whether this template was a specialization of a
|
||||||
|
@ -665,10 +614,21 @@ public:
|
||||||
/// \brief Retrieve the previous declaration of this template, or
|
/// \brief Retrieve the previous declaration of this template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
|
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||||
return getInstantiatedFromMemberTemplateImpl();
|
return getCommonPtr()->InstantiatedFromMember.getPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual RedeclarableTemplateDecl *getNextRedeclaration();
|
void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
|
||||||
|
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
|
||||||
|
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef redeclarable_base::redecl_iterator redecl_iterator;
|
||||||
|
redecl_iterator redecls_begin() const {
|
||||||
|
return redeclarable_base::redecls_begin();
|
||||||
|
}
|
||||||
|
redecl_iterator redecls_end() const {
|
||||||
|
return redeclarable_base::redecls_end();
|
||||||
|
}
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
||||||
|
@ -680,80 +640,11 @@ public:
|
||||||
return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
|
return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend class ASTReader;
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
friend class ASTDeclWriter;
|
friend class ASTDeclWriter;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class decl_type>
|
|
||||||
class RedeclarableTemplate {
|
|
||||||
RedeclarableTemplateDecl *thisDecl() {
|
|
||||||
return static_cast<decl_type*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
|
||||||
/// NULL if no such declaration exists.
|
|
||||||
decl_type *getPreviousDeclaration() {
|
|
||||||
return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
|
||||||
/// NULL if no such declaration exists.
|
|
||||||
const decl_type *getPreviousDeclaration() const {
|
|
||||||
return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Set the previous declaration of this function template.
|
|
||||||
void setPreviousDeclaration(decl_type *Prev) {
|
|
||||||
thisDecl()->setPreviousDeclarationImpl(Prev);
|
|
||||||
}
|
|
||||||
|
|
||||||
decl_type *getCanonicalDecl() {
|
|
||||||
return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl());
|
|
||||||
}
|
|
||||||
|
|
||||||
const decl_type *getCanonicalDecl() const {
|
|
||||||
return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the member template that this template was instantiated
|
|
||||||
/// from.
|
|
||||||
///
|
|
||||||
/// This routine will return non-NULL for member templates of
|
|
||||||
/// class templates. For example, given:
|
|
||||||
///
|
|
||||||
/// \code
|
|
||||||
/// template <typename T>
|
|
||||||
/// struct X {
|
|
||||||
/// template <typename U> void f();
|
|
||||||
/// template <typename U> struct A {};
|
|
||||||
/// };
|
|
||||||
/// \endcode
|
|
||||||
///
|
|
||||||
/// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a
|
|
||||||
/// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
|
|
||||||
/// return X<int>::f, a FunctionTemplateDecl (whose parent is again
|
|
||||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
|
||||||
/// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
|
|
||||||
/// ClassTemplateDecl).
|
|
||||||
///
|
|
||||||
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
|
|
||||||
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
|
|
||||||
/// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again
|
|
||||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
|
||||||
/// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD).
|
|
||||||
///
|
|
||||||
/// \returns NULL if this is not an instantiation of a member template.
|
|
||||||
decl_type *getInstantiatedFromMemberTemplate() {
|
|
||||||
return static_cast<decl_type*>(
|
|
||||||
thisDecl()->getInstantiatedFromMemberTemplateImpl());
|
|
||||||
}
|
|
||||||
|
|
||||||
void setInstantiatedFromMemberTemplate(decl_type *TD) {
|
|
||||||
thisDecl()->setInstantiatedFromMemberTemplateImpl(TD);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct RedeclarableTemplateDecl::
|
template <> struct RedeclarableTemplateDecl::
|
||||||
SpecEntryTraits<FunctionTemplateSpecializationInfo> {
|
SpecEntryTraits<FunctionTemplateSpecializationInfo> {
|
||||||
typedef FunctionDecl DeclType;
|
typedef FunctionDecl DeclType;
|
||||||
|
@ -765,13 +656,10 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Declaration of a template function.
|
/// Declaration of a template function.
|
||||||
class FunctionTemplateDecl : public RedeclarableTemplateDecl,
|
class FunctionTemplateDecl : public RedeclarableTemplateDecl {
|
||||||
public RedeclarableTemplate<FunctionTemplateDecl> {
|
|
||||||
static void DeallocateCommon(void *Ptr);
|
static void DeallocateCommon(void *Ptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base;
|
|
||||||
|
|
||||||
/// \brief Data that is common to all of the declarations of a given
|
/// \brief Data that is common to all of the declarations of a given
|
||||||
/// function template.
|
/// function template.
|
||||||
struct Common : CommonBase {
|
struct Common : CommonBase {
|
||||||
|
@ -834,26 +722,31 @@ public:
|
||||||
unsigned NumArgs, void *&InsertPos);
|
unsigned NumArgs, void *&InsertPos);
|
||||||
|
|
||||||
FunctionTemplateDecl *getCanonicalDecl() {
|
FunctionTemplateDecl *getCanonicalDecl() {
|
||||||
return redeclarable_base::getCanonicalDecl();
|
return cast<FunctionTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getCanonicalDecl());
|
||||||
}
|
}
|
||||||
const FunctionTemplateDecl *getCanonicalDecl() const {
|
const FunctionTemplateDecl *getCanonicalDecl() const {
|
||||||
return redeclarable_base::getCanonicalDecl();
|
return cast<FunctionTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getCanonicalDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
FunctionTemplateDecl *getPreviousDeclaration() {
|
FunctionTemplateDecl *getPreviousDeclaration() {
|
||||||
return redeclarable_base::getPreviousDeclaration();
|
return cast_or_null<FunctionTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getPreviousDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
const FunctionTemplateDecl *getPreviousDeclaration() const {
|
const FunctionTemplateDecl *getPreviousDeclaration() const {
|
||||||
return redeclarable_base::getPreviousDeclaration();
|
return cast_or_null<FunctionTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getPreviousDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
|
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||||
return redeclarable_base::getInstantiatedFromMemberTemplate();
|
return cast_or_null<FunctionTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
|
typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
|
||||||
|
@ -1745,13 +1638,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Declaration of a class template.
|
/// Declaration of a class template.
|
||||||
class ClassTemplateDecl : public RedeclarableTemplateDecl,
|
class ClassTemplateDecl : public RedeclarableTemplateDecl {
|
||||||
public RedeclarableTemplate<ClassTemplateDecl> {
|
|
||||||
static void DeallocateCommon(void *Ptr);
|
static void DeallocateCommon(void *Ptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
|
|
||||||
|
|
||||||
/// \brief Data that is common to all of the declarations of a given
|
/// \brief Data that is common to all of the declarations of a given
|
||||||
/// class template.
|
/// class template.
|
||||||
struct Common : CommonBase {
|
struct Common : CommonBase {
|
||||||
|
@ -1836,26 +1726,31 @@ public:
|
||||||
void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
|
void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
|
||||||
|
|
||||||
ClassTemplateDecl *getCanonicalDecl() {
|
ClassTemplateDecl *getCanonicalDecl() {
|
||||||
return redeclarable_base::getCanonicalDecl();
|
return cast<ClassTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getCanonicalDecl());
|
||||||
}
|
}
|
||||||
const ClassTemplateDecl *getCanonicalDecl() const {
|
const ClassTemplateDecl *getCanonicalDecl() const {
|
||||||
return redeclarable_base::getCanonicalDecl();
|
return cast<ClassTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getCanonicalDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this class template, or
|
/// \brief Retrieve the previous declaration of this class template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
ClassTemplateDecl *getPreviousDeclaration() {
|
ClassTemplateDecl *getPreviousDeclaration() {
|
||||||
return redeclarable_base::getPreviousDeclaration();
|
return cast_or_null<ClassTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getPreviousDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this class template, or
|
/// \brief Retrieve the previous declaration of this class template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
const ClassTemplateDecl *getPreviousDeclaration() const {
|
const ClassTemplateDecl *getPreviousDeclaration() const {
|
||||||
return redeclarable_base::getPreviousDeclaration();
|
return cast_or_null<ClassTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getPreviousDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
|
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||||
return redeclarable_base::getInstantiatedFromMemberTemplate();
|
return cast_or_null<ClassTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Return the partial specialization with the provided arguments if it
|
/// \brief Return the partial specialization with the provided arguments if it
|
||||||
|
@ -2041,13 +1936,10 @@ public:
|
||||||
/// Declaration of an alias template. For example:
|
/// Declaration of an alias template. For example:
|
||||||
///
|
///
|
||||||
/// template <typename T> using V = std::map<T*, int, MyCompare<T>>;
|
/// template <typename T> using V = std::map<T*, int, MyCompare<T>>;
|
||||||
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl,
|
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
|
||||||
public RedeclarableTemplate<TypeAliasTemplateDecl> {
|
|
||||||
static void DeallocateCommon(void *Ptr);
|
static void DeallocateCommon(void *Ptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef RedeclarableTemplate<TypeAliasTemplateDecl> redeclarable_base;
|
|
||||||
|
|
||||||
typedef CommonBase Common;
|
typedef CommonBase Common;
|
||||||
|
|
||||||
TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||||
|
@ -2068,26 +1960,31 @@ public:
|
||||||
|
|
||||||
|
|
||||||
TypeAliasTemplateDecl *getCanonicalDecl() {
|
TypeAliasTemplateDecl *getCanonicalDecl() {
|
||||||
return redeclarable_base::getCanonicalDecl();
|
return cast<TypeAliasTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getCanonicalDecl());
|
||||||
}
|
}
|
||||||
const TypeAliasTemplateDecl *getCanonicalDecl() const {
|
const TypeAliasTemplateDecl *getCanonicalDecl() const {
|
||||||
return redeclarable_base::getCanonicalDecl();
|
return cast<TypeAliasTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getCanonicalDecl());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
TypeAliasTemplateDecl *getPreviousDeclaration() {
|
TypeAliasTemplateDecl *getPreviousDeclaration() {
|
||||||
return redeclarable_base::getPreviousDeclaration();
|
return cast_or_null<TypeAliasTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getPreviousDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Retrieve the previous declaration of this function template, or
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
/// NULL if no such declaration exists.
|
/// NULL if no such declaration exists.
|
||||||
const TypeAliasTemplateDecl *getPreviousDeclaration() const {
|
const TypeAliasTemplateDecl *getPreviousDeclaration() const {
|
||||||
return redeclarable_base::getPreviousDeclaration();
|
return cast_or_null<TypeAliasTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getPreviousDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
|
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||||
return redeclarable_base::getInstantiatedFromMemberTemplate();
|
return cast_or_null<TypeAliasTemplateDecl>(
|
||||||
|
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -112,42 +112,30 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
|
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
|
||||||
// Find the first declaration of this function template.
|
if (!Common) {
|
||||||
RedeclarableTemplateDecl *First = getCanonicalDecl();
|
// Walk the previous-declaration chain until we either find a declaration
|
||||||
|
// with a common pointer or we run out of previous declarations.
|
||||||
|
llvm::SmallVector<RedeclarableTemplateDecl *, 2> PrevDecls;
|
||||||
|
for (RedeclarableTemplateDecl *Prev = getPreviousDeclaration(); Prev;
|
||||||
|
Prev = Prev->getPreviousDeclaration()) {
|
||||||
|
if (Prev->Common) {
|
||||||
|
Common = Prev->Common;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrevDecls.push_back(Prev);
|
||||||
|
}
|
||||||
|
|
||||||
if (First->CommonOrPrev.isNull()) {
|
// If we never found a common pointer, allocate one now.
|
||||||
CommonBase *CommonPtr = First->newCommon(getASTContext());
|
if (!Common)
|
||||||
First->CommonOrPrev = CommonPtr;
|
Common = newCommon(getASTContext());
|
||||||
CommonPtr->Latest = First;
|
|
||||||
|
// Update any previous declarations we saw with the common pointer.
|
||||||
|
for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I)
|
||||||
|
PrevDecls[I]->Common = Common;
|
||||||
}
|
}
|
||||||
return First->CommonOrPrev.get<CommonBase*>();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Common;
|
||||||
RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() {
|
|
||||||
RedeclarableTemplateDecl *Tmpl = this;
|
|
||||||
while (Tmpl->getPreviousDeclaration())
|
|
||||||
Tmpl = Tmpl->getPreviousDeclaration();
|
|
||||||
return Tmpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RedeclarableTemplateDecl::setPreviousDeclarationImpl(
|
|
||||||
RedeclarableTemplateDecl *Prev) {
|
|
||||||
if (Prev) {
|
|
||||||
CommonBase *Common = Prev->getCommonPtr();
|
|
||||||
Prev = Common->Latest;
|
|
||||||
Common->Latest = this;
|
|
||||||
CommonOrPrev = Prev;
|
|
||||||
} else {
|
|
||||||
assert(CommonOrPrev.is<CommonBase*>() && "Cannot reset TemplateDecl Prev");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() {
|
|
||||||
if (CommonOrPrev.is<RedeclarableTemplateDecl*>())
|
|
||||||
return CommonOrPrev.get<RedeclarableTemplateDecl*>();
|
|
||||||
CommonBase *Common = CommonOrPrev.get<CommonBase*>();
|
|
||||||
return Common ? Common->Latest : this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class EntryType>
|
template <class EntryType>
|
||||||
|
|
|
@ -6152,10 +6152,10 @@ void ASTReader::finishPendingActions() {
|
||||||
PendingChainedObjCCategories.clear();
|
PendingChainedObjCCategories.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we deserialized any C++ or Objective-C class definitions or any
|
// If we deserialized any C++ or Objective-C class definitions, any
|
||||||
// Objective-C protocol definitions, make sure that all redeclarations point
|
// Objective-C protocol definitions, or any redeclarable templates, make sure
|
||||||
// to the definitions. Note that this can only happen now, after the
|
// that all redeclarations point to the definitions. Note that this can only
|
||||||
// redeclaration chains have been fully wired.
|
// happen now, after the redeclaration chains have been fully wired.
|
||||||
for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
|
for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
|
||||||
DEnd = PendingDefinitions.end();
|
DEnd = PendingDefinitions.end();
|
||||||
D != DEnd; ++D) {
|
D != DEnd; ++D) {
|
||||||
|
@ -6177,11 +6177,21 @@ void ASTReader::finishPendingActions() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(*D);
|
if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
|
||||||
for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
|
for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
|
||||||
REnd = PD->redecls_end();
|
REnd = PD->redecls_end();
|
||||||
|
R != REnd; ++R)
|
||||||
|
R->Data = PD->Data;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RedeclarableTemplateDecl *RTD
|
||||||
|
= cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
|
||||||
|
for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
|
||||||
|
REnd = RTD->redecls_end();
|
||||||
R != REnd; ++R)
|
R != REnd; ++R)
|
||||||
R->Data = PD->Data;
|
R->Common = RTD->Common;
|
||||||
}
|
}
|
||||||
PendingDefinitions.clear();
|
PendingDefinitions.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1234,72 +1234,40 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
||||||
|
|
||||||
ASTDeclReader::RedeclarableResult
|
ASTDeclReader::RedeclarableResult
|
||||||
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
|
RedeclarableResult Redecl = VisitRedeclarable(D);
|
||||||
// can be used while this is still initializing.
|
|
||||||
enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
|
|
||||||
RedeclKind Kind = (RedeclKind)Record[Idx++];
|
|
||||||
|
|
||||||
// Determine the first declaration ID.
|
|
||||||
DeclID FirstDeclID = 0;
|
|
||||||
switch (Kind) {
|
|
||||||
case FirstDeclaration: {
|
|
||||||
FirstDeclID = ThisDeclID;
|
|
||||||
|
|
||||||
// Since this is the first declaration of the template, fill in the
|
// Make sure we've allocated the Common pointer first. We do this before
|
||||||
// information for the 'common' pointer.
|
// VisitTemplateDecl so that getCommonPtr() can be used during initialization.
|
||||||
if (D->CommonOrPrev.isNull()) {
|
RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
|
||||||
RedeclarableTemplateDecl::CommonBase *Common
|
if (!CanonD->Common) {
|
||||||
= D->newCommon(Reader.getContext());
|
CanonD->Common = CanonD->newCommon(Reader.getContext());
|
||||||
Common->Latest = D;
|
Reader.PendingDefinitions.insert(CanonD);
|
||||||
D->CommonOrPrev = Common;
|
}
|
||||||
}
|
D->Common = CanonD->Common;
|
||||||
|
|
||||||
|
// If this is the first declaration of the template, fill in the information
|
||||||
|
// for the 'common' pointer.
|
||||||
|
if (ThisDeclID == Redecl.getFirstID()) {
|
||||||
if (RedeclarableTemplateDecl *RTD
|
if (RedeclarableTemplateDecl *RTD
|
||||||
= ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
|
= ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
|
||||||
assert(RTD->getKind() == D->getKind() &&
|
assert(RTD->getKind() == D->getKind() &&
|
||||||
"InstantiatedFromMemberTemplate kind mismatch");
|
"InstantiatedFromMemberTemplate kind mismatch");
|
||||||
D->setInstantiatedFromMemberTemplateImpl(RTD);
|
D->setInstantiatedFromMemberTemplate(RTD);
|
||||||
if (Record[Idx++])
|
if (Record[Idx++])
|
||||||
D->setMemberSpecialization();
|
D->setMemberSpecialization();
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case FirstInFile:
|
|
||||||
case PointsToPrevious: {
|
|
||||||
FirstDeclID = ReadDeclID(Record, Idx);
|
|
||||||
DeclID PrevDeclID = ReadDeclID(Record, Idx);
|
|
||||||
|
|
||||||
RedeclarableTemplateDecl *FirstDecl
|
|
||||||
= cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(FirstDeclID));
|
|
||||||
|
|
||||||
// We delay loading of the redeclaration chain to avoid deeply nested calls.
|
|
||||||
// We temporarily set the first (canonical) declaration as the previous one
|
|
||||||
// which is the one that matters and mark the real previous DeclID to be
|
|
||||||
// loaded and attached later on.
|
|
||||||
D->CommonOrPrev = FirstDecl;
|
|
||||||
|
|
||||||
if (Kind == PointsToPrevious) {
|
|
||||||
// Make a note that we need to wire up this declaration to its
|
|
||||||
// previous declaration, later. We don't need to do this for the first
|
|
||||||
// declaration in any given module file, because those will be wired
|
|
||||||
// together later.
|
|
||||||
Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VisitTemplateDecl(D);
|
VisitTemplateDecl(D);
|
||||||
D->IdentifierNamespace = Record[Idx++];
|
D->IdentifierNamespace = Record[Idx++];
|
||||||
|
|
||||||
return RedeclarableResult(Reader, FirstDeclID);
|
return Redecl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||||
VisitRedeclarableTemplateDecl(D);
|
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
||||||
|
|
||||||
if (D->getPreviousDeclaration() == 0) {
|
if (ThisDeclID == Redecl.getFirstID()) {
|
||||||
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
|
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
|
||||||
// the specializations.
|
// the specializations.
|
||||||
SmallVector<serialization::DeclID, 2> SpecIDs;
|
SmallVector<serialization::DeclID, 2> SpecIDs;
|
||||||
|
@ -1321,6 +1289,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||||
typedef serialization::DeclID DeclID;
|
typedef serialization::DeclID DeclID;
|
||||||
|
|
||||||
ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
|
ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
|
||||||
|
// FIXME: Append specializations!
|
||||||
CommonPtr->LazySpecializations
|
CommonPtr->LazySpecializations
|
||||||
= new (Reader.getContext()) DeclID [SpecIDs.size()];
|
= new (Reader.getContext()) DeclID [SpecIDs.size()];
|
||||||
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
|
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
|
||||||
|
@ -1415,9 +1384,9 @@ void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||||
VisitRedeclarableTemplateDecl(D);
|
RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
|
||||||
|
|
||||||
if (D->getPreviousDeclaration() == 0) {
|
if (ThisDeclID == Redecl.getFirstID()) {
|
||||||
// This FunctionTemplateDecl owns a CommonPtr; read it.
|
// This FunctionTemplateDecl owns a CommonPtr; read it.
|
||||||
|
|
||||||
// Read the function specialization declarations.
|
// Read the function specialization declarations.
|
||||||
|
@ -1808,7 +1777,7 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
|
||||||
ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous));
|
ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous));
|
||||||
} else {
|
} else {
|
||||||
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
|
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
|
||||||
TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous);
|
TD->RedeclLink.setPointer(cast<RedeclarableTemplateDecl>(previous));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1841,7 +1810,9 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
|
||||||
cast<NamespaceDecl>(Latest));
|
cast<NamespaceDecl>(Latest));
|
||||||
} else {
|
} else {
|
||||||
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
|
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
|
||||||
TD->getCommonPtr()->Latest = cast<RedeclarableTemplateDecl>(Latest);
|
TD->RedeclLink
|
||||||
|
= Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
|
||||||
|
cast<RedeclarableTemplateDecl>(Latest));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1031,38 +1031,17 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
|
VisitRedeclarable(D);
|
||||||
|
|
||||||
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
|
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
|
||||||
// getCommonPtr() can be used while this is still initializing.
|
// getCommonPtr() can be used while this is still initializing.
|
||||||
enum { FirstDeclaration, FirstInFile, PointsToPrevious };
|
if (D->isFirstDeclaration()) {
|
||||||
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
|
|
||||||
RedeclarableTemplateDecl *First = 0;
|
|
||||||
if (!Prev) {
|
|
||||||
Record.push_back(FirstDeclaration);
|
|
||||||
|
|
||||||
// This declaration owns the 'common' pointer, so serialize that data now.
|
// This declaration owns the 'common' pointer, so serialize that data now.
|
||||||
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
||||||
if (D->getInstantiatedFromMemberTemplate())
|
if (D->getInstantiatedFromMemberTemplate())
|
||||||
Record.push_back(D->isMemberSpecialization());
|
Record.push_back(D->isMemberSpecialization());
|
||||||
} else {
|
|
||||||
First = D->getFirstDeclaration();
|
|
||||||
Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
|
|
||||||
Writer.AddDeclRef(First, Record);
|
|
||||||
Writer.AddDeclRef(Prev, Record);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (D->getMostRecentDeclaration() != D && (!Prev || Prev->isFromASTFile())) {
|
|
||||||
if (!First)
|
|
||||||
First = D->getFirstDeclaration();
|
|
||||||
|
|
||||||
// Capture the set of redeclarations in this file.
|
|
||||||
LocalRedeclarationsInfo LocalInfo = {
|
|
||||||
Writer.GetDeclRef(First),
|
|
||||||
Writer.GetDeclRef(D),
|
|
||||||
Writer.GetDeclRef(D->getMostRecentDeclaration())
|
|
||||||
};
|
|
||||||
Writer.LocalRedeclarations.push_back(LocalInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
VisitTemplateDecl(D);
|
VisitTemplateDecl(D);
|
||||||
Record.push_back(D->getIdentifierNamespace());
|
Record.push_back(D->getIdentifierNamespace());
|
||||||
}
|
}
|
||||||
|
@ -1070,7 +1049,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||||
void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||||
VisitRedeclarableTemplateDecl(D);
|
VisitRedeclarableTemplateDecl(D);
|
||||||
|
|
||||||
if (D->getPreviousDeclaration() == 0) {
|
if (D->isFirstDeclaration()) {
|
||||||
typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
|
typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
|
||||||
CTSDSetTy &CTSDSet = D->getSpecializations();
|
CTSDSetTy &CTSDSet = D->getSpecializations();
|
||||||
Record.push_back(CTSDSet.size());
|
Record.push_back(CTSDSet.size());
|
||||||
|
@ -1158,7 +1137,7 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
|
||||||
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||||
VisitRedeclarableTemplateDecl(D);
|
VisitRedeclarableTemplateDecl(D);
|
||||||
|
|
||||||
if (D->getPreviousDeclaration() == 0) {
|
if (D->isFirstDeclaration()) {
|
||||||
// This FunctionTemplateDecl owns the CommonPtr; write it.
|
// This FunctionTemplateDecl owns the CommonPtr; write it.
|
||||||
|
|
||||||
// Write the function specialization declarations.
|
// Write the function specialization declarations.
|
||||||
|
|
Loading…
Reference in New Issue