diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-30 22:58:21 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-30 22:58:21 +0000 |
commit | 7532dc66648cfe7432c9fe66dec5225f0ab301c6 (patch) | |
tree | daa4d64ecc29357f90c6a51341fecdf79eae2025 /lib | |
parent | e31c0d206b872b056dc42c3af21b11d5de4edfd9 (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 78 | ||||
-rw-r--r-- | lib/AST/TemplateName.cpp | 54 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 60 | ||||
-rw-r--r-- | lib/AST/TypeSerialization.cpp | 22 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/MinimalAction.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 25 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 27 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 120 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 22 |
14 files changed, 268 insertions, 153 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index f3cf6b18eb..bb17954727 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -483,6 +483,10 @@ ASTContext::getTypeInfo(const Type *T) { 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::getTemplateTypeParmType(unsigned Depth, unsigned Index, } 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 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { 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 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { 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 0000000000..4e54fe4955 --- /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 0a3e8f91f0..6922dcc6c0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -93,8 +93,8 @@ QualType Type::getDesugaredType() const { 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 @@ const TemplateTypeParmType *Type::getAsTemplateTypeParmType() const { 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 EnumType::classof(const TagType *TT) { } bool -ClassTemplateSpecializationType:: +TemplateSpecializationType:: anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { for (unsigned Idx = 0; Idx < NumArgs; ++Idx) { switch (Args[Idx].getKind()) { @@ -997,17 +997,16 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { 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 @@ ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args, 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 @@ void ClassTemplateSpecializationType::Destroy(ASTContext& C) { } } -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 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString) const { InnerString = Name->getName() + InnerString; } -std::string ClassTemplateSpecializationType::PrintTemplateArgumentList( +std::string TemplateSpecializationType::PrintTemplateArgumentList( const TemplateArgument *Args, unsigned NumArgs) { std::string SpecString; @@ -1403,9 +1401,15 @@ std::string ClassTemplateSpecializationType::PrintTemplateArgumentList( } 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 @@ void TagType::getAsStringInternal(std::string &InnerString, 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 @@ void TagType::getAsStringInternal(std::string &InnerString, } 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 4f0334f47a..0562416da0 100644 --- a/lib/AST/TypeSerialization.cpp +++ b/lib/AST/TypeSerialization.cpp @@ -391,29 +391,17 @@ Type* TemplateTypeParmType::CreateImpl(ASTContext& Context, Deserializer& D) { } //===----------------------------------------------------------------------===// -// 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 7233bbf8e2..bde6fba137 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -561,7 +561,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, 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 85d7384c6c..5367c71b2c 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -392,6 +392,9 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { // 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 f31aef61d3..e99e96a7dc 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -135,7 +135,7 @@ bool MinimalAction::isCurrentClassName(const IdentifierInfo &, Scope *, 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 37a460cd41..fdfc7315a8 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -474,7 +474,7 @@ void Parser::ParseClassSpecifier(DeclSpec &DS, 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 dc57ac141c..4d419bbd87 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -117,7 +117,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { // 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 b962cbf646..8eda694864 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -406,7 +406,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { /// 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 @@ Parser::ParseTemplateIdAfterTemplateName(DeclPtrTy Template, /// 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 @@ void Parser::AnnotateTemplateIdToken(DeclPtrTy Template, TemplateNameKind TNK, 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 @@ bool Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) { 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 b34c241fd1..a101aaa732 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -885,7 +885,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { // 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 b7903c1b59..c46b044c29 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1691,7 +1691,7 @@ public: // 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 @@ public: 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 @@ public: 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 773a2b1b92..56a016d270 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -27,19 +27,23 @@ using namespace clang; /// 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 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, // 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 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, // 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 @@ TemplateNameKind Sema::isTemplateName(IdentifierInfo &II, Scope *S, 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 @@ translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, } } -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 @@ QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, // // 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 @@ QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, // 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, |