diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 72 |
1 files changed, 39 insertions, 33 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 795e6025d96f..8ad5b5951ea3 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1224,9 +1224,17 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, } } + // If this is a templated friend in a dependent context we should not put it + // on the redecl chain. In some cases, the templated friend can be the most + // recent declaration tricking the template instantiator to make substitutions + // there. + // FIXME: Figure out how to combine with shouldLinkDependentDeclWithPrevious + bool ShouldAddRedecl + = !(TUK == TUK_Friend && CurContext->isDependentContext()); + CXXRecordDecl *NewClass = CXXRecordDecl::Create(Context, Kind, SemanticContext, KWLoc, NameLoc, Name, - PrevClassTemplate? + PrevClassTemplate && ShouldAddRedecl ? PrevClassTemplate->getTemplatedDecl() : nullptr, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(NewClass, SS); @@ -1245,7 +1253,11 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, ClassTemplateDecl *NewTemplate = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, DeclarationName(Name), TemplateParams, - NewClass, PrevClassTemplate); + NewClass); + + if (ShouldAddRedecl) + NewTemplate->setPreviousDecl(PrevClassTemplate); + NewClass->setDescribedClassTemplate(NewTemplate); if (ModulePrivateLoc.isValid()) @@ -1653,6 +1665,7 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> { typedef RecursiveASTVisitor<DependencyChecker> super; unsigned Depth; + bool FindLessThanDepth; // Whether we're looking for a use of a template parameter that makes the // overall construct type-dependent / a dependent type. This is strictly @@ -1663,25 +1676,16 @@ struct DependencyChecker : RecursiveASTVisitor<DependencyChecker> { bool Match; SourceLocation MatchLoc; - DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent) - : Depth(Depth), IgnoreNonTypeDependent(IgnoreNonTypeDependent), - Match(false) {} + DependencyChecker(unsigned Depth, bool IgnoreNonTypeDependent, + bool FindLessThanDepth = false) + : Depth(Depth), FindLessThanDepth(FindLessThanDepth), + IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) {} DependencyChecker(TemplateParameterList *Params, bool IgnoreNonTypeDependent) - : IgnoreNonTypeDependent(IgnoreNonTypeDependent), Match(false) { - NamedDecl *ND = Params->getParam(0); - if (TemplateTypeParmDecl *PD = dyn_cast<TemplateTypeParmDecl>(ND)) { - Depth = PD->getDepth(); - } else if (NonTypeTemplateParmDecl *PD = - dyn_cast<NonTypeTemplateParmDecl>(ND)) { - Depth = PD->getDepth(); - } else { - Depth = cast<TemplateTemplateParmDecl>(ND)->getDepth(); - } - } + : DependencyChecker(Params->getDepth(), IgnoreNonTypeDependent) {} bool Matches(unsigned ParmDepth, SourceLocation Loc = SourceLocation()) { - if (ParmDepth >= Depth) { + if (FindLessThanDepth ^ (ParmDepth >= Depth)) { Match = true; MatchLoc = Loc; return true; @@ -2336,15 +2340,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // A<T, T> have identical types when A is declared as: // // template<typename T, typename U = T> struct A; - TemplateName CanonName = Context.getCanonicalTemplateName(Name); - CanonType = Context.getTemplateSpecializationType(CanonName, - Converted); - - // FIXME: CanonType is not actually the canonical type, and unfortunately - // it is a TemplateSpecializationType that we will never use again. - // In the future, we need to teach getTemplateSpecializationType to only - // build the canonical type and return that to us. - CanonType = Context.getCanonicalType(CanonType); + CanonType = Context.getCanonicalTemplateSpecializationType(Name, Converted); // This might work out to be a current instantiation, in which // case the canonical type needs to be the InjectedClassNameType. @@ -3452,7 +3448,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, SourceLocation TemplateLoc, SourceLocation RAngleLoc, TemplateTypeParmDecl *Param, - SmallVectorImpl<TemplateArgument> &Converted) { + SmallVectorImpl<TemplateArgument> &Converted) { TypeSourceInfo *ArgType = Param->getDefaultArgumentInfo(); // If the argument type is dependent, instantiate it now based @@ -5838,6 +5834,15 @@ Sema::BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, return E; } +static bool isDependentOnOuter(NonTypeTemplateParmDecl *NTTP) { + if (NTTP->getDepth() == 0 || !NTTP->getType()->isDependentType()) + return false; + DependencyChecker Checker(NTTP->getDepth(), /*IgnoreNonTypeDependent*/ false, + /*FindLessThanDepth*/ true); + Checker.TraverseType(NTTP->getType()); + return Checker.Match; +} + /// \brief Match two template parameters within template parameter lists. static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, bool Complain, @@ -5894,11 +5899,10 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old, // If we are matching a template template argument to a template // template parameter and one of the non-type template parameter types - // is dependent, then we must wait until template instantiation time - // to actually compare the arguments. + // is dependent on an outer template's parameter, then we must wait until + // template instantiation time to actually compare the arguments. if (Kind == Sema::TPL_TemplateTemplateArgumentMatch && - (OldNTTP->getType()->isDependentType() || - NewNTTP->getType()->isDependentType())) + (isDependentOnOuter(OldNTTP) || isDependentOnOuter(NewNTTP))) return true; if (!S.Context.hasSameType(OldNTTP->getType(), NewNTTP->getType())) { @@ -7785,6 +7789,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setTemplateKeywordLoc(TemplateLoc); Specialization->setBraceRange(SourceRange()); + bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>(); if (Attr) ProcessDeclAttributeList(S, Specialization, Attr); @@ -7847,8 +7852,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Fix a TSK_ImplicitInstantiation followed by a // TSK_ExplicitInstantiationDefinition - if (Old_TSK == TSK_ImplicitInstantiation && - Specialization->hasAttr<DLLExportAttr>() && + bool NewlyDLLExported = + !PreviouslyDLLExported && Specialization->hasAttr<DLLExportAttr>(); + if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && (Context.getTargetInfo().getCXXABI().isMicrosoft() || Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { // In the MS ABI, an explicit instantiation definition can add a dll |