summaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp126
1 files changed, 97 insertions, 29 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 0daa33cfbef5..af41e231134d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -150,7 +150,7 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D,
break;
// If this function is a generic lambda specialization, we are done.
- if (isGenericLambdaCallOperatorSpecialization(Function))
+ if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function))
break;
} else if (FunctionTemplateDecl *FunTmpl
@@ -203,9 +203,12 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const {
case DefaultTemplateArgumentChecking:
case DeclaringSpecialMember:
+ case DeclaringImplicitEqualityComparison:
case DefiningSynthesizedFunction:
case ExceptionSpecEvaluation:
case ConstraintSubstitution:
+ case ParameterMappingSubstitution:
+ case ConstraintNormalization:
case RewritingOperatorAsSpaceship:
return false;
@@ -363,7 +366,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintsCheck, TemplateDecl *Template,
+ ConstraintsCheck, NamedDecl *Template,
ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintsCheck,
@@ -372,13 +375,29 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema::InstantiatingTemplate::InstantiatingTemplate(
Sema &SemaRef, SourceLocation PointOfInstantiation,
- ConstraintSubstitution, TemplateDecl *Template,
+ ConstraintSubstitution, NamedDecl *Template,
sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange)
: InstantiatingTemplate(
SemaRef, CodeSynthesisContext::ConstraintSubstitution,
PointOfInstantiation, InstantiationRange, Template, nullptr,
{}, &DeductionInfo) {}
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ConstraintNormalization, NamedDecl *Template,
+ SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef, CodeSynthesisContext::ConstraintNormalization,
+ PointOfInstantiation, InstantiationRange, Template) {}
+
+Sema::InstantiatingTemplate::InstantiatingTemplate(
+ Sema &SemaRef, SourceLocation PointOfInstantiation,
+ ParameterMappingSubstitution, NamedDecl *Template,
+ SourceRange InstantiationRange)
+ : InstantiatingTemplate(
+ SemaRef, CodeSynthesisContext::ParameterMappingSubstitution,
+ PointOfInstantiation, InstantiationRange, Template) {}
+
void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
Ctx.SavedInNonInstantiationSFINAEContext = InNonInstantiationSFINAEContext;
InNonInstantiationSFINAEContext = false;
@@ -671,14 +690,29 @@ void Sema::PrintInstantiationStack() {
<< cast<CXXRecordDecl>(Active->Entity) << Active->SpecialMember;
break;
+ case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
+ Diags.Report(Active->Entity->getLocation(),
+ diag::note_in_declaration_of_implicit_equality_comparison);
+ break;
+
case CodeSynthesisContext::DefiningSynthesizedFunction: {
- // FIXME: For synthesized members other than special members, produce a note.
- auto *MD = dyn_cast<CXXMethodDecl>(Active->Entity);
- auto CSM = MD ? getSpecialMember(MD) : CXXInvalid;
- if (CSM != CXXInvalid) {
+ // FIXME: For synthesized functions that are not defaulted,
+ // produce a note.
+ auto *FD = dyn_cast<FunctionDecl>(Active->Entity);
+ DefaultedFunctionKind DFK =
+ FD ? getDefaultedFunctionKind(FD) : DefaultedFunctionKind();
+ if (DFK.isSpecialMember()) {
+ auto *MD = cast<CXXMethodDecl>(FD);
Diags.Report(Active->PointOfInstantiation,
diag::note_member_synthesized_at)
- << CSM << Context.getTagDeclType(MD->getParent());
+ << MD->isExplicitlyDefaulted() << DFK.asSpecialMember()
+ << Context.getTagDeclType(MD->getParent());
+ } else if (DFK.isComparison()) {
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_comparison_synthesized_at)
+ << (int)DFK.asComparison()
+ << Context.getTagDeclType(
+ cast<CXXRecordDecl>(FD->getLexicalDeclContext()));
}
break;
}
@@ -691,29 +725,43 @@ void Sema::PrintInstantiationStack() {
case CodeSynthesisContext::Memoization:
break;
- case CodeSynthesisContext::ConstraintsCheck:
- if (auto *CD = dyn_cast<ConceptDecl>(Active->Entity)) {
- SmallVector<char, 128> TemplateArgsStr;
- llvm::raw_svector_ostream OS(TemplateArgsStr);
- CD->printName(OS);
- printTemplateArgumentList(OS, Active->template_arguments(),
- getPrintingPolicy());
- Diags.Report(Active->PointOfInstantiation,
- diag::note_concept_specialization_here)
- << OS.str()
- << Active->InstantiationRange;
- break;
+ case CodeSynthesisContext::ConstraintsCheck: {
+ unsigned DiagID = 0;
+ if (isa<ConceptDecl>(Active->Entity))
+ DiagID = diag::note_concept_specialization_here;
+ else if (isa<TemplateDecl>(Active->Entity))
+ DiagID = diag::note_checking_constraints_for_template_id_here;
+ else if (isa<VarTemplatePartialSpecializationDecl>(Active->Entity))
+ DiagID = diag::note_checking_constraints_for_var_spec_id_here;
+ else {
+ assert(isa<ClassTemplatePartialSpecializationDecl>(Active->Entity));
+ DiagID = diag::note_checking_constraints_for_class_spec_id_here;
}
- // TODO: Concepts - implement this for constrained templates and partial
- // specializations.
- llvm_unreachable("only concept constraints are supported right now");
+ SmallVector<char, 128> TemplateArgsStr;
+ llvm::raw_svector_ostream OS(TemplateArgsStr);
+ cast<NamedDecl>(Active->Entity)->printName(OS);
+ printTemplateArgumentList(OS, Active->template_arguments(),
+ getPrintingPolicy());
+ Diags.Report(Active->PointOfInstantiation, DiagID) << OS.str()
+ << Active->InstantiationRange;
break;
-
+ }
case CodeSynthesisContext::ConstraintSubstitution:
Diags.Report(Active->PointOfInstantiation,
diag::note_constraint_substitution_here)
<< Active->InstantiationRange;
break;
+ case CodeSynthesisContext::ConstraintNormalization:
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_constraint_normalization_here)
+ << cast<NamedDecl>(Active->Entity)->getName()
+ << Active->InstantiationRange;
+ break;
+ case CodeSynthesisContext::ParameterMappingSubstitution:
+ Diags.Report(Active->PointOfInstantiation,
+ diag::note_parameter_mapping_substitution_here)
+ << Active->InstantiationRange;
+ break;
}
}
}
@@ -738,6 +786,8 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
case CodeSynthesisContext::ExceptionSpecInstantiation:
case CodeSynthesisContext::ConstraintsCheck:
+ case CodeSynthesisContext::ParameterMappingSubstitution:
+ case CodeSynthesisContext::ConstraintNormalization:
// This is a template instantiation, so there is no SFINAE.
return None;
@@ -759,6 +809,7 @@ Optional<TemplateDeductionInfo *> Sema::isSFINAEContext() const {
return Active->DeductionInfo;
case CodeSynthesisContext::DeclaringSpecialMember:
+ case CodeSynthesisContext::DeclaringImplicitEqualityComparison:
case CodeSynthesisContext::DefiningSynthesizedFunction:
case CodeSynthesisContext::RewritingOperatorAsSpaceship:
// This happens in a context unrelated to template instantiation, so
@@ -1514,8 +1565,12 @@ TemplateInstantiator::TransformFunctionTypeParam(ParmVarDecl *OldParm,
int indexAdjustment,
Optional<unsigned> NumExpansions,
bool ExpectParameterPack) {
- return SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
- NumExpansions, ExpectParameterPack);
+ auto NewParm =
+ SemaRef.SubstParmVarDecl(OldParm, TemplateArgs, indexAdjustment,
+ NumExpansions, ExpectParameterPack);
+ if (NewParm && SemaRef.getLangOpts().OpenCL)
+ SemaRef.deduceOpenCLAddressSpace(NewParm);
+ return NewParm;
}
QualType
@@ -2219,11 +2274,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Finish checking fields.
ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields,
SourceLocation(), SourceLocation(), ParsedAttributesView());
- CheckCompletedCXXClass(Instantiation);
+ CheckCompletedCXXClass(nullptr, Instantiation);
// Default arguments are parsed, if not instantiated. We can go instantiate
- // default arg exprs for default constructors if necessary now.
- ActOnFinishCXXNonNestedClass(Instantiation);
+ // default arg exprs for default constructors if necessary now. Unless we're
+ // parsing a class, in which case wait until that's finished.
+ if (ParsingClassDepth == 0)
+ ActOnFinishCXXNonNestedClass();
// Instantiate late parsed attributes, and attach them to their decls.
// See Sema::InstantiateAttrs
@@ -2900,6 +2957,17 @@ Sema::SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs) {
return Instantiator.TransformStmt(S);
}
+bool Sema::SubstTemplateArguments(
+ ArrayRef<TemplateArgumentLoc> Args,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateArgumentListInfo &Out) {
+ TemplateInstantiator Instantiator(*this, TemplateArgs,
+ SourceLocation(),
+ DeclarationName());
+ return Instantiator.TransformTemplateArguments(Args.begin(), Args.end(),
+ Out);
+}
+
ExprResult
Sema::SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs) {
if (!E)