Keep track of function template specializations, to eliminate
redundant, implicit instantiations of function templates and provide a place where we can hang function template specializations. llvm-svn: 74454
This commit is contained in:
parent
10de9e6602
commit
8f5d4423ca
|
@ -809,9 +809,7 @@ public:
|
||||||
return PreviousDeclaration;
|
return PreviousDeclaration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPreviousDeclaration(FunctionDecl * PrevDecl) {
|
void setPreviousDeclaration(FunctionDecl * PrevDecl);
|
||||||
PreviousDeclaration = PrevDecl;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned getBuiltinID(ASTContext &Context) const;
|
unsigned getBuiltinID(ASTContext &Context) const;
|
||||||
|
|
||||||
|
@ -961,7 +959,8 @@ public:
|
||||||
/// function template specialization from the template.
|
/// function template specialization from the template.
|
||||||
void setFunctionTemplateSpecialization(ASTContext &Context,
|
void setFunctionTemplateSpecialization(ASTContext &Context,
|
||||||
FunctionTemplateDecl *Template,
|
FunctionTemplateDecl *Template,
|
||||||
const TemplateArgumentList *TemplateArgs);
|
const TemplateArgumentList *TemplateArgs,
|
||||||
|
void *InsertPos);
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) {
|
static bool classof(const Decl *D) {
|
||||||
|
|
|
@ -100,6 +100,352 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief Represents a template argument within a class template
|
||||||
|
/// specialization.
|
||||||
|
class TemplateArgument {
|
||||||
|
union {
|
||||||
|
uintptr_t TypeOrValue;
|
||||||
|
struct {
|
||||||
|
char Value[sizeof(llvm::APSInt)];
|
||||||
|
void *Type;
|
||||||
|
} Integer;
|
||||||
|
struct {
|
||||||
|
TemplateArgument *Args;
|
||||||
|
unsigned NumArgs;
|
||||||
|
bool CopyArgs;
|
||||||
|
} Args;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Location of the beginning of this template argument.
|
||||||
|
SourceLocation StartLoc;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \brief The type of template argument we're storing.
|
||||||
|
enum ArgKind {
|
||||||
|
Null = 0,
|
||||||
|
/// The template argument is a type. Its value is stored in the
|
||||||
|
/// TypeOrValue field.
|
||||||
|
Type = 1,
|
||||||
|
/// The template argument is a declaration
|
||||||
|
Declaration = 2,
|
||||||
|
/// The template argument is an integral value stored in an llvm::APSInt.
|
||||||
|
Integral = 3,
|
||||||
|
/// The template argument is a value- or type-dependent expression
|
||||||
|
/// stored in an Expr*.
|
||||||
|
Expression = 4,
|
||||||
|
|
||||||
|
/// The template argument is actually a parameter pack. Arguments are stored
|
||||||
|
/// in the Args struct.
|
||||||
|
Pack = 5
|
||||||
|
} Kind;
|
||||||
|
|
||||||
|
/// \brief Construct an empty, invalid template argument.
|
||||||
|
TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
|
||||||
|
|
||||||
|
/// \brief Construct a template type argument.
|
||||||
|
TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
|
||||||
|
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
||||||
|
StartLoc = Loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Construct a template argument that refers to a
|
||||||
|
/// declaration, which is either an external declaration or a
|
||||||
|
/// template declaration.
|
||||||
|
TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
|
||||||
|
// FIXME: Need to be sure we have the "canonical" declaration!
|
||||||
|
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
||||||
|
StartLoc = Loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Construct an integral constant template argument.
|
||||||
|
TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
|
||||||
|
QualType Type)
|
||||||
|
: Kind(Integral) {
|
||||||
|
new (Integer.Value) llvm::APSInt(Value);
|
||||||
|
Integer.Type = Type.getAsOpaquePtr();
|
||||||
|
StartLoc = Loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Construct a template argument that is an expression.
|
||||||
|
///
|
||||||
|
/// This form of template argument only occurs in template argument
|
||||||
|
/// lists used for dependent types and for expression; it will not
|
||||||
|
/// occur in a non-dependent, canonical template argument list.
|
||||||
|
TemplateArgument(Expr *E);
|
||||||
|
|
||||||
|
/// \brief Copy constructor for a template argument.
|
||||||
|
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
||||||
|
if (Kind == Integral) {
|
||||||
|
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||||
|
Integer.Type = Other.Integer.Type;
|
||||||
|
} else if (Kind == Pack) {
|
||||||
|
Args.NumArgs = Other.Args.NumArgs;
|
||||||
|
Args.Args = new TemplateArgument[Args.NumArgs];
|
||||||
|
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||||
|
Args.Args[I] = Other.Args.Args[I];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
TypeOrValue = Other.TypeOrValue;
|
||||||
|
StartLoc = Other.StartLoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemplateArgument& operator=(const TemplateArgument& Other) {
|
||||||
|
// FIXME: Does not provide the strong guarantee for exception
|
||||||
|
// safety.
|
||||||
|
using llvm::APSInt;
|
||||||
|
|
||||||
|
// FIXME: Handle Packs
|
||||||
|
assert(Kind != Pack && "FIXME: Handle packs");
|
||||||
|
assert(Other.Kind != Pack && "FIXME: Handle packs");
|
||||||
|
|
||||||
|
if (Kind == Other.Kind && Kind == Integral) {
|
||||||
|
// Copy integral values.
|
||||||
|
*this->getAsIntegral() = *Other.getAsIntegral();
|
||||||
|
Integer.Type = Other.Integer.Type;
|
||||||
|
} else {
|
||||||
|
// Destroy the current integral value, if that's what we're holding.
|
||||||
|
if (Kind == Integral)
|
||||||
|
getAsIntegral()->~APSInt();
|
||||||
|
|
||||||
|
Kind = Other.Kind;
|
||||||
|
|
||||||
|
if (Other.Kind == Integral) {
|
||||||
|
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
||||||
|
Integer.Type = Other.Integer.Type;
|
||||||
|
} else
|
||||||
|
TypeOrValue = Other.TypeOrValue;
|
||||||
|
}
|
||||||
|
StartLoc = Other.StartLoc;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~TemplateArgument() {
|
||||||
|
using llvm::APSInt;
|
||||||
|
|
||||||
|
if (Kind == Integral)
|
||||||
|
getAsIntegral()->~APSInt();
|
||||||
|
else if (Kind == Pack && Args.CopyArgs)
|
||||||
|
delete[] Args.Args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Return the kind of stored template argument.
|
||||||
|
ArgKind getKind() const { return Kind; }
|
||||||
|
|
||||||
|
/// \brief Determine whether this template argument has no value.
|
||||||
|
bool isNull() const { return Kind == Null; }
|
||||||
|
|
||||||
|
/// \brief Retrieve the template argument as a type.
|
||||||
|
QualType getAsType() const {
|
||||||
|
if (Kind != Type)
|
||||||
|
return QualType();
|
||||||
|
|
||||||
|
return QualType::getFromOpaquePtr(
|
||||||
|
reinterpret_cast<void*>(TypeOrValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the template argument as a declaration.
|
||||||
|
Decl *getAsDecl() const {
|
||||||
|
if (Kind != Declaration)
|
||||||
|
return 0;
|
||||||
|
return reinterpret_cast<Decl *>(TypeOrValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the template argument as an integral value.
|
||||||
|
llvm::APSInt *getAsIntegral() {
|
||||||
|
if (Kind != Integral)
|
||||||
|
return 0;
|
||||||
|
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm::APSInt *getAsIntegral() const {
|
||||||
|
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the type of the integral value.
|
||||||
|
QualType getIntegralType() const {
|
||||||
|
if (Kind != Integral)
|
||||||
|
return QualType();
|
||||||
|
|
||||||
|
return QualType::getFromOpaquePtr(Integer.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setIntegralType(QualType T) {
|
||||||
|
assert(Kind == Integral &&
|
||||||
|
"Cannot set the integral type of a non-integral template argument");
|
||||||
|
Integer.Type = T.getAsOpaquePtr();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief Retrieve the template argument as an expression.
|
||||||
|
Expr *getAsExpr() const {
|
||||||
|
if (Kind != Expression)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return reinterpret_cast<Expr *>(TypeOrValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Iterator that traverses the elements of a template argument pack.
|
||||||
|
typedef const TemplateArgument * pack_iterator;
|
||||||
|
|
||||||
|
/// \brief Iterator referencing the first argument of a template argument
|
||||||
|
/// pack.
|
||||||
|
pack_iterator pack_begin() const {
|
||||||
|
assert(Kind == Pack);
|
||||||
|
return Args.Args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Iterator referencing one past the last argument of a template
|
||||||
|
/// argument pack.
|
||||||
|
pack_iterator pack_end() const {
|
||||||
|
assert(Kind == Pack);
|
||||||
|
return Args.Args + Args.NumArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief The number of template arguments in the given template argument
|
||||||
|
/// pack.
|
||||||
|
unsigned pack_size() const {
|
||||||
|
assert(Kind == Pack);
|
||||||
|
return Args.NumArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the location where the template argument starts.
|
||||||
|
SourceLocation getLocation() const { return StartLoc; }
|
||||||
|
|
||||||
|
/// \brief Construct a template argument pack.
|
||||||
|
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
|
||||||
|
|
||||||
|
/// \brief Used to insert TemplateArguments into FoldingSets.
|
||||||
|
void Profile(llvm::FoldingSetNodeID &ID) const {
|
||||||
|
ID.AddInteger(Kind);
|
||||||
|
switch (Kind) {
|
||||||
|
case Null:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Type:
|
||||||
|
getAsType().Profile(ID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Declaration:
|
||||||
|
ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Integral:
|
||||||
|
getAsIntegral()->Profile(ID);
|
||||||
|
getIntegralType().Profile(ID);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Expression:
|
||||||
|
// FIXME: We need a canonical representation of expressions.
|
||||||
|
ID.AddPointer(getAsExpr());
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Pack:
|
||||||
|
ID.AddInteger(Args.NumArgs);
|
||||||
|
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
||||||
|
Args.Args[I].Profile(ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief A helper class for making template argument lists.
|
||||||
|
class TemplateArgumentListBuilder {
|
||||||
|
TemplateArgument *StructuredArgs;
|
||||||
|
unsigned MaxStructuredArgs;
|
||||||
|
unsigned NumStructuredArgs;
|
||||||
|
|
||||||
|
TemplateArgument *FlatArgs;
|
||||||
|
unsigned MaxFlatArgs;
|
||||||
|
unsigned NumFlatArgs;
|
||||||
|
|
||||||
|
bool AddingToPack;
|
||||||
|
unsigned PackBeginIndex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
|
||||||
|
unsigned NumTemplateArgs)
|
||||||
|
: StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
|
||||||
|
NumStructuredArgs(0), FlatArgs(0),
|
||||||
|
MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
|
||||||
|
AddingToPack(false), PackBeginIndex(0) { }
|
||||||
|
|
||||||
|
void Append(const TemplateArgument& Arg);
|
||||||
|
void BeginPack();
|
||||||
|
void EndPack();
|
||||||
|
|
||||||
|
void ReleaseArgs();
|
||||||
|
|
||||||
|
unsigned flatSize() const {
|
||||||
|
return NumFlatArgs;
|
||||||
|
}
|
||||||
|
const TemplateArgument *getFlatArguments() const {
|
||||||
|
return FlatArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned structuredSize() const {
|
||||||
|
// If we don't have any structured args, just reuse the flat size.
|
||||||
|
if (!StructuredArgs)
|
||||||
|
return flatSize();
|
||||||
|
|
||||||
|
return NumStructuredArgs;
|
||||||
|
}
|
||||||
|
const TemplateArgument *getStructuredArguments() const {
|
||||||
|
// If we don't have any structured args, just reuse the flat args.
|
||||||
|
if (!StructuredArgs)
|
||||||
|
return getFlatArguments();
|
||||||
|
|
||||||
|
return StructuredArgs;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \brief A template argument list.
|
||||||
|
///
|
||||||
|
/// FIXME: In the future, this class will be extended to support
|
||||||
|
/// variadic templates and member templates, which will make some of
|
||||||
|
/// the function names below make more sense.
|
||||||
|
class TemplateArgumentList {
|
||||||
|
/// \brief The template argument list.
|
||||||
|
///
|
||||||
|
/// The integer value will be non-zero to indicate that this
|
||||||
|
/// template argument list does not own the pointer.
|
||||||
|
llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
|
||||||
|
|
||||||
|
/// \brief The number of template arguments in this template
|
||||||
|
/// argument list.
|
||||||
|
unsigned NumFlatArguments;
|
||||||
|
|
||||||
|
llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
|
||||||
|
unsigned NumStructuredArguments;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TemplateArgumentList(ASTContext &Context,
|
||||||
|
TemplateArgumentListBuilder &Builder,
|
||||||
|
bool TakeArgs);
|
||||||
|
|
||||||
|
~TemplateArgumentList();
|
||||||
|
|
||||||
|
/// \brief Retrieve the template argument at a given index.
|
||||||
|
const TemplateArgument &get(unsigned Idx) const {
|
||||||
|
assert(Idx < NumFlatArguments && "Invalid template argument index");
|
||||||
|
return getFlatArgumentList()[Idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the template argument at a given index.
|
||||||
|
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
|
||||||
|
|
||||||
|
/// \brief Retrieve the number of template arguments in this
|
||||||
|
/// template argument list.
|
||||||
|
unsigned size() const { return NumFlatArguments; }
|
||||||
|
|
||||||
|
/// \brief Retrieve the number of template arguments in the
|
||||||
|
/// flattened template argument list.
|
||||||
|
unsigned flat_size() const { return NumFlatArguments; }
|
||||||
|
|
||||||
|
/// \brief Retrieve the flattened template argument list.
|
||||||
|
const TemplateArgument *getFlatArgumentList() const {
|
||||||
|
return FlatArguments.getPointer();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Kinds of Templates
|
// Kinds of Templates
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -157,40 +503,92 @@ protected:
|
||||||
/// \brief Provides information about a function template specialization,
|
/// \brief Provides information about a function template specialization,
|
||||||
/// which is a FunctionDecl that has been explicitly specialization or
|
/// which is a FunctionDecl that has been explicitly specialization or
|
||||||
/// instantiated from a function template.
|
/// instantiated from a function template.
|
||||||
class FunctionTemplateSpecializationInfo {
|
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
|
||||||
public:
|
public:
|
||||||
|
/// \brief The function template specialization that this structure
|
||||||
|
/// describes.
|
||||||
|
FunctionDecl *Function;
|
||||||
|
|
||||||
|
/// \brief The function template from which this function template
|
||||||
|
/// specialization was generated.
|
||||||
FunctionTemplateDecl *Template;
|
FunctionTemplateDecl *Template;
|
||||||
|
|
||||||
|
/// \brief The template arguments used to produce the function template
|
||||||
|
/// specialization from the function template.
|
||||||
const TemplateArgumentList *TemplateArguments;
|
const TemplateArgumentList *TemplateArguments;
|
||||||
|
|
||||||
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
|
Profile(ID, TemplateArguments->getFlatArgumentList(),
|
||||||
|
TemplateArguments->flat_size());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
|
||||||
|
unsigned NumTemplateArgs) {
|
||||||
|
ID.AddInteger(NumTemplateArgs);
|
||||||
|
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
|
||||||
|
TemplateArgs[Arg].Profile(ID);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Declaration of a template function.
|
/// Declaration of a template function.
|
||||||
class FunctionTemplateDecl : public TemplateDecl {
|
class FunctionTemplateDecl : public TemplateDecl {
|
||||||
protected:
|
protected:
|
||||||
/// \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.
|
/// function template.
|
||||||
struct Common {
|
struct Common {
|
||||||
/// \brief The class template specializations for this class
|
/// \brief The function template specializations for this function
|
||||||
/// template, including explicit specializations and instantiations.
|
/// template, including explicit specializations and instantiations.
|
||||||
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
|
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
|
||||||
|
|
||||||
/// \brief The class template partial specializations for this class
|
|
||||||
/// template.
|
|
||||||
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
|
|
||||||
PartialSpecializations;
|
|
||||||
|
|
||||||
/// \brief The injected-class-name type for this class template.
|
|
||||||
QualType InjectedClassNameType;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief A pointer to the previous declaration (if this is a redeclaration)
|
||||||
|
/// or to the data that is common to all declarations of this function
|
||||||
|
/// template.
|
||||||
|
llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
|
||||||
|
|
||||||
|
/// \brief Retrieves the "common" pointer shared by all
|
||||||
|
/// (re-)declarations of the same function template. Calling this routine
|
||||||
|
/// may implicitly allocate memory for the common pointer.
|
||||||
|
Common *getCommonPtr();
|
||||||
|
|
||||||
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||||
TemplateParameterList *Params, NamedDecl *Decl)
|
TemplateParameterList *Params, NamedDecl *Decl)
|
||||||
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
|
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
|
||||||
|
CommonOrPrev((Common*)0) { }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Get the underling function declaration of the template.
|
void Destroy(ASTContext &C);
|
||||||
|
|
||||||
|
/// Get the underlying function declaration of the template.
|
||||||
FunctionDecl *getTemplatedDecl() const {
|
FunctionDecl *getTemplatedDecl() const {
|
||||||
return static_cast<FunctionDecl*>(TemplatedDecl);
|
return static_cast<FunctionDecl*>(TemplatedDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the set of function template specializations of this
|
||||||
|
/// function template.
|
||||||
|
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
||||||
|
return getCommonPtr()->Specializations;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
|
/// NULL if no such declaration exists.
|
||||||
|
const FunctionTemplateDecl *getPreviousDeclaration() const {
|
||||||
|
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the previous declaration of this function template, or
|
||||||
|
/// NULL if no such declaration exists.
|
||||||
|
FunctionTemplateDecl *getPreviousDeclaration() {
|
||||||
|
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Set the previous declaration of this function template.
|
||||||
|
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
|
||||||
|
if (Prev)
|
||||||
|
CommonOrPrev = Prev;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a template function node.
|
/// Create a template function node.
|
||||||
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation L,
|
SourceLocation L,
|
||||||
|
@ -421,352 +819,6 @@ public:
|
||||||
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Represents a template argument within a class template
|
|
||||||
/// specialization.
|
|
||||||
class TemplateArgument {
|
|
||||||
union {
|
|
||||||
uintptr_t TypeOrValue;
|
|
||||||
struct {
|
|
||||||
char Value[sizeof(llvm::APSInt)];
|
|
||||||
void *Type;
|
|
||||||
} Integer;
|
|
||||||
struct {
|
|
||||||
TemplateArgument *Args;
|
|
||||||
unsigned NumArgs;
|
|
||||||
bool CopyArgs;
|
|
||||||
} Args;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief Location of the beginning of this template argument.
|
|
||||||
SourceLocation StartLoc;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// \brief The type of template argument we're storing.
|
|
||||||
enum ArgKind {
|
|
||||||
Null = 0,
|
|
||||||
/// The template argument is a type. Its value is stored in the
|
|
||||||
/// TypeOrValue field.
|
|
||||||
Type = 1,
|
|
||||||
/// The template argument is a declaration
|
|
||||||
Declaration = 2,
|
|
||||||
/// The template argument is an integral value stored in an llvm::APSInt.
|
|
||||||
Integral = 3,
|
|
||||||
/// The template argument is a value- or type-dependent expression
|
|
||||||
/// stored in an Expr*.
|
|
||||||
Expression = 4,
|
|
||||||
|
|
||||||
/// The template argument is actually a parameter pack. Arguments are stored
|
|
||||||
/// in the Args struct.
|
|
||||||
Pack = 5
|
|
||||||
} Kind;
|
|
||||||
|
|
||||||
/// \brief Construct an empty, invalid template argument.
|
|
||||||
TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
|
|
||||||
|
|
||||||
/// \brief Construct a template type argument.
|
|
||||||
TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
|
|
||||||
TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
|
|
||||||
StartLoc = Loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Construct a template argument that refers to a
|
|
||||||
/// declaration, which is either an external declaration or a
|
|
||||||
/// template declaration.
|
|
||||||
TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
|
|
||||||
// FIXME: Need to be sure we have the "canonical" declaration!
|
|
||||||
TypeOrValue = reinterpret_cast<uintptr_t>(D);
|
|
||||||
StartLoc = Loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Construct an integral constant template argument.
|
|
||||||
TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
|
|
||||||
QualType Type)
|
|
||||||
: Kind(Integral) {
|
|
||||||
new (Integer.Value) llvm::APSInt(Value);
|
|
||||||
Integer.Type = Type.getAsOpaquePtr();
|
|
||||||
StartLoc = Loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Construct a template argument that is an expression.
|
|
||||||
///
|
|
||||||
/// This form of template argument only occurs in template argument
|
|
||||||
/// lists used for dependent types and for expression; it will not
|
|
||||||
/// occur in a non-dependent, canonical template argument list.
|
|
||||||
TemplateArgument(Expr *E);
|
|
||||||
|
|
||||||
/// \brief Copy constructor for a template argument.
|
|
||||||
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
|
|
||||||
if (Kind == Integral) {
|
|
||||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
|
||||||
Integer.Type = Other.Integer.Type;
|
|
||||||
} else if (Kind == Pack) {
|
|
||||||
Args.NumArgs = Other.Args.NumArgs;
|
|
||||||
Args.Args = new TemplateArgument[Args.NumArgs];
|
|
||||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
|
||||||
Args.Args[I] = Other.Args.Args[I];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
TypeOrValue = Other.TypeOrValue;
|
|
||||||
StartLoc = Other.StartLoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateArgument& operator=(const TemplateArgument& Other) {
|
|
||||||
// FIXME: Does not provide the strong guarantee for exception
|
|
||||||
// safety.
|
|
||||||
using llvm::APSInt;
|
|
||||||
|
|
||||||
// FIXME: Handle Packs
|
|
||||||
assert(Kind != Pack && "FIXME: Handle packs");
|
|
||||||
assert(Other.Kind != Pack && "FIXME: Handle packs");
|
|
||||||
|
|
||||||
if (Kind == Other.Kind && Kind == Integral) {
|
|
||||||
// Copy integral values.
|
|
||||||
*this->getAsIntegral() = *Other.getAsIntegral();
|
|
||||||
Integer.Type = Other.Integer.Type;
|
|
||||||
} else {
|
|
||||||
// Destroy the current integral value, if that's what we're holding.
|
|
||||||
if (Kind == Integral)
|
|
||||||
getAsIntegral()->~APSInt();
|
|
||||||
|
|
||||||
Kind = Other.Kind;
|
|
||||||
|
|
||||||
if (Other.Kind == Integral) {
|
|
||||||
new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
|
|
||||||
Integer.Type = Other.Integer.Type;
|
|
||||||
} else
|
|
||||||
TypeOrValue = Other.TypeOrValue;
|
|
||||||
}
|
|
||||||
StartLoc = Other.StartLoc;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
~TemplateArgument() {
|
|
||||||
using llvm::APSInt;
|
|
||||||
|
|
||||||
if (Kind == Integral)
|
|
||||||
getAsIntegral()->~APSInt();
|
|
||||||
else if (Kind == Pack && Args.CopyArgs)
|
|
||||||
delete[] Args.Args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Return the kind of stored template argument.
|
|
||||||
ArgKind getKind() const { return Kind; }
|
|
||||||
|
|
||||||
/// \brief Determine whether this template argument has no value.
|
|
||||||
bool isNull() const { return Kind == Null; }
|
|
||||||
|
|
||||||
/// \brief Retrieve the template argument as a type.
|
|
||||||
QualType getAsType() const {
|
|
||||||
if (Kind != Type)
|
|
||||||
return QualType();
|
|
||||||
|
|
||||||
return QualType::getFromOpaquePtr(
|
|
||||||
reinterpret_cast<void*>(TypeOrValue));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the template argument as a declaration.
|
|
||||||
Decl *getAsDecl() const {
|
|
||||||
if (Kind != Declaration)
|
|
||||||
return 0;
|
|
||||||
return reinterpret_cast<Decl *>(TypeOrValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the template argument as an integral value.
|
|
||||||
llvm::APSInt *getAsIntegral() {
|
|
||||||
if (Kind != Integral)
|
|
||||||
return 0;
|
|
||||||
return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const llvm::APSInt *getAsIntegral() const {
|
|
||||||
return const_cast<TemplateArgument*>(this)->getAsIntegral();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the type of the integral value.
|
|
||||||
QualType getIntegralType() const {
|
|
||||||
if (Kind != Integral)
|
|
||||||
return QualType();
|
|
||||||
|
|
||||||
return QualType::getFromOpaquePtr(Integer.Type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setIntegralType(QualType T) {
|
|
||||||
assert(Kind == Integral &&
|
|
||||||
"Cannot set the integral type of a non-integral template argument");
|
|
||||||
Integer.Type = T.getAsOpaquePtr();
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief Retrieve the template argument as an expression.
|
|
||||||
Expr *getAsExpr() const {
|
|
||||||
if (Kind != Expression)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return reinterpret_cast<Expr *>(TypeOrValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Iterator that traverses the elements of a template argument pack.
|
|
||||||
typedef const TemplateArgument * pack_iterator;
|
|
||||||
|
|
||||||
/// \brief Iterator referencing the first argument of a template argument
|
|
||||||
/// pack.
|
|
||||||
pack_iterator pack_begin() const {
|
|
||||||
assert(Kind == Pack);
|
|
||||||
return Args.Args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Iterator referencing one past the last argument of a template
|
|
||||||
/// argument pack.
|
|
||||||
pack_iterator pack_end() const {
|
|
||||||
assert(Kind == Pack);
|
|
||||||
return Args.Args + Args.NumArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief The number of template arguments in the given template argument
|
|
||||||
/// pack.
|
|
||||||
unsigned pack_size() const {
|
|
||||||
assert(Kind == Pack);
|
|
||||||
return Args.NumArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the location where the template argument starts.
|
|
||||||
SourceLocation getLocation() const { return StartLoc; }
|
|
||||||
|
|
||||||
/// \brief Construct a template argument pack.
|
|
||||||
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
|
|
||||||
|
|
||||||
/// \brief Used to insert TemplateArguments into FoldingSets.
|
|
||||||
void Profile(llvm::FoldingSetNodeID &ID) const {
|
|
||||||
ID.AddInteger(Kind);
|
|
||||||
switch (Kind) {
|
|
||||||
case Null:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Type:
|
|
||||||
getAsType().Profile(ID);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Declaration:
|
|
||||||
ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Integral:
|
|
||||||
getAsIntegral()->Profile(ID);
|
|
||||||
getIntegralType().Profile(ID);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Expression:
|
|
||||||
// FIXME: We need a canonical representation of expressions.
|
|
||||||
ID.AddPointer(getAsExpr());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Pack:
|
|
||||||
ID.AddInteger(Args.NumArgs);
|
|
||||||
for (unsigned I = 0; I != Args.NumArgs; ++I)
|
|
||||||
Args.Args[I].Profile(ID);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief A helper class for making template argument lists.
|
|
||||||
class TemplateArgumentListBuilder {
|
|
||||||
TemplateArgument *StructuredArgs;
|
|
||||||
unsigned MaxStructuredArgs;
|
|
||||||
unsigned NumStructuredArgs;
|
|
||||||
|
|
||||||
TemplateArgument *FlatArgs;
|
|
||||||
unsigned MaxFlatArgs;
|
|
||||||
unsigned NumFlatArgs;
|
|
||||||
|
|
||||||
bool AddingToPack;
|
|
||||||
unsigned PackBeginIndex;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
|
|
||||||
unsigned NumTemplateArgs)
|
|
||||||
: StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
|
|
||||||
NumStructuredArgs(0), FlatArgs(0),
|
|
||||||
MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
|
|
||||||
AddingToPack(false), PackBeginIndex(0) { }
|
|
||||||
|
|
||||||
void Append(const TemplateArgument& Arg);
|
|
||||||
void BeginPack();
|
|
||||||
void EndPack();
|
|
||||||
|
|
||||||
void ReleaseArgs();
|
|
||||||
|
|
||||||
unsigned flatSize() const {
|
|
||||||
return NumFlatArgs;
|
|
||||||
}
|
|
||||||
const TemplateArgument *getFlatArguments() const {
|
|
||||||
return FlatArgs;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned structuredSize() const {
|
|
||||||
// If we don't have any structured args, just reuse the flat size.
|
|
||||||
if (!StructuredArgs)
|
|
||||||
return flatSize();
|
|
||||||
|
|
||||||
return NumStructuredArgs;
|
|
||||||
}
|
|
||||||
const TemplateArgument *getStructuredArguments() const {
|
|
||||||
// If we don't have any structured args, just reuse the flat args.
|
|
||||||
if (!StructuredArgs)
|
|
||||||
return getFlatArguments();
|
|
||||||
|
|
||||||
return StructuredArgs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// \brief A template argument list.
|
|
||||||
///
|
|
||||||
/// FIXME: In the future, this class will be extended to support
|
|
||||||
/// variadic templates and member templates, which will make some of
|
|
||||||
/// the function names below make more sense.
|
|
||||||
class TemplateArgumentList {
|
|
||||||
/// \brief The template argument list.
|
|
||||||
///
|
|
||||||
/// The integer value will be non-zero to indicate that this
|
|
||||||
/// template argument list does not own the pointer.
|
|
||||||
llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
|
|
||||||
|
|
||||||
/// \brief The number of template arguments in this template
|
|
||||||
/// argument list.
|
|
||||||
unsigned NumFlatArguments;
|
|
||||||
|
|
||||||
llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
|
|
||||||
unsigned NumStructuredArguments;
|
|
||||||
|
|
||||||
public:
|
|
||||||
TemplateArgumentList(ASTContext &Context,
|
|
||||||
TemplateArgumentListBuilder &Builder,
|
|
||||||
bool TakeArgs);
|
|
||||||
|
|
||||||
~TemplateArgumentList();
|
|
||||||
|
|
||||||
/// \brief Retrieve the template argument at a given index.
|
|
||||||
const TemplateArgument &get(unsigned Idx) const {
|
|
||||||
assert(Idx < NumFlatArguments && "Invalid template argument index");
|
|
||||||
return getFlatArgumentList()[Idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Retrieve the template argument at a given index.
|
|
||||||
const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
|
|
||||||
|
|
||||||
/// \brief Retrieve the number of template arguments in this
|
|
||||||
/// template argument list.
|
|
||||||
unsigned size() const { return NumFlatArguments; }
|
|
||||||
|
|
||||||
/// \brief Retrieve the number of template arguments in the
|
|
||||||
/// flattened template argument list.
|
|
||||||
unsigned flat_size() const { return NumFlatArguments; }
|
|
||||||
|
|
||||||
/// \brief Retrieve the flattened template argument list.
|
|
||||||
const TemplateArgument *getFlatArgumentList() const {
|
|
||||||
return FlatArguments.getPointer();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// \brief Describes the kind of template specialization that a
|
// \brief Describes the kind of template specialization that a
|
||||||
// particular template specialization declaration represents.
|
// particular template specialization declaration represents.
|
||||||
enum TemplateSpecializationKind {
|
enum TemplateSpecializationKind {
|
||||||
|
|
|
@ -1806,6 +1806,12 @@ Decl *ASTContext::getCanonicalDecl(Decl *D) {
|
||||||
return const_cast<FunctionDecl *>(Function);
|
return const_cast<FunctionDecl *>(Function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
|
||||||
|
while (FunTmpl->getPreviousDeclaration())
|
||||||
|
FunTmpl = FunTmpl->getPreviousDeclaration();
|
||||||
|
return FunTmpl;
|
||||||
|
}
|
||||||
|
|
||||||
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
|
||||||
while (Var->getPreviousDeclaration())
|
while (Var->getPreviousDeclaration())
|
||||||
Var = Var->getPreviousDeclaration();
|
Var = Var->getPreviousDeclaration();
|
||||||
|
|
|
@ -372,11 +372,6 @@ void FunctionDecl::Destroy(ASTContext& C) {
|
||||||
|
|
||||||
C.Deallocate(ParamInfo);
|
C.Deallocate(ParamInfo);
|
||||||
|
|
||||||
if (FunctionTemplateSpecializationInfo *Info
|
|
||||||
= TemplateOrSpecialization
|
|
||||||
.dyn_cast<FunctionTemplateSpecializationInfo*>())
|
|
||||||
C.Deallocate(Info);
|
|
||||||
|
|
||||||
Decl::Destroy(C);
|
Decl::Destroy(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -564,6 +559,18 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
|
||||||
|
PreviousDeclaration = PrevDecl;
|
||||||
|
|
||||||
|
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
|
||||||
|
FunctionTemplateDecl *PrevFunTmpl
|
||||||
|
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
|
||||||
|
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
|
||||||
|
FunTmpl->setPreviousDeclaration(PrevFunTmpl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// getOverloadedOperator - Which C++ overloaded operator this
|
/// getOverloadedOperator - Which C++ overloaded operator this
|
||||||
/// function represents, if any.
|
/// function represents, if any.
|
||||||
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
|
||||||
|
@ -595,15 +602,21 @@ FunctionDecl::getTemplateSpecializationArgs() const {
|
||||||
void
|
void
|
||||||
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
|
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
|
||||||
FunctionTemplateDecl *Template,
|
FunctionTemplateDecl *Template,
|
||||||
const TemplateArgumentList *TemplateArgs) {
|
const TemplateArgumentList *TemplateArgs,
|
||||||
|
void *InsertPos) {
|
||||||
FunctionTemplateSpecializationInfo *Info
|
FunctionTemplateSpecializationInfo *Info
|
||||||
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
|
||||||
if (!Info)
|
if (!Info)
|
||||||
Info = new (Context) FunctionTemplateSpecializationInfo;
|
Info = new (Context) FunctionTemplateSpecializationInfo;
|
||||||
|
|
||||||
|
Info->Function = this;
|
||||||
Info->Template = Template;
|
Info->Template = Template;
|
||||||
Info->TemplateArguments = TemplateArgs;
|
Info->TemplateArguments = TemplateArgs;
|
||||||
TemplateOrSpecialization = Info;
|
TemplateOrSpecialization = Info;
|
||||||
|
|
||||||
|
// Insert this function template specialization into the set of known
|
||||||
|
// function template specialiations.
|
||||||
|
Template->getSpecializations().InsertNode(Info, InsertPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -81,11 +81,36 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
|
||||||
DeclContext *DC,
|
DeclContext *DC,
|
||||||
SourceLocation L,
|
SourceLocation L,
|
||||||
DeclarationName Name,
|
DeclarationName Name,
|
||||||
TemplateParameterList *Params,
|
TemplateParameterList *Params,
|
||||||
NamedDecl *Decl) {
|
NamedDecl *Decl) {
|
||||||
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
|
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FunctionTemplateDecl::Destroy(ASTContext &C) {
|
||||||
|
if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
|
||||||
|
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
|
||||||
|
Spec = CommonPtr->Specializations.begin(),
|
||||||
|
SpecEnd = CommonPtr->Specializations.end();
|
||||||
|
Spec != SpecEnd; ++Spec)
|
||||||
|
C.Deallocate(&*Spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
Decl::Destroy(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
|
||||||
|
// Find the first declaration of this function template.
|
||||||
|
FunctionTemplateDecl *First = this;
|
||||||
|
while (First->getPreviousDeclaration())
|
||||||
|
First = First->getPreviousDeclaration();
|
||||||
|
|
||||||
|
if (First->CommonOrPrev.isNull()) {
|
||||||
|
// FIXME: Allocate with the ASTContext
|
||||||
|
First->CommonOrPrev = new Common;
|
||||||
|
}
|
||||||
|
return First->CommonOrPrev.get<Common*>();
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ClassTemplateDecl Implementation
|
// ClassTemplateDecl Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -1500,6 +1500,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
|
||||||
break;
|
break;
|
||||||
// No code generation needed.
|
// No code generation needed.
|
||||||
case Decl::Using:
|
case Decl::Using:
|
||||||
|
case Decl::ClassTemplate:
|
||||||
|
case Decl::FunctionTemplate:
|
||||||
break;
|
break;
|
||||||
case Decl::CXXConstructor:
|
case Decl::CXXConstructor:
|
||||||
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
|
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
|
||||||
|
|
|
@ -1036,14 +1036,22 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
|
||||||
InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
|
InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
|
||||||
FunctionTemplate->getDeclContext(),
|
FunctionTemplate->getDeclContext(),
|
||||||
*DeducedArgumentList));
|
*DeducedArgumentList));
|
||||||
|
if (!Specialization)
|
||||||
if (!Specialization || Trap.hasErrorOccurred())
|
|
||||||
return TDK_SubstitutionFailure;
|
return TDK_SubstitutionFailure;
|
||||||
|
|
||||||
|
// If the template argument list is owned by the function template
|
||||||
|
// specialization, release it.
|
||||||
|
if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
|
||||||
|
Info.take();
|
||||||
|
|
||||||
// Turn the specialization into an actual function template specialization.
|
// There may have been an error that did not prevent us from constructing a
|
||||||
Specialization->setFunctionTemplateSpecialization(Context,
|
// declaration. Mark the declaration invalid and return with a substitution
|
||||||
FunctionTemplate,
|
// failure.
|
||||||
Info.take());
|
if (Trap.hasErrorOccurred()) {
|
||||||
|
Specialization->setInvalidDecl(true);
|
||||||
|
return TDK_SubstitutionFailure;
|
||||||
|
}
|
||||||
|
|
||||||
return TDK_Success;
|
return TDK_Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -294,7 +294,24 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
||||||
// FIXME: Look for existing specializations (explicit or otherwise).
|
// Check whether there is already a function template specialization for
|
||||||
|
// this declaration.
|
||||||
|
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
|
||||||
|
void *InsertPos = 0;
|
||||||
|
if (FunctionTemplate) {
|
||||||
|
llvm::FoldingSetNodeID ID;
|
||||||
|
FunctionTemplateSpecializationInfo::Profile(ID,
|
||||||
|
TemplateArgs.getFlatArgumentList(),
|
||||||
|
TemplateArgs.flat_size());
|
||||||
|
|
||||||
|
FunctionTemplateSpecializationInfo *Info
|
||||||
|
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
|
||||||
|
InsertPos);
|
||||||
|
|
||||||
|
// If we already have a function template specialization, return it.
|
||||||
|
if (Info)
|
||||||
|
return Info->Function;
|
||||||
|
}
|
||||||
|
|
||||||
Sema::LocalInstantiationScope Scope(SemaRef);
|
Sema::LocalInstantiationScope Scope(SemaRef);
|
||||||
|
|
||||||
|
@ -325,10 +342,15 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
|
||||||
NamedDecl *PrevDecl = 0;
|
NamedDecl *PrevDecl = 0;
|
||||||
SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
|
SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
|
||||||
/*FIXME:*/OverloadableAttrRequired);
|
/*FIXME:*/OverloadableAttrRequired);
|
||||||
|
|
||||||
|
|
||||||
// FIXME: link this to the function template from which it was instantiated.
|
if (FunctionTemplate) {
|
||||||
|
// Record this function template specialization.
|
||||||
|
Function->setFunctionTemplateSpecialization(SemaRef.Context,
|
||||||
|
FunctionTemplate,
|
||||||
|
&TemplateArgs,
|
||||||
|
InsertPos);
|
||||||
|
}
|
||||||
|
|
||||||
return Function;
|
return Function;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// RUN: clang-cc -emit-llvm %s -o -
|
||||||
|
template<typename T, typename U>
|
||||||
|
T* next(T* ptr, const U& diff);
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
T* next(T* ptr, const U& diff) {
|
||||||
|
return ptr + diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
void test(int *iptr, float *fptr, int diff) {
|
||||||
|
iptr = next(iptr, diff);
|
||||||
|
fptr = next(fptr, diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
T* next(T* ptr, const U& diff);
|
||||||
|
|
||||||
|
void test2(int *iptr, double *dptr, int diff) {
|
||||||
|
iptr = next(iptr, diff);
|
||||||
|
dptr = next(dptr, diff);
|
||||||
|
}
|
Loading…
Reference in New Issue