diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 21 | ||||
-rw-r--r-- | clang/lib/AST/DeclTemplate.cpp | 9 | ||||
-rw-r--r-- | clang/lib/AST/Type.cpp | 111 | ||||
-rw-r--r-- | clang/lib/AST/TypeSerialization.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 306 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 41 |
8 files changed, 339 insertions, 188 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 4579fb5a605..a51f432880e 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1309,14 +1309,15 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, QualType ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template, + const TemplateArgument *Args, unsigned NumArgs, - uintptr_t *Args, bool *ArgIsType, QualType Canon) { - Canon = getCanonicalType(Canon); + if (!Canon.isNull()) + Canon = getCanonicalType(Canon); llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args, - ArgIsType); + ClassTemplateSpecializationType::Profile(ID, Template, Args, NumArgs); + void *InsertPos = 0; ClassTemplateSpecializationType *Spec = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -1324,13 +1325,11 @@ ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template, if (Spec) return QualType(Spec, 0); - void *Mem = Allocate(sizeof(ClassTemplateSpecializationType) + - (sizeof(uintptr_t) * - (ClassTemplateSpecializationType:: - getNumPackedWords(NumArgs) + - NumArgs)), 8); - Spec = new (Mem) ClassTemplateSpecializationType(Template, NumArgs, Args, - ArgIsType, Canon); + void *Mem = Allocate((sizeof(ClassTemplateSpecializationType) + + sizeof(TemplateArgument) * NumArgs), + 8); + Spec = new (Mem) ClassTemplateSpecializationType(Template, Args, NumArgs, + Canon); Types.push_back(Spec); ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos); diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index ed4fd44e707..ac76c258a71 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -145,6 +145,15 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const { } //===----------------------------------------------------------------------===// +// TemplateArgument Implementation +//===----------------------------------------------------------------------===// + +TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) { + TypeOrValue = reinterpret_cast<uintptr_t>(E); + StartLoc = E->getSourceRange().getBegin(); +} + +//===----------------------------------------------------------------------===// // ClassTemplateSpecializationDecl Implementation //===----------------------------------------------------------------------===// ClassTemplateSpecializationDecl:: diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 3b06b4ee28d..412b0cf8341 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -921,59 +921,77 @@ bool EnumType::classof(const TagType *TT) { return isa<EnumDecl>(TT->getDecl()); } -void +bool ClassTemplateSpecializationType:: -packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words) { - const unsigned BitsPerWord = sizeof(uintptr_t) * 8; - - for (unsigned PW = 0, NumPackedWords = getNumPackedWords(NumArgs), Arg = 0; - PW != NumPackedWords; ++PW) { - uintptr_t Word = 0; - for (unsigned Bit = 0; Bit < BitsPerWord && Arg < NumArgs; ++Bit, ++Arg) { - Word <<= 1; - Word |= Values[Arg]; +anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) { + for (unsigned Idx = 0; Idx < NumArgs; ++Idx) { + switch (Args[Idx].getKind()) { + case TemplateArgument::Type: + if (Args[Idx].getAsType()->isDependentType()) + return true; + break; + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + // Never dependent + break; + + case TemplateArgument::Expression: + if (Args[Idx].getAsExpr()->isTypeDependent() || + Args[Idx].getAsExpr()->isValueDependent()) + return true; + break; } - Words[PW] = Word; } + + return false; } ClassTemplateSpecializationType:: -ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs, - uintptr_t *Args, bool *ArgIsType, - QualType Canon) - : Type(ClassTemplateSpecialization, Canon, /*FIXME:Dependent=*/false), - Template(T), NumArgs(NumArgs) +ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args, + unsigned NumArgs, QualType Canon) + : Type(ClassTemplateSpecialization, + Canon.isNull()? QualType(this, 0) : Canon, + /*FIXME: Check for dependent template */ + anyDependentTemplateArguments(Args, NumArgs)), + Template(T), NumArgs(NumArgs) { - uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1); + assert((!Canon.isNull() || + anyDependentTemplateArguments(Args, NumArgs)) && + "No canonical type for non-dependent class template specialization"); - // Pack the argument-is-type values into the words just after the - // class template specialization type. - packBooleanValues(NumArgs, ArgIsType, Data); - - // Copy the template arguments after the packed words. - Data += getNumPackedWords(NumArgs); + TemplateArgument *TemplateArgs + = reinterpret_cast<TemplateArgument *>(this + 1); for (unsigned Arg = 0; Arg < NumArgs; ++Arg) - Data[Arg] = Args[Arg]; + new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]); } void ClassTemplateSpecializationType::Destroy(ASTContext& C) { for (unsigned Arg = 0; Arg < NumArgs; ++Arg) - if (!isArgType(Arg)) - getArgAsExpr(Arg)->Destroy(C); + if (Expr *E = getArg(Arg).getAsExpr()) + E->Destroy(C); +} + +ClassTemplateSpecializationType::iterator +ClassTemplateSpecializationType::end() const { + return begin() + getNumArgs(); } -uintptr_t -ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const { - const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1); - Data += getNumPackedWords(NumArgs); - return Data[Arg]; +const TemplateArgument & +ClassTemplateSpecializationType::getArg(unsigned Idx) const { + assert(Idx < getNumArgs() && "Template argument out of range"); + return getArgs()[Idx]; } -bool ClassTemplateSpecializationType::isArgType(unsigned Arg) const { - const unsigned BitsPerWord = sizeof(uintptr_t) * 8; - const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1); - Data += Arg / BitsPerWord; - return (*Data >> ((NumArgs - Arg) % BitsPerWord - 1)) & 0x01; +void +ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, + TemplateDecl *T, + const TemplateArgument *Args, + unsigned NumArgs) { + ID.AddPointer(T); + + for (unsigned Idx = 0; Idx < NumArgs; ++Idx) + Args[Idx].Profile(ID); } //===----------------------------------------------------------------------===// @@ -1280,11 +1298,24 @@ getAsStringInternal(std::string &InnerString) const { // Print the argument into a string. std::string ArgString; - if (isArgType(Arg)) - getArgAsType(Arg).getAsStringInternal(ArgString); - else { + switch (getArg(Arg).getKind()) { + case TemplateArgument::Type: + getArg(Arg).getAsType().getAsStringInternal(ArgString); + break; + + case TemplateArgument::Declaration: + ArgString = cast<NamedDecl>(getArg(Arg).getAsDecl())->getNameAsString(); + break; + + case TemplateArgument::Integral: + ArgString = getArg(Arg).getAsIntegral()->toString(10, true); + break; + + case TemplateArgument::Expression: { llvm::raw_string_ostream s(ArgString); - getArgAsExpr(Arg)->printPretty(s); + getArg(Arg).getAsExpr()->printPretty(s); + break; + } } // If this is the first argument and its string representation diff --git a/clang/lib/AST/TypeSerialization.cpp b/clang/lib/AST/TypeSerialization.cpp index b7a8f1a366d..1b9fed4866a 100644 --- a/clang/lib/AST/TypeSerialization.cpp +++ b/clang/lib/AST/TypeSerialization.cpp @@ -390,13 +390,7 @@ void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const { S.Emit(getCanonicalTypeInternal()); S.EmitPtr(Template); S.EmitInt(NumArgs); - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - S.EmitBool(isArgType(Arg)); - if (isArgType(Arg)) - S.Emit(getArgAsType(Arg)); - else - S.EmitOwnedPtr(getArgAsExpr(Arg)); - } + // FIXME: Serialize class template specialization types } Type* @@ -409,19 +403,10 @@ CreateImpl(ASTContext& Context, Deserializer& D) { TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>()); unsigned NumArgs = D.ReadInt(); - for (unsigned Arg = 0; Arg < NumArgs; ++Arg) { - bool IsType = D.ReadBool(); - ArgIsType.push_back(IsType); - if (IsType) - Args.push_back( - reinterpret_cast<uintptr_t>(QualType::ReadVal(D).getAsOpaquePtr())); - else - Args.push_back(reinterpret_cast<uintptr_t>(D.ReadOwnedPtr<Expr>(Context))); - } - - return Context.getClassTemplateSpecializationType(Template, NumArgs, - &Args[0], &ArgIsType[0], - Canon).getTypePtr(); + // FIXME: De-serialize class template specialization types + (void)Template; + (void)NumArgs; + return 0; } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 4ac8ffc0fb8..83be8959090 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1601,6 +1601,13 @@ public: AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists); + QualType CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc); + virtual TypeResult ActOnClassTemplateId(DeclTy *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -1630,8 +1637,8 @@ public: bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ASTTemplateArgsPtr& TemplateArgs, - SourceLocation *TemplateArgLocs, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, SourceLocation RAngleLoc, llvm::SmallVectorImpl<TemplateArgument> &Converted); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 7773b9e6150..e9e2e3c2ace 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -383,7 +383,8 @@ Sema::BaseResult Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange, bool Virtual, AccessSpecifier Access, TypeTy *basetype, SourceLocation BaseLoc) { - CXXRecordDecl *Class = (CXXRecordDecl*)classdecl; + AdjustDeclIfTemplate(classdecl); + CXXRecordDecl *Class = cast<CXXRecordDecl>((Decl*)classdecl); QualType BaseType = QualType::getFromOpaquePtr(basetype); if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange, Virtual, Access, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a55e3a51845..281984de2c9 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -658,61 +658,115 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, return Invalid; } -Action::TypeResult -Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, +/// \brief Translates template arguments as provided by the parser +/// into template arguments used by semantic analysis. +static void +translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, SourceLocation *TemplateArgLocs, - SourceLocation RAngleLoc, - const CXXScopeSpec *SS) { - TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD)); - ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template); + llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) { + TemplateArgs.reserve(TemplateArgsIn.size()); + + void **Args = TemplateArgsIn.getArgs(); + bool *ArgIsType = TemplateArgsIn.getArgIsType(); + for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) { + TemplateArgs.push_back( + ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg], + QualType::getFromOpaquePtr(Args[Arg])) + : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg]))); + } +} +QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc) { // Check that the template argument list is well-formed for this // template. llvm::SmallVector<TemplateArgument, 16> ConvertedTemplateArgs; - if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, - TemplateArgs, TemplateArgLocs, RAngleLoc, + if (CheckTemplateArgumentList(ClassTemplate, TemplateLoc, LAngleLoc, + TemplateArgs, NumTemplateArgs, RAngleLoc, ConvertedTemplateArgs)) - return true; + return QualType(); assert((ConvertedTemplateArgs.size() == - Template->getTemplateParameters()->size()) && + ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); - // Find the class template specialization declaration that - // corresponds to these arguments. - llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size()); - void *InsertPos = 0; - ClassTemplateSpecializationDecl *Decl - = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); - if (!Decl) { - // This is the first time we have referenced this class template - // specialization. Create the canonical declaration and add it to - // the set of specializations. - Decl = ClassTemplateSpecializationDecl::Create(Context, + QualType CanonType; + + if (ClassTemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, + NumTemplateArgs)) { + // This class template specialization is a dependent + // type. Therefore, its canonical type is another class template + // specialization type that contains all of the converted + // arguments in canonical form. This ensures that, e.g., A<T> and + // A<T, T> have identical types when A is declared as: + // + // template<typename T, typename U = T> struct A; + + CanonType = Context.getClassTemplateSpecializationType(ClassTemplate, + &ConvertedTemplateArgs[0], + ConvertedTemplateArgs.size()); + } else { + // Find the class template specialization declaration that + // corresponds to these arguments. + llvm::FoldingSetNodeID ID; + ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0], + ConvertedTemplateArgs.size()); + void *InsertPos = 0; + ClassTemplateSpecializationDecl *Decl + = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + if (!Decl) { + // This is the first time we have referenced this class template + // specialization. Create the canonical declaration and add it to + // the set of specializations. + Decl = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), - TemplateLoc, - ClassTemplate, - &ConvertedTemplateArgs[0], - ConvertedTemplateArgs.size(), - 0); - ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); - Decl->setLexicalDeclContext(CurContext); + TemplateLoc, + ClassTemplate, + &ConvertedTemplateArgs[0], + ConvertedTemplateArgs.size(), + 0); + ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); + Decl->setLexicalDeclContext(CurContext); + } + + CanonType = Context.getTypeDeclType(Decl); } // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - QualType Result - = Context.getClassTemplateSpecializationType(Template, - TemplateArgs.size(), - reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()), - TemplateArgs.getArgIsType(), - Context.getTypeDeclType(Decl)); - TemplateArgs.release(); + return Context.getClassTemplateSpecializationType(ClassTemplate, + TemplateArgs, + NumTemplateArgs, + CanonType); +} + +Action::TypeResult +Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc, + const CXXScopeSpec *SS) { + TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD)); + ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template); + + // 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); + + TemplateArgsIn.release(); return Result.getAsOpaquePtr(); } @@ -721,13 +775,13 @@ Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc, bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - ASTTemplateArgsPtr& Args, - SourceLocation *TemplateArgLocs, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, SourceLocation RAngleLoc, llvm::SmallVectorImpl<TemplateArgument> &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); - unsigned NumArgs = Args.size(); + unsigned NumArgs = NumTemplateArgs; bool Invalid = false; if (NumArgs > NumParams || @@ -737,7 +791,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // arguments. SourceRange Range; if (NumArgs > NumParams) - Range = SourceRange(TemplateArgLocs[NumParams], RAngleLoc); + Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc); Diag(TemplateLoc, diag::err_template_arg_list_different_arity) << (NumArgs > NumParams) << (isa<ClassTemplateDecl>(Template)? 0 : @@ -759,9 +813,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ParamEnd = Params->end(); Param != ParamEnd; ++Param, ++ArgIdx) { // Decode the template argument - QualType ArgType; - Expr *ArgExpr = 0; - SourceLocation ArgLoc; + TemplateArgument Arg; if (ArgIdx >= NumArgs) { // Retrieve the default template argument from the template // parameter. @@ -769,7 +821,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (!TTP->hasDefaultArgument()) break; - ArgType = TTP->getDefaultArgument(); + QualType ArgType = TTP->getDefaultArgument(); // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. @@ -781,15 +833,14 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (ArgType.isNull()) return true; - ArgLoc = TTP->getDefaultArgumentLoc(); + Arg = TemplateArgument(TTP->getLocation(), ArgType); } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { if (!NTTP->hasDefaultArgument()) break; // FIXME: Instantiate default argument - ArgExpr = NTTP->getDefaultArgument(); - ArgLoc = NTTP->getDefaultArgumentLoc(); + Arg = TemplateArgument(NTTP->getDefaultArgument()); } else { TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); @@ -798,29 +849,24 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, break; // FIXME: Instantiate default argument - ArgExpr = TempParm->getDefaultArgument(); - ArgLoc = TempParm->getDefaultArgumentLoc(); + Arg = TemplateArgument(TempParm->getDefaultArgument()); } } else { // Retrieve the template argument produced by the user. - ArgLoc = TemplateArgLocs[ArgIdx]; - - if (Args.getArgIsType()[ArgIdx]) - ArgType = QualType::getFromOpaquePtr(Args.getArgs()[ArgIdx]); - else - ArgExpr = reinterpret_cast<Expr *>(Args.getArgs()[ArgIdx]); + Arg = TemplateArgs[ArgIdx]; } if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) { // Check template type parameters. - if (!ArgType.isNull()) { - if (CheckTemplateArgument(TTP, ArgType, ArgLoc)) + if (Arg.getKind() == TemplateArgument::Type) { + if (CheckTemplateArgument(TTP, Arg.getAsType(), Arg.getLocation())) Invalid = true; // Add the converted template type argument. Converted.push_back( - TemplateArgument(Context.getCanonicalType(ArgType))); + TemplateArgument(Arg.getLocation(), + Context.getCanonicalType(Arg.getAsType()))); continue; } @@ -829,9 +875,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // type shall be a type-id. // We have a template type parameter but the template argument - // is an expression. - Diag(ArgExpr->getSourceRange().getBegin(), - diag::err_template_arg_must_be_type); + // is not a type. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_type); Diag((*Param)->getLocation(), diag::note_template_param_here); Invalid = true; } else if (NonTypeTemplateParmDecl *NTTP @@ -859,50 +904,81 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, } } - if (ArgExpr) { - if (CheckTemplateArgument(NTTP, NTTPType, ArgExpr, &Converted)) + switch (Arg.getKind()) { + case TemplateArgument::Expression: { + Expr *E = Arg.getAsExpr(); + if (CheckTemplateArgument(NTTP, NTTPType, E, &Converted)) Invalid = true; - continue; + break; } - // We have a non-type template parameter but the template - // argument is a type. - - // C++ [temp.arg]p2: - // In a template-argument, an ambiguity between a type-id and - // an expression is resolved to a type-id, regardless of the - // form of the corresponding template-parameter. - // - // We warn specifically about this case, since it can be rather - // confusing for users. - if (ArgType->isFunctionType()) - Diag(ArgLoc, diag::err_template_arg_nontype_ambig) - << ArgType; - else - Diag(ArgLoc, diag::err_template_arg_must_be_expr); - Diag((*Param)->getLocation(), diag::note_template_param_here); - Invalid = true; + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + // We've already checked this template argument, so just copy + // it to the list of converted arguments. + Converted.push_back(Arg); + break; + + case TemplateArgument::Type: + // We have a non-type template parameter but the template + // argument is a type. + + // C++ [temp.arg]p2: + // In a template-argument, an ambiguity between a type-id and + // an expression is resolved to a type-id, regardless of the + // form of the corresponding template-parameter. + // + // We warn specifically about this case, since it can be rather + // confusing for users. + if (Arg.getAsType()->isFunctionType()) + Diag(Arg.getLocation(), diag::err_template_arg_nontype_ambig) + << Arg.getAsType(); + else + Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr); + Diag((*Param)->getLocation(), diag::note_template_param_here); + Invalid = true; + } } else { // Check template template parameters. TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - if (ArgExpr && isa<DeclRefExpr>(ArgExpr) && - isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) { - if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr))) - Invalid = true; - - // Add the converted template argument. - // FIXME: Need the "canonical" template declaration! - Converted.push_back( - TemplateArgument(cast<DeclRefExpr>(ArgExpr)->getDecl())); - continue; + switch (Arg.getKind()) { + case TemplateArgument::Expression: { + Expr *ArgExpr = Arg.getAsExpr(); + if (ArgExpr && isa<DeclRefExpr>(ArgExpr) && + isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) { + if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr))) + Invalid = true; + + // Add the converted template argument. + // FIXME: Need the "canonical" template declaration! + Converted.push_back( + TemplateArgument(Arg.getLocation(), + cast<DeclRefExpr>(ArgExpr)->getDecl())); + continue; + } + } + // fall through + + case TemplateArgument::Type: { + // We have a template template parameter but the template + // argument does not refer to a template. + Diag(Arg.getLocation(), diag::err_template_arg_must_be_template); + Invalid = true; + break; } - // We have a template template parameter but the template - // argument does not refer to a template. - Diag(ArgLoc, diag::err_template_arg_must_be_template); - Invalid = true; + case TemplateArgument::Declaration: + // We've already checked this template argument, so just copy + // it to the list of converted arguments. + Converted.push_back(Arg); + break; + + case TemplateArgument::Integral: + assert(false && "Integral argument with template template parameter"); + break; + } } } @@ -1109,11 +1185,16 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, QualType InstantiatedParamType, Expr *&Arg, llvm::SmallVectorImpl<TemplateArgument> *Converted) { + SourceLocation StartLoc = Arg->getSourceRange().getBegin(); + // If either the parameter has a dependent type or the argument is // type-dependent, there's nothing we can check now. // FIXME: Add template argument to Converted! - if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) + if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) { + // FIXME: Produce a cloned, canonical expression? + Converted->push_back(TemplateArgument(Arg)); return false; + } // C++ [temp.arg.nontype]p5: // The following conversions are performed on each expression used @@ -1188,7 +1269,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, IntegerType->isSignedIntegerType()); CanonicalArg = Value; - Converted->push_back(TemplateArgument(CanonicalArg)); + Converted->push_back(TemplateArgument(StartLoc, CanonicalArg)); } return false; @@ -1252,7 +1333,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; if (Converted) - Converted->push_back(TemplateArgument(Member)); + Converted->push_back(TemplateArgument(StartLoc, Member)); return false; } @@ -1262,7 +1343,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; if (Converted) - Converted->push_back(TemplateArgument(Entity)); + Converted->push_back(TemplateArgument(StartLoc, Entity)); return false; } @@ -1297,7 +1378,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; if (Converted) - Converted->push_back(TemplateArgument(Entity)); + Converted->push_back(TemplateArgument(StartLoc, Entity)); return false; } @@ -1339,7 +1420,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; if (Converted) - Converted->push_back(TemplateArgument(Entity)); + Converted->push_back(TemplateArgument(StartLoc, Entity)); return false; } @@ -1366,7 +1447,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; if (Converted) - Converted->push_back(TemplateArgument(Member)); + Converted->push_back(TemplateArgument(StartLoc, Member)); return false; } @@ -1649,7 +1730,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, DeclTy *TemplateD, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, + ASTTemplateArgsPtr TemplateArgsIn, SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, @@ -1701,12 +1782,16 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, Kind = ClassTemplate->getTemplatedDecl()->getTagKind(); } + // Translate the parser's template argument list in our AST format. + llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + // Check that the template argument list is well-formed for this // template. llvm::SmallVector<TemplateArgument, 16> ConvertedTemplateArgs; if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, - TemplateArgs, TemplateArgLocs, RAngleLoc, - ConvertedTemplateArgs)) + &TemplateArgs[0], TemplateArgs.size(), + RAngleLoc, ConvertedTemplateArgs)) return 0; assert((ConvertedTemplateArgs.size() == @@ -1786,11 +1871,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // template arguments in the specialization. Specialization->setTypeAsWritten( Context.getClassTemplateSpecializationType(ClassTemplate, + &TemplateArgs[0], TemplateArgs.size(), - reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()), - TemplateArgs.getArgIsType(), Context.getTypeDeclType(Specialization))); - TemplateArgs.release(); + TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: // A template explicit specialization is in the scope of the diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index faeebc06808..71bba49af9d 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -302,9 +302,44 @@ TemplateTypeInstantiator:: InstantiateClassTemplateSpecializationType( const ClassTemplateSpecializationType *T, unsigned Quals) const { - // FIXME: Implement this - assert(false && "Cannot instantiate ClassTemplateSpecializationType yet"); - return QualType(); + llvm::SmallVector<TemplateArgument, 16> InstantiatedTemplateArgs; + InstantiatedTemplateArgs.reserve(T->getNumArgs()); + for (ClassTemplateSpecializationType::iterator Arg = T->begin(), + ArgEnd = T->end(); + Arg != ArgEnd; ++Arg) { + switch (Arg->getKind()) { + case TemplateArgument::Type: { + QualType T = SemaRef.InstantiateType(Arg->getAsType(), + TemplateArgs, NumTemplateArgs, + Arg->getLocation(), + DeclarationName()); + if (T.isNull()) + return QualType(); + + InstantiatedTemplateArgs.push_back( + TemplateArgument(Arg->getLocation(), T)); + break; + } + + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + InstantiatedTemplateArgs.push_back(*Arg); + break; + + case TemplateArgument::Expression: + assert(false && "Cannot instantiate expressions yet"); + break; + } + } + + // 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()); } QualType |