Improve the representation of template names in the AST. This
representation handles the various ways in which one can name a
template, including unqualified references ("vector"), qualified
references ("std::vector"), and dependent template names
("MetaFun::template apply").
One immediate effect of this change is that the representation of
nested-name-specifiers in type names for class template
specializations (e.g., std::vector<int>) is more accurate. Rather than
representing std::vector<int> as
std::(vector<int>)
we represent it as
(std::vector)<int>
which more closely follows the C++ grammar.
Additionally, templates are no longer represented as declarations
(DeclPtrTy) in Parse-Sema interactions. Instead, I've introduced a new
OpaquePtr type (TemplateTy) that holds the representation of a
TemplateName. This will simplify the handling of dependent
template-names, once we get there.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68074 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index f3cf6b1..bb17954 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -483,6 +483,10 @@
Align = Layout.getAlignment();
break;
}
+
+ case Type::TemplateSpecialization:
+ assert(false && "Dependent types have no size");
+ break;
}
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
@@ -1358,30 +1362,31 @@
}
QualType
-ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
- const TemplateArgument *Args,
- unsigned NumArgs,
- QualType Canon) {
+ASTContext::getTemplateSpecializationType(TemplateName Template,
+ const TemplateArgument *Args,
+ unsigned NumArgs,
+ QualType Canon) {
+ // FIXME: If Template is dependent, canonicalize it!
+
if (!Canon.isNull())
Canon = getCanonicalType(Canon);
llvm::FoldingSetNodeID ID;
- ClassTemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
+ TemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
void *InsertPos = 0;
- ClassTemplateSpecializationType *Spec
- = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
+ TemplateSpecializationType *Spec
+ = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
if (Spec)
return QualType(Spec, 0);
- void *Mem = Allocate((sizeof(ClassTemplateSpecializationType) +
+ void *Mem = Allocate((sizeof(TemplateSpecializationType) +
sizeof(TemplateArgument) * NumArgs),
8);
- Spec = new (Mem) ClassTemplateSpecializationType(Template, Args, NumArgs,
- Canon);
+ Spec = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon);
Types.push_back(Spec);
- ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos);
+ TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
return QualType(Spec, 0);
}
@@ -2486,6 +2491,53 @@
ObjCConstantStringType = getObjCInterfaceType(Decl);
}
+/// \brief Retrieve the template name that represents a qualified
+/// template name such as \c std::vector.
+TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
+ bool TemplateKeyword,
+ TemplateDecl *Template) {
+ llvm::FoldingSetNodeID ID;
+ QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template);
+
+ void *InsertPos = 0;
+ QualifiedTemplateName *QTN =
+ QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+ if (!QTN) {
+ QTN = new (*this,4) QualifiedTemplateName(NNS, TemplateKeyword, Template);
+ QualifiedTemplateNames.InsertNode(QTN, InsertPos);
+ }
+
+ return TemplateName(QTN);
+}
+
+/// \brief Retrieve the template name that represents a dependent
+/// template name such as \c MetaFun::template apply.
+TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS,
+ const IdentifierInfo *Name) {
+ assert(NNS->isDependent() && "Nested name specifier must be dependent");
+
+ llvm::FoldingSetNodeID ID;
+ DependentTemplateName::Profile(ID, NNS, Name);
+
+ void *InsertPos = 0;
+ DependentTemplateName *QTN =
+ DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (QTN)
+ return TemplateName(QTN);
+
+ NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS);
+ if (CanonNNS == NNS) {
+ QTN = new (*this,4) DependentTemplateName(NNS, Name);
+ } else {
+ TemplateName Canon = getDependentTemplateName(CanonNNS, Name);
+ QTN = new (*this,4) DependentTemplateName(NNS, Name, Canon);
+ }
+
+ DependentTemplateNames.InsertNode(QTN, InsertPos);
+ return TemplateName(QTN);
+}
+
/// getFromTargetType - Given one of the integer types provided by
/// TargetInfo, produce the corresponding type. The unsigned @p Type
/// is actually a value of type @c TargetInfo::IntType.
@@ -3033,6 +3085,10 @@
ResultType.setCVRQualifiers(LHSCan.getCVRQualifiers());
return ResultType;
#endif
+
+ case Type::TemplateSpecialization:
+ assert(false && "Dependent types have no size");
+ break;
}
return QualType();
diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp
new file mode 100644
index 0000000..4e54fe4
--- /dev/null
+++ b/lib/AST/TemplateName.cpp
@@ -0,0 +1,54 @@
+//===--- TemplateName.h - C++ Template Name Representation-------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TemplateName interface and subclasses.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+
+TemplateDecl *TemplateName::getAsTemplateDecl() const {
+ if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+ return Template;
+
+ if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName())
+ return QTN->getTemplateDecl();
+
+ return 0;
+}
+
+bool TemplateName::isDependent() const {
+ if (TemplateDecl *Template = getAsTemplateDecl()) {
+ // FIXME: We don't yet have a notion of dependent
+ // declarations. When we do, check that. This hack won't last
+ // long!.
+ return isa<TemplateTemplateParmDecl>(Template);
+ }
+
+ return true;
+}
+
+void TemplateName::Print(llvm::raw_ostream &OS) const {
+ if (TemplateDecl *Template = Storage.dyn_cast<TemplateDecl *>())
+ OS << Template->getIdentifier()->getName();
+ else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+ QTN->getQualifier()->Print(OS);
+ if (QTN->hasTemplateKeyword())
+ OS << "template ";
+ OS << QTN->getTemplateDecl()->getIdentifier()->getName();
+ } else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
+ DTN->getQualifier()->Print(OS);
+ OS << "template ";
+ OS << DTN->getName()->getName();
+ }
+}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 0a3e8f9..6922dcc 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -93,8 +93,8 @@
return TOE->getUnderlyingExpr()->getType().getDesugaredType();
if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
return TOT->getUnderlyingType().getDesugaredType();
- if (const ClassTemplateSpecializationType *Spec
- = dyn_cast<ClassTemplateSpecializationType>(this))
+ if (const TemplateSpecializationType *Spec
+ = dyn_cast<TemplateSpecializationType>(this))
return Spec->getCanonicalTypeInternal().getDesugaredType();
if (const QualifiedNameType *QualName = dyn_cast<QualifiedNameType>(this))
return QualName->getNamedType().getDesugaredType();
@@ -549,11 +549,11 @@
return dyn_cast<TemplateTypeParmType>(CanonicalType);
}
-const ClassTemplateSpecializationType *
-Type::getAsClassTemplateSpecializationType() const {
+const TemplateSpecializationType *
+Type::getAsTemplateSpecializationType() const {
// There is no sugar for class template specialization types, so
// just return the canonical type pointer if it is the right class.
- return dyn_cast<ClassTemplateSpecializationType>(CanonicalType);
+ return dyn_cast<TemplateSpecializationType>(CanonicalType);
}
bool Type::isIntegerType() const {
@@ -972,7 +972,7 @@
}
bool
-ClassTemplateSpecializationType::
+TemplateSpecializationType::
anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
switch (Args[Idx].getKind()) {
@@ -997,17 +997,16 @@
return false;
}
-ClassTemplateSpecializationType::
-ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args,
- unsigned NumArgs, QualType Canon)
- : Type(ClassTemplateSpecialization,
+TemplateSpecializationType::
+TemplateSpecializationType(TemplateName T, const TemplateArgument *Args,
+ unsigned NumArgs, QualType Canon)
+ : Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
- /*FIXME: Check for dependent template */
- anyDependentTemplateArguments(Args, NumArgs)),
+ T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)),
Template(T), NumArgs(NumArgs)
{
assert((!Canon.isNull() ||
- anyDependentTemplateArguments(Args, NumArgs)) &&
+ T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)) &&
"No canonical type for non-dependent class template specialization");
TemplateArgument *TemplateArgs
@@ -1016,7 +1015,7 @@
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
}
-void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
+void TemplateSpecializationType::Destroy(ASTContext& C) {
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
// FIXME: Not all expressions get cloned, so we can't yet perform
// this destruction.
@@ -1025,24 +1024,23 @@
}
}
-ClassTemplateSpecializationType::iterator
-ClassTemplateSpecializationType::end() const {
+TemplateSpecializationType::iterator
+TemplateSpecializationType::end() const {
return begin() + getNumArgs();
}
const TemplateArgument &
-ClassTemplateSpecializationType::getArg(unsigned Idx) const {
+TemplateSpecializationType::getArg(unsigned Idx) const {
assert(Idx < getNumArgs() && "Template argument out of range");
return getArgs()[Idx];
}
void
-ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
- TemplateDecl *T,
- const TemplateArgument *Args,
- unsigned NumArgs) {
- ID.AddPointer(T);
-
+TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
+ TemplateName T,
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ T.Profile(ID);
for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
Args[Idx].Profile(ID);
}
@@ -1351,7 +1349,7 @@
InnerString = Name->getName() + InnerString;
}
-std::string ClassTemplateSpecializationType::PrintTemplateArgumentList(
+std::string TemplateSpecializationType::PrintTemplateArgumentList(
const TemplateArgument *Args,
unsigned NumArgs) {
std::string SpecString;
@@ -1403,9 +1401,15 @@
}
void
-ClassTemplateSpecializationType::
+TemplateSpecializationType::
getAsStringInternal(std::string &InnerString) const {
- std::string SpecString = Template->getNameAsString();
+ std::string SpecString;
+
+ {
+ llvm::raw_string_ostream OS(SpecString);
+ Template.Print(OS);
+ }
+
SpecString += PrintTemplateArgumentList(getArgs(), getNumArgs());
if (InnerString.empty())
InnerString.swap(SpecString);
@@ -1515,7 +1519,7 @@
if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(getDecl())) {
std::string TemplateArgs
- = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+ = TemplateSpecializationType::PrintTemplateArgumentList(
Spec->getTemplateArgs(),
Spec->getNumTemplateArgs());
InnerString = TemplateArgs + InnerString;
@@ -1534,7 +1538,7 @@
} else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(DC)) {
std::string TemplateArgs
- = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+ = TemplateSpecializationType::PrintTemplateArgumentList(
Spec->getTemplateArgs(),
Spec->getNumTemplateArgs());
MyPart = Spec->getIdentifier()->getName() + TemplateArgs;
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index 4f0334f..0562416 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -391,29 +391,17 @@
}
//===----------------------------------------------------------------------===//
-// ClassTemplateSpecializationType
+// TemplateSpecializationType
//===----------------------------------------------------------------------===//
-void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const {
- S.Emit(getCanonicalTypeInternal());
- S.EmitPtr(Template);
- S.EmitInt(NumArgs);
- // FIXME: Serialize class template specialization types
+void TemplateSpecializationType::EmitImpl(Serializer& S) const {
+ // FIXME: Serialization support
}
Type*
-ClassTemplateSpecializationType::
+TemplateSpecializationType::
CreateImpl(ASTContext& Context, Deserializer& D) {
- llvm::SmallVector<uintptr_t, 16> Args;
- llvm::SmallVector<bool, 16> ArgIsType;
-
- QualType Canon = QualType::ReadVal(D);
- TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>());
- unsigned NumArgs = D.ReadInt();
-
- // FIXME: De-serialize class template specialization types
- (void)Template;
- (void)NumArgs;
+ // FIXME: Deserialization support
return 0;
}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 7233bbf..bde6fba 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -561,7 +561,7 @@
case Type::FixedWidthInt:
case Type::BlockPointer:
case Type::MemberPointer:
- case Type::ClassTemplateSpecialization:
+ case Type::TemplateSpecialization:
case Type::QualifiedName:
case Type::ObjCQualifiedClass:
// Unsupported types
diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp
index 85d7384..5367c71 100644
--- a/lib/CodeGen/CodeGenTypes.cpp
+++ b/lib/CodeGen/CodeGenTypes.cpp
@@ -392,6 +392,9 @@
// http://gcc.gnu.org/onlinedocs/gccint/Type-Layout.html#Type-Layout
assert(0 && "FIXME: We can't handle member pointers yet.");
return llvm::OpaqueType::get();
+
+ case Type::TemplateSpecialization:
+ assert(false && "Dependent types can't get here");
}
// FIXME: implement.
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index f31aef6..e99e96a 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -135,7 +135,7 @@
TemplateNameKind
MinimalAction::isTemplateName(IdentifierInfo &II, Scope *S,
- DeclPtrTy &TemplateDecl,
+ TemplateTy &TemplateDecl,
const CXXScopeSpec *SS) {
return TNK_Non_template;
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 37a460c..fdfc731 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -474,7 +474,7 @@
TagOrTempResult
= Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TK,
StartLoc, SS,
- DeclPtrTy::make(TemplateId->Template),
+ TemplateTy::make(TemplateId->Template),
TemplateId->TemplateNameLoc,
TemplateId->LAngleLoc,
TemplateArgsPtr,
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index dc57ac1..4d419bb 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -117,7 +117,7 @@
// an operator and not as part of a simple-template-id.
}
- DeclPtrTy Template;
+ TemplateTy Template;
TemplateNameKind TNK = TNK_Non_template;
// FIXME: If the nested-name-specifier thus far is dependent,
// set TNK = TNK_Dependent_template_name and skip the
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index b962cbf..8eda694 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -406,7 +406,7 @@
/// last token in the stream (e.g., so that it can be replaced with an
/// annotation token).
bool
-Parser::ParseTemplateIdAfterTemplateName(DeclPtrTy Template,
+Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
SourceLocation TemplateNameLoc,
const CXXScopeSpec *SS,
bool ConsumeLastToken,
@@ -499,7 +499,7 @@
/// replaced with a type annotation token. Otherwise, the
/// simple-template-id is always replaced with a template-id
/// annotation token.
-void Parser::AnnotateTemplateIdToken(DeclPtrTy Template, TemplateNameKind TNK,
+void Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK,
const CXXScopeSpec *SS,
SourceLocation TemplateKWLoc,
bool AllowTypeAnnotation) {
@@ -531,12 +531,13 @@
return;
// Build the annotation token.
+ // FIXME: Not just for class templates!
if (TNK == TNK_Class_template && AllowTypeAnnotation) {
Action::TypeResult Type
- = Actions.ActOnClassTemplateId(Template, TemplateNameLoc,
- LAngleLoc, TemplateArgsPtr,
- &TemplateArgLocations[0],
- RAngleLoc, SS);
+ = Actions.ActOnTemplateIdType(Template, TemplateNameLoc,
+ LAngleLoc, TemplateArgsPtr,
+ &TemplateArgLocations[0],
+ RAngleLoc);
if (Type.isInvalid()) // FIXME: better recovery?
return;
@@ -603,12 +604,12 @@
TemplateId->NumArgs);
Action::TypeResult Type
- = Actions.ActOnClassTemplateId(DeclPtrTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->getTemplateArgLocations(),
- TemplateId->RAngleLoc, SS);
+ = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+ TemplateId->TemplateNameLoc,
+ TemplateId->LAngleLoc,
+ TemplateArgsPtr,
+ TemplateId->getTemplateArgLocations(),
+ TemplateId->RAngleLoc);
if (Type.isInvalid()) {
// FIXME: better recovery?
ConsumeToken();
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp
index b34c241..a101aaa 100644
--- a/lib/Parse/Parser.cpp
+++ b/lib/Parse/Parser.cpp
@@ -885,7 +885,7 @@
// If this is a template-id, annotate with a template-id or type token.
if (NextToken().is(tok::less)) {
- DeclPtrTy Template;
+ TemplateTy Template;
if (TemplateNameKind TNK
= Actions.isTemplateName(*Tok.getIdentifierInfo(),
CurScope, Template, &SS))
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index b7903c1..c46b044 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1691,7 +1691,7 @@
// C++ Templates [C++ 14]
//
virtual TemplateNameKind isTemplateName(IdentifierInfo &II, Scope *S,
- DeclPtrTy &TemplateDecl,
+ TemplateTy &Template,
const CXXScopeSpec *SS = 0);
bool DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl);
TemplateDecl *AdjustDeclIfTemplate(DeclPtrTy &Decl);
@@ -1742,20 +1742,19 @@
MultiTemplateParamsArg TemplateParameterLists,
AccessSpecifier AS);
- QualType CheckClassTemplateId(ClassTemplateDecl *ClassTemplate,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
- SourceLocation RAngleLoc);
+ QualType CheckTemplateIdType(TemplateName Template,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc);
virtual TypeResult
- ActOnClassTemplateId(DeclPtrTy Template, SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgs,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc,
- const CXXScopeSpec *SS);
+ ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgs,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc);
bool CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate,
ClassTemplateSpecializationDecl *PrevDecl,
@@ -1766,7 +1765,7 @@
ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc,
const CXXScopeSpec &SS,
- DeclPtrTy Template,
+ TemplateTy Template,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgs,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 773a2b1..56a016d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -27,19 +27,23 @@
/// passed to indicate the C++ scope in which the identifier will be
/// found.
TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S,
- DeclPtrTy &Template,
+ TemplateTy &TemplateResult,
const CXXScopeSpec *SS) {
NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
+ TemplateNameKind TNK = TNK_Non_template;
+ TemplateDecl *Template = 0;
+
if (IIDecl) {
- if (isa<TemplateDecl>(IIDecl)) {
- Template = DeclPtrTy::make(IIDecl);
+ if ((Template = dyn_cast<TemplateDecl>(IIDecl))) {
if (isa<FunctionTemplateDecl>(IIDecl))
- return TNK_Function_template;
- if (isa<ClassTemplateDecl>(IIDecl))
- return TNK_Class_template;
- assert(isa<TemplateTemplateParmDecl>(IIDecl) && "Unknown TemplateDecl");
- return TNK_Template_template_parm;
+ TNK = TNK_Function_template;
+ else if (isa<ClassTemplateDecl>(IIDecl))
+ TNK = TNK_Class_template;
+ else if (isa<TemplateTemplateParmDecl>(IIDecl))
+ TNK = TNK_Template_template_parm;
+ else
+ assert(false && "Unknown template declaration kind");
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(IIDecl)) {
// C++ [temp.local]p1:
// Like normal (non-template) classes, class templates have an
@@ -54,12 +58,12 @@
// specialization.
if (Record->isInjectedClassName()) {
Record = cast<CXXRecordDecl>(Context.getCanonicalDecl(Record));
- if ((Template = DeclPtrTy::make(Record->getDescribedClassTemplate())))
- return TNK_Class_template;
- if (ClassTemplateSpecializationDecl *Spec
+ if ((Template = Record->getDescribedClassTemplate()))
+ TNK = TNK_Class_template;
+ else if (ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Record)) {
- Template = DeclPtrTy::make(Spec->getSpecializedTemplate());
- return TNK_Class_template;
+ Template = Spec->getSpecializedTemplate();
+ TNK = TNK_Class_template;
}
}
}
@@ -67,7 +71,7 @@
// FIXME: What follows is a gross hack.
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) {
if (FD->getType()->isDependentType()) {
- Template = DeclPtrTy::make(FD);
+ TemplateResult = TemplateTy::make(FD);
return TNK_Function_template;
}
} else if (OverloadedFunctionDecl *Ovl
@@ -76,13 +80,25 @@
FEnd = Ovl->function_end();
F != FEnd; ++F) {
if ((*F)->getType()->isDependentType()) {
- Template = DeclPtrTy::make(Ovl);
+ TemplateResult = TemplateTy::make(Ovl);
return TNK_Function_template;
}
}
}
+
+ if (TNK != TNK_Non_template) {
+ if (SS && SS->isSet() && !SS->isInvalid()) {
+ NestedNameSpecifier *Qualifier
+ = static_cast<NestedNameSpecifier *>(SS->getScopeRep());
+ TemplateResult
+ = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier,
+ false,
+ Template));
+ } else
+ TemplateResult = TemplateTy::make(TemplateName(Template));
+ }
}
- return TNK_Non_template;
+ return TNK;
}
/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining
@@ -700,27 +716,30 @@
}
}
-QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate,
- SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- const TemplateArgument *TemplateArgs,
- unsigned NumTemplateArgs,
- SourceLocation RAngleLoc) {
+QualType Sema::CheckTemplateIdType(TemplateName Name,
+ SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs,
+ SourceLocation RAngleLoc) {
+ TemplateDecl *Template = Name.getAsTemplateDecl();
+ assert(Template && "Cannot handle dependent template-names yet");
+
// Check that the template argument list is well-formed for this
// template.
llvm::SmallVector<TemplateArgument, 16> ConvertedTemplateArgs;
- if (CheckTemplateArgumentList(ClassTemplate, TemplateLoc, LAngleLoc,
+ if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc,
TemplateArgs, NumTemplateArgs, RAngleLoc,
ConvertedTemplateArgs))
return QualType();
assert((ConvertedTemplateArgs.size() ==
- ClassTemplate->getTemplateParameters()->size()) &&
+ Template->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
QualType CanonType;
- if (ClassTemplateSpecializationType::anyDependentTemplateArguments(
+ if (TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs,
NumTemplateArgs)) {
// This class template specialization is a dependent
@@ -731,10 +750,11 @@
//
// template<typename T, typename U = T> struct A;
- CanonType = Context.getClassTemplateSpecializationType(ClassTemplate,
+ CanonType = Context.getTemplateSpecializationType(Name,
&ConvertedTemplateArgs[0],
ConvertedTemplateArgs.size());
- } else {
+ } else if (ClassTemplateDecl *ClassTemplate
+ = dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
@@ -764,35 +784,26 @@
// Build the fully-sugared type for this class template
// specialization, which refers back to the class template
// specialization we created or found.
- return Context.getClassTemplateSpecializationType(ClassTemplate,
- TemplateArgs,
- NumTemplateArgs,
- CanonType);
+ return Context.getTemplateSpecializationType(Name, TemplateArgs,
+ NumTemplateArgs, CanonType);
}
Action::TypeResult
-Sema::ActOnClassTemplateId(DeclPtrTy TemplateD, SourceLocation TemplateLoc,
- SourceLocation LAngleLoc,
- ASTTemplateArgsPtr TemplateArgsIn,
- SourceLocation *TemplateArgLocs,
- SourceLocation RAngleLoc,
- const CXXScopeSpec *SS) {
- TemplateDecl *Template = cast<TemplateDecl>(TemplateD.getAs<Decl>());
- ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template);
+Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
+ SourceLocation LAngleLoc,
+ ASTTemplateArgsPtr TemplateArgsIn,
+ SourceLocation *TemplateArgLocs,
+ SourceLocation RAngleLoc) {
+ TemplateName Template = TemplateD.getAsVal<TemplateName>();
// Translate the parser's template argument list in our AST format.
llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
- QualType Result = CheckClassTemplateId(ClassTemplate, TemplateLoc,
- LAngleLoc,
- &TemplateArgs[0],
- TemplateArgs.size(),
- RAngleLoc);
+ QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
+ &TemplateArgs[0], TemplateArgs.size(),
+ RAngleLoc);
- if (SS)
- Result = getQualifiedNameType(*SS, Result);
-
TemplateArgsIn.release();
return Result.getAsOpaquePtr();
}
@@ -1795,7 +1806,7 @@
Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
SourceLocation KWLoc,
const CXXScopeSpec &SS,
- DeclPtrTy TemplateD,
+ TemplateTy TemplateD,
SourceLocation TemplateNameLoc,
SourceLocation LAngleLoc,
ASTTemplateArgsPtr TemplateArgsIn,
@@ -1804,10 +1815,9 @@
AttributeList *Attr,
MultiTemplateParamsArg TemplateParameterLists) {
// Find the class template we're specializing
+ TemplateName Name = TemplateD.getAsVal<TemplateName>();
ClassTemplateDecl *ClassTemplate
- = dyn_cast_or_null<ClassTemplateDecl>(TemplateD.getAs<Decl>());
- if (!ClassTemplate)
- return true;
+ = cast<ClassTemplateDecl>(Name.getAsTemplateDecl());
// Check the validity of the template headers that introduce this
// template.
@@ -1937,11 +1947,11 @@
// name based on the "canonical" representation used to store the
// template arguments in the specialization.
QualType WrittenTy
- = Context.getClassTemplateSpecializationType(ClassTemplate,
- &TemplateArgs[0],
- TemplateArgs.size(),
+ = Context.getTemplateSpecializationType(Name,
+ &TemplateArgs[0],
+ TemplateArgs.size(),
Context.getTypeDeclType(Specialization));
- Specialization->setTypeAsWritten(getQualifiedNameType(SS, WrittenTy));
+ Specialization->setTypeAsWritten(WrittenTy);
TemplateArgsIn.release();
// C++ [temp.expl.spec]p9:
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 2578703..08f9601 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -114,7 +114,7 @@
case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: {
TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity);
std::string TemplateArgsStr
- = ClassTemplateSpecializationType::PrintTemplateArgumentList(
+ = TemplateSpecializationType::PrintTemplateArgumentList(
Active->TemplateArgs,
Active->NumTemplateArgs);
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
@@ -433,13 +433,12 @@
QualType
TemplateTypeInstantiator::
-InstantiateClassTemplateSpecializationType(
- const ClassTemplateSpecializationType *T,
+InstantiateTemplateSpecializationType(
+ const TemplateSpecializationType *T,
unsigned Quals) const {
llvm::SmallVector<TemplateArgument, 16> InstantiatedTemplateArgs;
InstantiatedTemplateArgs.reserve(T->getNumArgs());
- for (ClassTemplateSpecializationType::iterator Arg = T->begin(),
- ArgEnd = T->end();
+ for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
Arg != ArgEnd; ++Arg) {
switch (Arg->getKind()) {
case TemplateArgument::Type: {
@@ -473,12 +472,13 @@
// FIXME: We're missing the locations of the template name, '<', and
// '>'.
- return SemaRef.CheckClassTemplateId(cast<ClassTemplateDecl>(T->getTemplate()),
- Loc,
- SourceLocation(),
- &InstantiatedTemplateArgs[0],
- InstantiatedTemplateArgs.size(),
- SourceLocation());
+ // FIXME: Need to instantiate into the template name.
+ return SemaRef.CheckTemplateIdType(T->getTemplateName(),
+ Loc,
+ SourceLocation(),
+ &InstantiatedTemplateArgs[0],
+ InstantiatedTemplateArgs.size(),
+ SourceLocation());
}
QualType