summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp96
1 files changed, 92 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 49ba771379e..fba8cd4eee0 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -271,9 +271,11 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
} else {
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
- isa<BuiltinTemplateDecl>(TD));
+ isa<BuiltinTemplateDecl>(TD) || isa<ConceptDecl>(TD));
TemplateKind =
- isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
+ isa<VarTemplateDecl>(TD) ? TNK_Var_template :
+ isa<ConceptDecl>(TD) ? TNK_Concept_template :
+ TNK_Type_template;
}
}
@@ -3227,7 +3229,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
TemplateDecl *Template = Name.getAsTemplateDecl();
if (!Template || isa<FunctionTemplateDecl>(Template) ||
- isa<VarTemplateDecl>(Template)) {
+ isa<VarTemplateDecl>(Template) ||
+ isa<ConceptDecl>(Template)) {
// We might have a substituted template template parameter pack. If so,
// build a template specialization type for it.
if (Name.getAsSubstTemplateTemplateParmPack())
@@ -4234,6 +4237,18 @@ void Sema::diagnoseMissingTemplateArguments(TemplateName Name,
}
}
+ExprResult
+Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
+ const DeclarationNameInfo &NameInfo,
+ ConceptDecl *Template,
+ SourceLocation TemplateLoc,
+ const TemplateArgumentListInfo *TemplateArgs) {
+ // TODO: Do concept specialization here.
+ Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) <<
+ "concept specialization";
+ return ExprError();
+}
+
ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
SourceLocation TemplateKWLoc,
LookupResult &R,
@@ -4274,6 +4289,12 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
TemplateKWLoc, TemplateArgs);
}
+ if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) {
+ return CheckConceptTemplateId(SS, R.getLookupNameInfo(),
+ R.getAsSingle<ConceptDecl>(),
+ TemplateKWLoc, TemplateArgs);
+ }
+
// We don't want lookup warnings at this point.
R.suppressDiagnostics();
@@ -7974,7 +7995,74 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
return NewDecl;
}
-/// Strips various properties off an implicit instantiation
+Decl *Sema::ActOnConceptDefinition(Scope *S,
+ MultiTemplateParamsArg TemplateParameterLists,
+ IdentifierInfo *Name, SourceLocation NameLoc,
+ Expr *ConstraintExpr) {
+ DeclContext *DC = CurContext;
+
+ if (!DC->getRedeclContext()->isFileContext()) {
+ Diag(NameLoc,
+ diag::err_concept_decls_may_only_appear_in_global_namespace_scope);
+ return nullptr;
+ }
+
+ if (TemplateParameterLists.size() > 1) {
+ Diag(NameLoc, diag::err_concept_extra_headers);
+ return nullptr;
+ }
+
+ if (TemplateParameterLists.front()->size() == 0) {
+ Diag(NameLoc, diag::err_concept_no_parameters);
+ return nullptr;
+ }
+
+ ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name,
+ TemplateParameterLists.front(),
+ ConstraintExpr);
+
+ if (!ConstraintExpr->isTypeDependent() &&
+ ConstraintExpr->getType() != Context.BoolTy) {
+ // C++2a [temp.constr.atomic]p3:
+ // E shall be a constant expression of type bool.
+ // TODO: Do this check for individual atomic constraints
+ // and not the constraint expression. Probably should do it in
+ // ParseConstraintExpression.
+ Diag(ConstraintExpr->getSourceRange().getBegin(),
+ diag::err_concept_initialized_with_non_bool_type)
+ << ConstraintExpr->getType();
+ NewDecl->setInvalidDecl();
+ }
+
+ if (NewDecl->getAssociatedConstraints()) {
+ // C++2a [temp.concept]p4:
+ // A concept shall not have associated constraints.
+ // TODO: Make a test once we have actual associated constraints.
+ Diag(NameLoc, diag::err_concept_no_associated_constraints);
+ NewDecl->setInvalidDecl();
+ }
+
+ // Check for conflicting previous declaration.
+ DeclarationNameInfo NameInfo(NewDecl->getDeclName(), NameLoc);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForVisibleRedeclaration);
+ LookupName(Previous, S);
+
+ FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage=*/false,
+ /*AllowInlineNamespace*/false);
+ if (!Previous.empty()) {
+ auto *Old = Previous.getRepresentativeDecl();
+ Diag(NameLoc, isa<ConceptDecl>(Old) ? diag::err_redefinition :
+ diag::err_redefinition_different_kind) << NewDecl->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ }
+
+ ActOnDocumentableDecl(NewDecl);
+ PushOnScopeChains(NewDecl, S);
+ return NewDecl;
+}
+
+/// \brief Strips various properties off an implicit instantiation
/// that has just been explicitly specialized.
static void StripImplicitInstantiation(NamedDecl *D) {
D->dropAttr<DLLImportAttr>();
OpenPOWER on IntegriCloud