aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp72
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