aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp204
1 files changed, 125 insertions, 79 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
index e9b38551683c..d94cb0d0f485 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaTemplate.cpp
@@ -778,7 +778,7 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
SourceLocation Loc,
IdentifierInfo *Name) {
NamedDecl *PrevDecl = SemaRef.LookupSingleName(
- S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+ S, Name, Loc, Sema::LookupOrdinaryName, Sema::ForVisibleRedeclaration);
if (PrevDecl && PrevDecl->isTemplateParameter())
SemaRef.DiagnoseTemplateParameterShadow(Loc, PrevDecl);
}
@@ -792,7 +792,7 @@ static void maybeDiagnoseTemplateParameterShadow(Sema &SemaRef, Scope *S,
/// ParamNameLoc is the location of the parameter name (if any).
/// If the type parameter has a default argument, it will be added
/// later via ActOnTypeParameterDefault.
-Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
+NamedDecl *Sema::ActOnTypeParameter(Scope *S, bool Typename,
SourceLocation EllipsisLoc,
SourceLocation KeyLoc,
IdentifierInfo *ParamName,
@@ -922,13 +922,67 @@ QualType Sema::CheckNonTypeTemplateParameterType(QualType T,
return QualType();
}
-Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
+NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
unsigned Depth,
unsigned Position,
SourceLocation EqualLoc,
Expr *Default) {
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
+ // Check that we have valid decl-specifiers specified.
+ auto CheckValidDeclSpecifiers = [this, &D] {
+ // C++ [temp.param]
+ // p1
+ // template-parameter:
+ // ...
+ // parameter-declaration
+ // p2
+ // ... A storage class shall not be specified in a template-parameter
+ // declaration.
+ // [dcl.typedef]p1:
+ // The typedef specifier [...] shall not be used in the decl-specifier-seq
+ // of a parameter-declaration
+ const DeclSpec &DS = D.getDeclSpec();
+ auto EmitDiag = [this](SourceLocation Loc) {
+ Diag(Loc, diag::err_invalid_decl_specifier_in_nontype_parm)
+ << FixItHint::CreateRemoval(Loc);
+ };
+ if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified)
+ EmitDiag(DS.getStorageClassSpecLoc());
+
+ if (DS.getThreadStorageClassSpec() != TSCS_unspecified)
+ EmitDiag(DS.getThreadStorageClassSpecLoc());
+
+ // [dcl.inline]p1:
+ // The inline specifier can be applied only to the declaration or
+ // definition of a variable or function.
+
+ if (DS.isInlineSpecified())
+ EmitDiag(DS.getInlineSpecLoc());
+
+ // [dcl.constexpr]p1:
+ // The constexpr specifier shall be applied only to the definition of a
+ // variable or variable template or the declaration of a function or
+ // function template.
+
+ if (DS.isConstexprSpecified())
+ EmitDiag(DS.getConstexprSpecLoc());
+
+ // [dcl.fct.spec]p1:
+ // Function-specifiers can be used only in function declarations.
+
+ if (DS.isVirtualSpecified())
+ EmitDiag(DS.getVirtualSpecLoc());
+
+ if (DS.isExplicitSpecified())
+ EmitDiag(DS.getExplicitSpecLoc());
+
+ if (DS.isNoreturnSpecified())
+ EmitDiag(DS.getNoreturnSpecLoc());
+ };
+
+ CheckValidDeclSpecifiers();
+
if (TInfo->getType()->isUndeducedType()) {
Diag(D.getIdentifierLoc(),
diag::warn_cxx14_compat_template_nontype_parm_auto_type)
@@ -999,7 +1053,7 @@ Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
/// ActOnTemplateTemplateParameter - Called when a C++ template template
/// parameter (e.g. T in template <template \<typename> class T> class array)
/// has been parsed. S is the current scope.
-Decl *Sema::ActOnTemplateTemplateParameter(Scope* S,
+NamedDecl *Sema::ActOnTemplateTemplateParameter(Scope* S,
SourceLocation TmpLoc,
TemplateParameterList *Params,
SourceLocation EllipsisLoc,
@@ -1080,7 +1134,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
SourceLocation ExportLoc,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
- ArrayRef<Decl *> Params,
+ ArrayRef<NamedDecl *> Params,
SourceLocation RAngleLoc,
Expr *RequiresClause) {
if (ExportLoc.isValid())
@@ -1088,7 +1142,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth,
return TemplateParameterList::Create(
Context, TemplateLoc, LAngleLoc,
- llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()),
+ llvm::makeArrayRef(Params.data(), Params.size()),
RAngleLoc, RequiresClause);
}
@@ -1133,7 +1187,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
LookupResult Previous(*this, Name, NameLoc,
(SS.isEmpty() && TUK == TUK_Friend)
? LookupTagName : LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
if (SS.isNotEmpty() && !SS.isInvalid()) {
SemanticContext = computeDeclContext(SS, true);
if (!SemanticContext) {
@@ -1192,8 +1246,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
// If there is a previous declaration with the same name, check
// whether this is a valid redeclaration.
- ClassTemplateDecl *PrevClassTemplate
- = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
+ ClassTemplateDecl *PrevClassTemplate =
+ dyn_cast_or_null<ClassTemplateDecl>(PrevDecl);
// We may have found the injected-class-name of a class template,
// class template partial specialization, or class template specialization.
@@ -1484,6 +1538,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK,
CurContext->addDecl(Friend);
}
+ if (PrevClassTemplate)
+ CheckRedeclarationModuleOwnership(NewTemplate, PrevClassTemplate);
+
if (Invalid) {
NewTemplate->setInvalidDecl();
NewClass->setInvalidDecl();
@@ -1834,7 +1891,6 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
// for which some class template parameter without a default argument never
// appears in a deduced context).
bool AddedAny = false;
- bool AddedCopyOrMove = false;
for (NamedDecl *D : LookupConstructors(Transform.Primary)) {
D = D->getUnderlyingDecl();
if (D->isInvalidDecl() || D->isImplicit())
@@ -1851,20 +1907,22 @@ void Sema::DeclareImplicitDeductionGuides(TemplateDecl *Template,
Transform.transformConstructor(FTD, CD);
AddedAny = true;
-
- AddedCopyOrMove |= CD->isCopyOrMoveConstructor();
}
- // Synthesize an X() -> X<...> guide if there were no declared constructors.
- // FIXME: The standard doesn't say (how) to do this.
+ // C++17 [over.match.class.deduct]
+ // -- If C is not defined or does not declare any constructors, an
+ // additional function template derived as above from a hypothetical
+ // constructor C().
if (!AddedAny)
Transform.buildSimpleDeductionGuide(None);
- // Synthesize an X(X<...>) -> X<...> guide if there was no declared constructor
- // resembling a copy or move constructor.
- // FIXME: The standard doesn't say (how) to do this.
- if (!AddedCopyOrMove)
- Transform.buildSimpleDeductionGuide(Transform.DeducedType);
+ // -- An additional function template derived as above from a hypothetical
+ // constructor C(C), called the copy deduction candidate.
+ cast<CXXDeductionGuideDecl>(
+ cast<FunctionTemplateDecl>(
+ Transform.buildSimpleDeductionGuide(Transform.DeducedType))
+ ->getTemplatedDecl())
+ ->setIsCopyDeductionCandidate();
}
/// \brief Diagnose the presence of a default template argument on a
@@ -2863,11 +2921,9 @@ static Expr *lookThroughRangesV3Condition(Preprocessor &PP, Expr *Cond) {
return Cond;
}
-/// Find the failed subexpression within enable_if, and describe it
-/// with a string.
-static std::pair<Expr *, std::string>
-findFailedEnableIfCondition(Sema &S, Expr *Cond) {
- Cond = lookThroughRangesV3Condition(S.PP, Cond);
+std::pair<Expr *, std::string>
+Sema::findFailedBooleanCondition(Expr *Cond, bool AllowTopLevelCond) {
+ Cond = lookThroughRangesV3Condition(PP, Cond);
// Separate out all of the terms in a conjunction.
SmallVector<Expr *, 4> Terms;
@@ -2876,27 +2932,37 @@ findFailedEnableIfCondition(Sema &S, Expr *Cond) {
// Determine which term failed.
Expr *FailedCond = nullptr;
for (Expr *Term : Terms) {
+ Expr *TermAsWritten = Term->IgnoreParenImpCasts();
+
+ // Literals are uninteresting.
+ if (isa<CXXBoolLiteralExpr>(TermAsWritten) ||
+ isa<IntegerLiteral>(TermAsWritten))
+ continue;
+
// The initialization of the parameter from the argument is
// a constant-evaluated context.
EnterExpressionEvaluationContext ConstantEvaluated(
- S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
+ *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
bool Succeeded;
- if (Term->EvaluateAsBooleanCondition(Succeeded, S.Context) &&
+ if (Term->EvaluateAsBooleanCondition(Succeeded, Context) &&
!Succeeded) {
- FailedCond = Term->IgnoreParenImpCasts();
+ FailedCond = TermAsWritten;
break;
}
}
- if (!FailedCond)
+ if (!FailedCond) {
+ if (!AllowTopLevelCond)
+ return { nullptr, "" };
+
FailedCond = Cond->IgnoreParenImpCasts();
+ }
std::string Description;
{
llvm::raw_string_ostream Out(Description);
- FailedCond->printPretty(Out, nullptr,
- PrintingPolicy(S.Context.getLangOpts()));
+ FailedCond->printPretty(Out, nullptr, getPrintingPolicy());
}
return { FailedCond, Description };
}
@@ -2980,8 +3046,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedEnableIfCondition(
- *this, TemplateArgs[0].getSourceExpression());
+ findFailedBooleanCondition(
+ TemplateArgs[0].getSourceExpression(),
+ /*AllowTopLevelCond=*/true);
// Remove the old SFINAE diagnostic.
PartialDiagnosticAt OldDiag =
@@ -3668,7 +3735,7 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
// Check that this isn't a redefinition of this specialization,
// merging with previous declarations.
LookupResult PrevSpec(*this, GetNameForDeclarator(D), LookupOrdinaryName,
- ForRedeclaration);
+ forRedeclarationInCurContext());
PrevSpec.addDecl(PrevDecl);
D.setRedeclaration(CheckVariableDeclaration(Specialization, PrevSpec));
} else if (Specialization->isStaticDataMember() &&
@@ -4792,7 +4859,12 @@ bool Sema::CheckTemplateArgumentList(
// template.
TemplateArgumentListInfo NewArgs = TemplateArgs;
- TemplateParameterList *Params = Template->getTemplateParameters();
+ // Make sure we get the template parameter list from the most
+ // recentdeclaration, since that is the only one that has is guaranteed to
+ // have all the default template argument information.
+ TemplateParameterList *Params =
+ cast<TemplateDecl>(Template->getMostRecentDecl())
+ ->getTemplateParameters();
SourceLocation RAngleLoc = NewArgs.getRAngleLoc();
@@ -5116,6 +5188,11 @@ bool UnnamedLocalNoLinkageFinder::VisitDependentSizedExtVectorType(
return Visit(T->getElementType());
}
+bool UnnamedLocalNoLinkageFinder::VisitDependentAddressSpaceType(
+ const DependentAddressSpaceType *T) {
+ return Visit(T->getPointeeType());
+}
+
bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
return Visit(T->getElementType());
}
@@ -5900,7 +5977,7 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
SourceLocation StartLoc = Arg->getLocStart();
// If the parameter type somehow involves auto, deduce the type now.
- if (getLangOpts().CPlusPlus1z && ParamType->isUndeducedType()) {
+ if (getLangOpts().CPlusPlus17 && ParamType->isUndeducedType()) {
// During template argument deduction, we allow 'decltype(auto)' to
// match an arbitrary dependent argument.
// FIXME: The language rules don't say what happens in this case.
@@ -5984,8 +6061,8 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
EnterExpressionEvaluationContext ConstantEvaluated(
*this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
- if (getLangOpts().CPlusPlus1z) {
- // C++1z [temp.arg.nontype]p1:
+ if (getLangOpts().CPlusPlus17) {
+ // C++17 [temp.arg.nontype]p1:
// A template-argument for a non-type template parameter shall be
// a converted constant expression of the type of the template-parameter.
APValue Value;
@@ -6152,7 +6229,6 @@ ExprResult Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
// -- an integral constant-expression of integral or enumeration
// type; or
// -- the name of a non-type template-parameter; or
- SourceLocation NonConstantLoc;
llvm::APSInt Value;
if (!ArgType->isIntegralOrEnumerationType()) {
Diag(Arg->getLocStart(),
@@ -8015,15 +8091,6 @@ bool Sema::CheckFunctionTemplateSpecialization(
// Ignore access information; it doesn't figure into redeclaration checking.
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
- // an explicit specialization (14.8.3) [...] of a concept definition.
- if (Specialization->getPrimaryTemplate()->isConcept()) {
- Diag(FD->getLocation(), diag::err_concept_specialized)
- << 0 /*function*/ << 1 /*explicitly specialized*/;
- Diag(Specialization->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
FunctionTemplateSpecializationInfo *SpecInfo
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
@@ -8910,15 +8977,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_explicit_instantiation_constexpr);
- // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
- // applied only to the definition of a function template or variable template,
- // declared in namespace scope.
- if (D.getDeclSpec().isConceptSpecified()) {
- Diag(D.getDeclSpec().getConceptSpecLoc(),
- diag::err_concept_specified_specialization) << 0;
- return true;
- }
-
// A deduction guide is not on the list of entities that can be explicitly
// instantiated.
if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) {
@@ -8998,15 +9056,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
- // explicit instantiation (14.8.2) [...] of a concept definition.
- if (PrevTemplate->isConcept()) {
- Diag(D.getIdentifierLoc(), diag::err_concept_specialized)
- << 1 /*variable*/ << 0 /*explicitly instantiated*/;
- Diag(PrevTemplate->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
// Translate the parser's template argument list into our AST format.
TemplateArgumentListInfo TemplateArgs =
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
@@ -9049,7 +9098,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (!HasNoEffect) {
// Instantiate static data member or variable template.
-
Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (PrevTemplate) {
// Merge attributes.
@@ -9217,10 +9265,18 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return (Decl*) nullptr;
}
- Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
if (Attr)
ProcessDeclAttributeList(S, Specialization, Attr);
+ // In MSVC mode, dllimported explicit instantiation definitions are treated as
+ // instantiation declarations.
+ if (TSK == TSK_ExplicitInstantiationDefinition &&
+ Specialization->hasAttr<DLLImportAttr>() &&
+ Context.getTargetInfo().getCXXABI().isMicrosoft())
+ TSK = TSK_ExplicitInstantiationDeclaration;
+
+ Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());
+
if (Specialization->isDefined()) {
// Let the ASTConsumer know that this function has been explicitly
// instantiated now, and its linkage might have changed.
@@ -9243,16 +9299,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
diag::ext_explicit_instantiation_without_qualified_id)
<< Specialization << D.getCXXScopeSpec().getRange();
- // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
- // explicit instantiation (14.8.2) [...] of a concept definition.
- if (FunTmpl && FunTmpl->isConcept() &&
- !D.getDeclSpec().isConceptSpecified()) {
- Diag(D.getIdentifierLoc(), diag::err_concept_specialized)
- << 0 /*function*/ << 0 /*explicitly instantiated*/;
- Diag(FunTmpl->getLocation(), diag::note_previous_declaration);
- return true;
- }
-
CheckExplicitInstantiationScope(*this,
FunTmpl? (NamedDecl *)FunTmpl
: Specialization->getInstantiatedFromMemberFunction(),
@@ -9513,7 +9559,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
Expr *FailedCond;
std::string FailedDescription;
std::tie(FailedCond, FailedDescription) =
- findFailedEnableIfCondition(*this, Cond);
+ findFailedBooleanCondition(Cond, /*AllowTopLevelCond=*/true);
Diag(FailedCond->getExprLoc(),
diag::err_typename_nested_not_found_requirement)
@@ -9591,7 +9637,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword,
// A type-specifier of the form
// typename[opt] nested-name-specifier[opt] template-name
// is a placeholder for a deduced class type [...].
- if (getLangOpts().CPlusPlus1z) {
+ if (getLangOpts().CPlusPlus17) {
if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) {
return Context.getElaboratedType(
Keyword, QualifierLoc.getNestedNameSpecifier(),