From fdf80e86a52849813d05da4b6c25884c06ba9e98 Mon Sep 17 00:00:00 2001 From: Saar Raz Date: Fri, 6 Dec 2019 01:30:21 +0200 Subject: [Concepts] Constraint Enforcement & Diagnostics Part of the C++20 concepts implementation effort. - Associated constraints (requires clauses, currently) are now enforced when instantiating/specializing templates and when considering partial specializations and function overloads. - Elaborated diagnostics give helpful insight as to why the constraints were not satisfied. Phabricator: D41569 Re-commit, after fixing some memory bugs. --- clang/lib/Serialization/ASTReaderStmt.cpp | 24 ++++++++++++++++++++++-- clang/lib/Serialization/ASTWriterStmt.cpp | 20 +++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) (limited to 'clang/lib/Serialization') diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index f426ed3b8d3..815a9744c5b 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTReader.h" +#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTContext.h" #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" @@ -742,14 +743,33 @@ void ASTStmtReader::VisitConceptSpecializationExpr( E->TemplateKWLoc = Record.readSourceLocation(); E->ConceptNameLoc = Record.readSourceLocation(); E->FoundDecl = ReadDeclAs(); - E->NamedConcept.setPointer(ReadDeclAs()); + E->NamedConcept = ReadDeclAs(); const ASTTemplateArgumentListInfo *ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); llvm::SmallVector Args; for (unsigned I = 0; I < NumTemplateArgs; ++I) Args.push_back(Record.readTemplateArgument()); E->setTemplateArguments(ArgsAsWritten, Args); - E->NamedConcept.setInt(Record.readInt() == 1); + ConstraintSatisfaction Satisfaction; + Satisfaction.IsSatisfied = Record.readInt(); + if (!Satisfaction.IsSatisfied) { + unsigned NumDetailRecords = Record.readInt(); + for (unsigned i = 0; i != NumDetailRecords; ++i) { + Expr *ConstraintExpr = Record.readExpr(); + bool IsDiagnostic = Record.readInt(); + if (IsDiagnostic) { + SourceLocation DiagLocation = Record.readSourceLocation(); + std::string DiagMessage = Record.readString(); + Satisfaction.Details.emplace_back( + ConstraintExpr, new (Record.getContext()) + ConstraintSatisfaction::SubstitutionDiagnostic{ + DiagLocation, DiagMessage}); + } else + Satisfaction.Details.emplace_back(ConstraintExpr, Record.readExpr()); + } + } + E->Satisfaction = ASTConstraintSatisfaction::Create(Record.getContext(), + Satisfaction); } void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 2b331a97985..1e801d02afc 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -401,7 +401,25 @@ void ASTStmtWriter::VisitConceptSpecializationExpr( Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten()); for (const TemplateArgument &Arg : TemplateArgs) Record.AddTemplateArgument(Arg); - Record.push_back(E->isSatisfied()); + const ASTConstraintSatisfaction &Satisfaction = E->getSatisfaction(); + Record.push_back(Satisfaction.IsSatisfied); + if (!Satisfaction.IsSatisfied) { + Record.push_back(Satisfaction.NumRecords); + for (const auto &DetailRecord : Satisfaction) { + Record.AddStmt(const_cast(DetailRecord.first)); + auto *E = DetailRecord.second.dyn_cast(); + Record.push_back(E == nullptr); + if (E) + Record.AddStmt(E); + else { + auto *Diag = DetailRecord.second.get *>(); + Record.AddSourceLocation(Diag->first); + Record.AddString(Diag->second); + } + } + } + Code = serialization::EXPR_CONCEPT_SPECIALIZATION; } -- cgit v1.2.3