2009-02-05 03:02:06 +08:00
|
|
|
//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the C++ related Decl classes for templates.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
|
|
#include "clang/AST/DeclTemplate.h"
|
2009-02-10 02:46:07 +08:00
|
|
|
#include "clang/AST/Expr.h"
|
2009-02-05 03:02:06 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
|
|
|
#include "clang/Basic/IdentifierTable.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
using namespace clang;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateParameterList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-02-07 06:42:48 +08:00
|
|
|
TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
|
|
|
|
SourceLocation LAngleLoc,
|
|
|
|
Decl **Params, unsigned NumParams,
|
|
|
|
SourceLocation RAngleLoc)
|
|
|
|
: TemplateLoc(TemplateLoc), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
|
|
|
|
NumParams(NumParams) {
|
2009-02-05 03:02:06 +08:00
|
|
|
for (unsigned Idx = 0; Idx < NumParams; ++Idx)
|
|
|
|
begin()[Idx] = Params[Idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
TemplateParameterList *
|
2009-02-07 06:42:48 +08:00
|
|
|
TemplateParameterList::Create(ASTContext &C, SourceLocation TemplateLoc,
|
|
|
|
SourceLocation LAngleLoc, Decl **Params,
|
|
|
|
unsigned NumParams, SourceLocation RAngleLoc) {
|
2009-02-05 03:02:06 +08:00
|
|
|
unsigned Size = sizeof(TemplateParameterList) + sizeof(Decl *) * NumParams;
|
|
|
|
unsigned Align = llvm::AlignOf<TemplateParameterList>::Alignment;
|
|
|
|
void *Mem = C.Allocate(Size, Align);
|
2009-02-07 06:42:48 +08:00
|
|
|
return new (Mem) TemplateParameterList(TemplateLoc, LAngleLoc, Params,
|
|
|
|
NumParams, RAngleLoc);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2009-02-12 02:16:40 +08:00
|
|
|
unsigned TemplateParameterList::getMinRequiredArguments() const {
|
|
|
|
unsigned NumRequiredArgs = size();
|
|
|
|
iterator Param = const_cast<TemplateParameterList *>(this)->end(),
|
|
|
|
ParamBegin = const_cast<TemplateParameterList *>(this)->begin();
|
|
|
|
while (Param != ParamBegin) {
|
|
|
|
--Param;
|
|
|
|
if (!(isa<TemplateTypeParmDecl>(*Param) &&
|
|
|
|
cast<TemplateTypeParmDecl>(*Param)->hasDefaultArgument()) &&
|
|
|
|
!(isa<NonTypeTemplateParmDecl>(*Param) &&
|
|
|
|
cast<NonTypeTemplateParmDecl>(*Param)->hasDefaultArgument()) &&
|
|
|
|
!(isa<TemplateTemplateParmDecl>(*Param) &&
|
|
|
|
cast<TemplateTemplateParmDecl>(*Param)->hasDefaultArgument()))
|
|
|
|
break;
|
|
|
|
|
|
|
|
--NumRequiredArgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NumRequiredArgs;
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TemplateDecl::~TemplateDecl() {
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// FunctionTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
|
|
|
NamedDecl *Decl) {
|
|
|
|
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplateDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
|
|
|
|
DeclContext *DC,
|
|
|
|
SourceLocation L,
|
|
|
|
DeclarationName Name,
|
|
|
|
TemplateParameterList *Params,
|
Introduce a new expression type, UnresolvedDeclRefExpr, that describes
dependent qualified-ids such as
Fibonacci<N - 1>::value
where N is a template parameter. These references are "unresolved"
because the name is dependent and, therefore, cannot be resolved to a
declaration node (as we would do for a DeclRefExpr or
QualifiedDeclRefExpr). UnresolvedDeclRefExprs instantiate to
DeclRefExprs, QualifiedDeclRefExprs, etc.
Also, be a bit more careful about keeping only a single set of
specializations for a class template, and instantiating from the
definition of that template rather than a previous declaration. In
general, we need a better solution for this for all TagDecls, because
it's too easy to accidentally look at a declaration that isn't the
definition.
We can now process a simple Fibonacci computation described as a
template metaprogram.
llvm-svn: 67308
2009-03-20 01:26:29 +08:00
|
|
|
NamedDecl *Decl,
|
|
|
|
ClassTemplateDecl *PrevDecl) {
|
|
|
|
Common *CommonPtr;
|
|
|
|
if (PrevDecl)
|
|
|
|
CommonPtr = PrevDecl->CommonPtr;
|
|
|
|
else
|
|
|
|
CommonPtr = new (C) Common;
|
|
|
|
|
|
|
|
return new (C) ClassTemplateDecl(DC, L, Name, Params, Decl, PrevDecl,
|
|
|
|
CommonPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
ClassTemplateDecl::~ClassTemplateDecl() {
|
|
|
|
assert(CommonPtr == 0 && "ClassTemplateDecl must be explicitly destroyed");
|
|
|
|
}
|
|
|
|
|
|
|
|
void ClassTemplateDecl::Destroy(ASTContext& C) {
|
|
|
|
if (!PreviousDeclaration) {
|
|
|
|
CommonPtr->~Common();
|
|
|
|
C.Deallocate((void*)CommonPtr);
|
|
|
|
}
|
|
|
|
CommonPtr = 0;
|
|
|
|
|
|
|
|
this->~ClassTemplateDecl();
|
|
|
|
C.Deallocate((void*)this);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
2009-05-11 06:57:19 +08:00
|
|
|
QualType ClassTemplateDecl::getInjectedClassNameType(ASTContext &Context) {
|
|
|
|
if (!CommonPtr->InjectedClassNameType.isNull())
|
|
|
|
return CommonPtr->InjectedClassNameType;
|
|
|
|
|
|
|
|
// FIXME: n2800 14.6.1p1 should say how the template arguments
|
|
|
|
// corresponding to template parameter packs should be pack
|
|
|
|
// expansions. We already say that in 14.6.2.1p2, so it would be
|
|
|
|
// better to fix that redundancy.
|
|
|
|
|
|
|
|
TemplateParameterList *Params = getTemplateParameters();
|
|
|
|
|
|
|
|
llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
|
|
|
|
llvm::SmallVector<TemplateArgument, 16> CanonTemplateArgs;
|
|
|
|
TemplateArgs.reserve(Params->size());
|
|
|
|
CanonTemplateArgs.reserve(Params->size());
|
|
|
|
|
|
|
|
for (TemplateParameterList::iterator
|
|
|
|
Param = Params->begin(), ParamEnd = Params->end();
|
|
|
|
Param != ParamEnd; ++Param) {
|
|
|
|
if (isa<TemplateTypeParmDecl>(*Param)) {
|
|
|
|
QualType ParamType = Context.getTypeDeclType(cast<TypeDecl>(*Param));
|
|
|
|
TemplateArgs.push_back(TemplateArgument((*Param)->getLocation(),
|
|
|
|
ParamType));
|
|
|
|
CanonTemplateArgs.push_back(
|
|
|
|
TemplateArgument((*Param)->getLocation(),
|
|
|
|
Context.getCanonicalType(ParamType)));
|
|
|
|
} else if (NonTypeTemplateParmDecl *NTTP =
|
|
|
|
dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
|
|
|
|
// FIXME: Build canonical expression, too!
|
|
|
|
Expr *E = new (Context) DeclRefExpr(NTTP, NTTP->getType(),
|
|
|
|
NTTP->getLocation(),
|
|
|
|
NTTP->getType()->isDependentType(),
|
|
|
|
/*Value-dependent=*/true);
|
|
|
|
TemplateArgs.push_back(TemplateArgument(E));
|
|
|
|
CanonTemplateArgs.push_back(TemplateArgument(E));
|
|
|
|
} else {
|
|
|
|
TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
|
|
|
|
TemplateArgs.push_back(TemplateArgument(TTP->getLocation(), TTP));
|
|
|
|
CanonTemplateArgs.push_back(TemplateArgument(TTP->getLocation(),
|
|
|
|
Context.getCanonicalDecl(TTP)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FIXME: I should really move the "build-the-canonical-type" logic
|
|
|
|
// into ASTContext::getTemplateSpecializationType.
|
|
|
|
TemplateName Name = TemplateName(this);
|
|
|
|
QualType CanonType = Context.getTemplateSpecializationType(
|
|
|
|
Context.getCanonicalTemplateName(Name),
|
|
|
|
&CanonTemplateArgs[0],
|
|
|
|
CanonTemplateArgs.size());
|
|
|
|
|
|
|
|
CommonPtr->InjectedClassNameType
|
|
|
|
= Context.getTemplateSpecializationType(Name,
|
|
|
|
&TemplateArgs[0],
|
|
|
|
TemplateArgs.size(),
|
|
|
|
CanonType);
|
|
|
|
return CommonPtr->InjectedClassNameType;
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateTypeParm Allocation/Deallocation Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TemplateTypeParmDecl *
|
|
|
|
TemplateTypeParmDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id, bool Typename) {
|
2009-02-06 07:33:38 +08:00
|
|
|
QualType Type = C.getTemplateTypeParmType(D, P, Id);
|
|
|
|
return new (C) TemplateTypeParmDecl(DC, L, Id, Typename, Type);
|
2009-02-05 03:02:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// NonTypeTemplateParmDecl Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
NonTypeTemplateParmDecl *
|
|
|
|
NonTypeTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id, QualType T,
|
|
|
|
SourceLocation TypeSpecStartLoc) {
|
|
|
|
return new (C) NonTypeTemplateParmDecl(DC, L, D, P, Id, T,
|
|
|
|
TypeSpecStartLoc);
|
|
|
|
}
|
|
|
|
|
2009-02-11 03:49:53 +08:00
|
|
|
SourceLocation NonTypeTemplateParmDecl::getDefaultArgumentLoc() const {
|
|
|
|
return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
|
|
|
|
: SourceLocation();
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:02:06 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateTemplateParmDecl Method Implementations
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TemplateTemplateParmDecl *
|
|
|
|
TemplateTemplateParmDecl::Create(ASTContext &C, DeclContext *DC,
|
|
|
|
SourceLocation L, unsigned D, unsigned P,
|
|
|
|
IdentifierInfo *Id,
|
|
|
|
TemplateParameterList *Params) {
|
|
|
|
return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
|
|
|
|
}
|
|
|
|
|
2009-02-11 03:49:53 +08:00
|
|
|
SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
|
|
|
|
return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
|
|
|
|
: SourceLocation();
|
|
|
|
}
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
|
2009-03-10 07:48:35 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// TemplateArgument Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
|
|
|
|
TypeOrValue = reinterpret_cast<uintptr_t>(E);
|
|
|
|
StartLoc = E->getSourceRange().getBegin();
|
|
|
|
}
|
|
|
|
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ClassTemplateSpecializationDecl Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
ClassTemplateSpecializationDecl::
|
|
|
|
ClassTemplateSpecializationDecl(DeclContext *DC, SourceLocation L,
|
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
|
|
TemplateArgument *TemplateArgs,
|
|
|
|
unsigned NumTemplateArgs)
|
|
|
|
: CXXRecordDecl(ClassTemplateSpecialization,
|
|
|
|
SpecializedTemplate->getTemplatedDecl()->getTagKind(),
|
|
|
|
DC, L,
|
|
|
|
// FIXME: Should we use DeclarationName for the name of
|
|
|
|
// class template specializations?
|
|
|
|
SpecializedTemplate->getIdentifier()),
|
|
|
|
SpecializedTemplate(SpecializedTemplate),
|
2009-02-18 07:15:12 +08:00
|
|
|
NumTemplateArgs(NumTemplateArgs), SpecializationKind(TSK_Undeclared) {
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
TemplateArgument *Arg = reinterpret_cast<TemplateArgument *>(this + 1);
|
|
|
|
for (unsigned ArgIdx = 0; ArgIdx < NumTemplateArgs; ++ArgIdx, ++Arg)
|
Implement parsing of nested-name-specifiers that involve template-ids, e.g.,
std::vector<int>::allocator_type
When we parse a template-id that names a type, it will become either a
template-id annotation (which is a parsed representation of a
template-id that has not yet been through semantic analysis) or a
typename annotation (where semantic analysis has resolved the
template-id to an actual type), depending on the context. We only
produce a type in contexts where we know that we only need type
information, e.g., in a type specifier. Otherwise, we create a
template-id annotation that can later be "upgraded" by transforming it
into a typename annotation when the parser needs a type. This occurs,
for example, when we've parsed "std::vector<int>" above and then see
the '::' after it. However, it means that when writing something like
this:
template<> class Outer::Inner<int> { ... };
We have two tokens to represent Outer::Inner<int>: one token for the
nested name specifier Outer::, and one template-id annotation token
for Inner<int>, which will be passed to semantic analysis to define
the class template specialization.
Most of the churn in the template tests in this patch come from an
improvement in our error recovery from ill-formed template-ids.
llvm-svn: 65467
2009-02-26 03:37:18 +08:00
|
|
|
new (Arg) TemplateArgument(TemplateArgs[ArgIdx]);
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ClassTemplateSpecializationDecl *
|
|
|
|
ClassTemplateSpecializationDecl::Create(ASTContext &Context,
|
|
|
|
DeclContext *DC, SourceLocation L,
|
|
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
|
|
TemplateArgument *TemplateArgs,
|
2009-02-18 07:15:12 +08:00
|
|
|
unsigned NumTemplateArgs,
|
|
|
|
ClassTemplateSpecializationDecl *PrevDecl) {
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
unsigned Size = sizeof(ClassTemplateSpecializationDecl) +
|
|
|
|
sizeof(TemplateArgument) * NumTemplateArgs;
|
|
|
|
unsigned Align = llvm::AlignOf<ClassTemplateSpecializationDecl>::Alignment;
|
|
|
|
void *Mem = Context.Allocate(Size, Align);
|
2009-02-18 07:15:12 +08:00
|
|
|
ClassTemplateSpecializationDecl *Result
|
|
|
|
= new (Mem) ClassTemplateSpecializationDecl(DC, L, SpecializedTemplate,
|
|
|
|
TemplateArgs, NumTemplateArgs);
|
|
|
|
Context.getTypeDeclType(Result, PrevDecl);
|
|
|
|
return Result;
|
Added ClassTemplateSpecializationDecl, which is a subclass of
CXXRecordDecl that is used to represent class template
specializations. These are canonical declarations that can refer to
either an actual class template specialization in the code, e.g.,
template<> class vector<bool> { };
or to a template instantiation. However, neither of these features is
actually implemented yet, so really we're just using (and uniqing) the
declarations to make sure that, e.g., A<int> is a different type from
A<float>. Note that we carefully distinguish between what the user
wrote in the source code (e.g., "A<FLOAT>") and the semantic entity it
represents (e.g., "A<float, int>"); the former is in the sugared Type,
the latter is an actual Decl.
llvm-svn: 64716
2009-02-17 09:05:43 +08:00
|
|
|
}
|