aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:37 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:11:37 +0000
commit461a67fa15370a9ec88f8f8a240bf7c123bb2029 (patch)
tree6942083d7d56bba40ec790a453ca58ad3baf6832 /lib/Sema/SemaTemplate.cpp
parent75c3240472ba6ac2669ee72ca67eb72d4e2851fc (diff)
downloadsrc-461a67fa15370a9ec88f8f8a240bf7c123bb2029.tar.gz
src-461a67fa15370a9ec88f8f8a240bf7c123bb2029.zip
Vendor import of clang trunk r321017:vendor/clang/clang-trunk-r321017
Notes
Notes: svn path=/vendor/clang/dist/; revision=326941 svn path=/vendor/clang/clang-trunk-r321017/; revision=326942; tag=vendor/clang/clang-trunk-r321017
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r--lib/Sema/SemaTemplate.cpp144
1 files changed, 68 insertions, 76 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index e9b38551683c..c70a8ba8f126 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/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);
}
@@ -1080,7 +1080,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 +1088,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 +1133,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 +1192,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 +1484,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 +1837,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 +1853,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 +2867,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 +2878,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 +2992,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 +3681,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 +4805,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 +5134,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 +5923,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 +6007,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 +6175,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 +8037,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 +8923,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 +9002,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 +9044,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 +9211,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 +9245,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 +9505,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 +9583,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(),