blob: 018ac2d7dc9d1b52d6ff42f08a26379a04a2edd3 [file] [log] [blame]
Saar Raz5d98ba62019-10-15 15:24:26 +00001//===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements semantic analysis for C++ constraints and concepts.
11//
12//===----------------------------------------------------------------------===//
13
Saar Razb65b1f32020-01-09 15:07:51 +020014#include "clang/Sema/SemaConcept.h"
Saar Raz5d98ba62019-10-15 15:24:26 +000015#include "clang/Sema/Sema.h"
Saar Razfdf80e82019-12-06 01:30:21 +020016#include "clang/Sema/SemaInternal.h"
Saar Raz5d98ba62019-10-15 15:24:26 +000017#include "clang/Sema/SemaDiagnostic.h"
18#include "clang/Sema/TemplateDeduction.h"
19#include "clang/Sema/Template.h"
Saar Razbaa84d82020-01-18 14:58:01 +020020#include "clang/AST/ExprCXX.h"
Saar Razdf061c32019-12-23 08:37:35 +020021#include "clang/AST/RecursiveASTVisitor.h"
Saar Razb65b1f32020-01-09 15:07:51 +020022#include "clang/Basic/OperatorPrecedence.h"
Saar Razfdf80e82019-12-06 01:30:21 +020023#include "llvm/ADT/DenseMap.h"
24#include "llvm/ADT/PointerUnion.h"
Saar Raz5d98ba62019-10-15 15:24:26 +000025using namespace clang;
26using namespace sema;
27
Saar Razb65b1f32020-01-09 15:07:51 +020028bool
29Sema::CheckConstraintExpression(Expr *ConstraintExpression, Token NextToken,
30 bool *PossibleNonPrimary,
31 bool IsTrailingRequiresClause) {
Saar Raz5d98ba62019-10-15 15:24:26 +000032 // C++2a [temp.constr.atomic]p1
33 // ..E shall be a constant expression of type bool.
34
35 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
36
37 if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
38 if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
Saar Razb65b1f32020-01-09 15:07:51 +020039 return CheckConstraintExpression(BinOp->getLHS(), NextToken,
40 PossibleNonPrimary) &&
41 CheckConstraintExpression(BinOp->getRHS(), NextToken,
42 PossibleNonPrimary);
Saar Raz5d98ba62019-10-15 15:24:26 +000043 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
Saar Razb65b1f32020-01-09 15:07:51 +020044 return CheckConstraintExpression(C->getSubExpr(), NextToken,
45 PossibleNonPrimary);
Saar Raz5d98ba62019-10-15 15:24:26 +000046
47 QualType Type = ConstraintExpression->getType();
Saar Razb65b1f32020-01-09 15:07:51 +020048
49 auto CheckForNonPrimary = [&] {
50 if (PossibleNonPrimary)
51 *PossibleNonPrimary =
52 // We have the following case:
53 // template<typename> requires func(0) struct S { };
54 // The user probably isn't aware of the parentheses required around
55 // the function call, and we're only going to parse 'func' as the
56 // primary-expression, and complain that it is of non-bool type.
57 (NextToken.is(tok::l_paren) &&
58 (IsTrailingRequiresClause ||
59 (Type->isDependentType() &&
60 IsDependentFunctionNameExpr(ConstraintExpression)) ||
61 Type->isFunctionType() ||
62 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
63 // We have the following case:
64 // template<typename T> requires size_<T> == 0 struct S { };
65 // The user probably isn't aware of the parentheses required around
66 // the binary operator, and we're only going to parse 'func' as the
67 // first operand, and complain that it is of non-bool type.
68 getBinOpPrecedence(NextToken.getKind(),
69 /*GreaterThanIsOperator=*/true,
70 getLangOpts().CPlusPlus11) > prec::LogicalAnd;
71 };
72
73 // An atomic constraint!
74 if (ConstraintExpression->isTypeDependent()) {
75 CheckForNonPrimary();
76 return true;
77 }
78
Saar Raz5d98ba62019-10-15 15:24:26 +000079 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
80 Diag(ConstraintExpression->getExprLoc(),
81 diag::err_non_bool_atomic_constraint) << Type
82 << ConstraintExpression->getSourceRange();
Saar Razb65b1f32020-01-09 15:07:51 +020083 CheckForNonPrimary();
Saar Raz5d98ba62019-10-15 15:24:26 +000084 return false;
85 }
Saar Razb65b1f32020-01-09 15:07:51 +020086
87 if (PossibleNonPrimary)
88 *PossibleNonPrimary = false;
Saar Raz5d98ba62019-10-15 15:24:26 +000089 return true;
90}
91
Saar Razfdf80e82019-12-06 01:30:21 +020092template <typename AtomicEvaluator>
93static bool
94calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
95 ConstraintSatisfaction &Satisfaction,
96 AtomicEvaluator &&Evaluator) {
Saar Raz5d98ba62019-10-15 15:24:26 +000097 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
98
99 if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
Saar Razfdf80e82019-12-06 01:30:21 +0200100 if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
101 if (calculateConstraintSatisfaction(S, BO->getLHS(), Satisfaction,
102 Evaluator))
Saar Raz5d98ba62019-10-15 15:24:26 +0000103 return true;
Saar Razfdf80e82019-12-06 01:30:21 +0200104
105 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
106
107 if (BO->getOpcode() == BO_LOr && IsLHSSatisfied)
108 // [temp.constr.op] p3
109 // A disjunction is a constraint taking two operands. To determine if
110 // a disjunction is satisfied, the satisfaction of the first operand
111 // is checked. If that is satisfied, the disjunction is satisfied.
112 // Otherwise, the disjunction is satisfied if and only if the second
113 // operand is satisfied.
Saar Raz5d98ba62019-10-15 15:24:26 +0000114 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200115
116 if (BO->getOpcode() == BO_LAnd && !IsLHSSatisfied)
117 // [temp.constr.op] p2
118 // A conjunction is a constraint taking two operands. To determine if
119 // a conjunction is satisfied, the satisfaction of the first operand
120 // is checked. If that is not satisfied, the conjunction is not
121 // satisfied. Otherwise, the conjunction is satisfied if and only if
122 // the second operand is satisfied.
Saar Raz5d98ba62019-10-15 15:24:26 +0000123 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200124
125 return calculateConstraintSatisfaction(S, BO->getRHS(), Satisfaction,
126 std::forward<AtomicEvaluator>(Evaluator));
Saar Raz5d98ba62019-10-15 15:24:26 +0000127 }
128 }
129 else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
Saar Razfdf80e82019-12-06 01:30:21 +0200130 return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
131 std::forward<AtomicEvaluator>(Evaluator));
Saar Razffa214e2019-10-25 00:09:37 +0300132
Saar Razfdf80e82019-12-06 01:30:21 +0200133 // An atomic constraint expression
134 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
Vlad Tsyrklevich38839d02019-10-28 14:36:31 -0700135
Saar Razfdf80e82019-12-06 01:30:21 +0200136 if (SubstitutedAtomicExpr.isInvalid())
Vlad Tsyrklevich38839d02019-10-28 14:36:31 -0700137 return true;
138
Saar Razfdf80e82019-12-06 01:30:21 +0200139 if (!SubstitutedAtomicExpr.isUsable())
140 // Evaluator has decided satisfaction without yielding an expression.
141 return false;
142
143 EnterExpressionEvaluationContext ConstantEvaluated(
144 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
Saar Raz5d98ba62019-10-15 15:24:26 +0000145 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
146 Expr::EvalResult EvalResult;
147 EvalResult.Diag = &EvaluationDiags;
Saar Razfdf80e82019-12-06 01:30:21 +0200148 if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
149 // C++2a [temp.constr.atomic]p1
150 // ...E shall be a constant expression of type bool.
151 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
152 diag::err_non_constant_constraint_expression)
153 << SubstitutedAtomicExpr.get()->getSourceRange();
Saar Raz5d98ba62019-10-15 15:24:26 +0000154 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
Saar Razfdf80e82019-12-06 01:30:21 +0200155 S.Diag(PDiag.first, PDiag.second);
Saar Raz5d98ba62019-10-15 15:24:26 +0000156 return true;
157 }
158
Saar Razfdf80e82019-12-06 01:30:21 +0200159 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
160 if (!Satisfaction.IsSatisfied)
161 Satisfaction.Details.emplace_back(ConstraintExpr,
162 SubstitutedAtomicExpr.get());
Saar Raz5d98ba62019-10-15 15:24:26 +0000163
164 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200165}
166
167template <typename TemplateDeclT>
168static bool calculateConstraintSatisfaction(
169 Sema &S, TemplateDeclT *Template, ArrayRef<TemplateArgument> TemplateArgs,
170 SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
171 const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
172 return calculateConstraintSatisfaction(
173 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
174 EnterExpressionEvaluationContext ConstantEvaluated(
175 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
176
177 // Atomic constraint - substitute arguments and check satisfaction.
178 ExprResult SubstitutedExpression;
179 {
180 TemplateDeductionInfo Info(TemplateNameLoc);
181 Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
182 Sema::InstantiatingTemplate::ConstraintSubstitution{}, Template,
183 Info, AtomicExpr->getSourceRange());
184 if (Inst.isInvalid())
185 return ExprError();
186 // We do not want error diagnostics escaping here.
187 Sema::SFINAETrap Trap(S);
188 SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
189 MLTAL);
190 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
191 // C++2a [temp.constr.atomic]p1
192 // ...If substitution results in an invalid type or expression, the
193 // constraint is not satisfied.
194 if (!Trap.hasErrorOccurred())
195 // A non-SFINAE error has occured as a result of this
196 // substitution.
197 return ExprError();
198
199 PartialDiagnosticAt SubstDiag{SourceLocation(),
200 PartialDiagnostic::NullDiagnostic()};
201 Info.takeSFINAEDiagnostic(SubstDiag);
202 // FIXME: Concepts: This is an unfortunate consequence of there
203 // being no serialization code for PartialDiagnostics and the fact
204 // that serializing them would likely take a lot more storage than
205 // just storing them as strings. We would still like, in the
206 // future, to serialize the proper PartialDiagnostic as serializing
207 // it as a string defeats the purpose of the diagnostic mechanism.
208 SmallString<128> DiagString;
209 DiagString = ": ";
210 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
211 unsigned MessageSize = DiagString.size();
212 char *Mem = new (S.Context) char[MessageSize];
213 memcpy(Mem, DiagString.c_str(), MessageSize);
214 Satisfaction.Details.emplace_back(
215 AtomicExpr,
216 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
217 SubstDiag.first, StringRef(Mem, MessageSize)});
218 Satisfaction.IsSatisfied = false;
219 return ExprEmpty();
220 }
221 }
222
223 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
224 return ExprError();
225
226 return SubstitutedExpression;
227 });
228}
229
230template<typename TemplateDeclT>
231static bool CheckConstraintSatisfaction(Sema &S, TemplateDeclT *Template,
232 ArrayRef<const Expr *> ConstraintExprs,
233 ArrayRef<TemplateArgument> TemplateArgs,
234 SourceRange TemplateIDRange,
235 ConstraintSatisfaction &Satisfaction) {
236 if (ConstraintExprs.empty()) {
237 Satisfaction.IsSatisfied = true;
238 return false;
239 }
240
241 for (auto& Arg : TemplateArgs)
242 if (Arg.isInstantiationDependent()) {
243 // No need to check satisfaction for dependent constraint expressions.
244 Satisfaction.IsSatisfied = true;
245 return false;
246 }
247
248 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
249 Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs,
250 TemplateIDRange);
251 if (Inst.isInvalid())
252 return true;
253
254 MultiLevelTemplateArgumentList MLTAL;
255 MLTAL.addOuterTemplateArguments(TemplateArgs);
256
257 for (const Expr *ConstraintExpr : ConstraintExprs) {
258 if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
259 TemplateIDRange.getBegin(), MLTAL,
260 ConstraintExpr, Satisfaction))
261 return true;
262 if (!Satisfaction.IsSatisfied)
263 // [temp.constr.op] p2
264 // [...] To determine if a conjunction is satisfied, the satisfaction
265 // of the first operand is checked. If that is not satisfied, the
266 // conjunction is not satisfied. [...]
267 return false;
268 }
269 return false;
270}
271
272bool Sema::CheckConstraintSatisfaction(TemplateDecl *Template,
273 ArrayRef<const Expr *> ConstraintExprs,
274 ArrayRef<TemplateArgument> TemplateArgs,
275 SourceRange TemplateIDRange,
276 ConstraintSatisfaction &Satisfaction) {
277 return ::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
278 TemplateArgs, TemplateIDRange,
279 Satisfaction);
280}
281
282bool
283Sema::CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl* Part,
284 ArrayRef<const Expr *> ConstraintExprs,
285 ArrayRef<TemplateArgument> TemplateArgs,
286 SourceRange TemplateIDRange,
287 ConstraintSatisfaction &Satisfaction) {
288 return ::CheckConstraintSatisfaction(*this, Part, ConstraintExprs,
289 TemplateArgs, TemplateIDRange,
290 Satisfaction);
291}
292
293bool
294Sema::CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl* Partial,
295 ArrayRef<const Expr *> ConstraintExprs,
296 ArrayRef<TemplateArgument> TemplateArgs,
297 SourceRange TemplateIDRange,
298 ConstraintSatisfaction &Satisfaction) {
299 return ::CheckConstraintSatisfaction(*this, Partial, ConstraintExprs,
300 TemplateArgs, TemplateIDRange,
301 Satisfaction);
302}
303
304bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
305 ConstraintSatisfaction &Satisfaction) {
306 return calculateConstraintSatisfaction(
307 *this, ConstraintExpr, Satisfaction,
308 [](const Expr *AtomicExpr) -> ExprResult {
309 return ExprResult(const_cast<Expr *>(AtomicExpr));
310 });
311}
312
313bool Sema::EnsureTemplateArgumentListConstraints(
314 TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
315 SourceRange TemplateIDRange) {
316 ConstraintSatisfaction Satisfaction;
317 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
318 TD->getAssociatedConstraints(AssociatedConstraints);
319 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
320 TemplateIDRange, Satisfaction))
321 return true;
322
323 if (!Satisfaction.IsSatisfied) {
324 SmallString<128> TemplateArgString;
325 TemplateArgString = " ";
326 TemplateArgString += getTemplateArgumentBindingsText(
327 TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
328
329 Diag(TemplateIDRange.getBegin(),
330 diag::err_template_arg_list_constraints_not_satisfied)
331 << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
332 << TemplateArgString << TemplateIDRange;
333 DiagnoseUnsatisfiedConstraint(Satisfaction);
334 return true;
335 }
336 return false;
337}
338
339static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
340 Expr *SubstExpr,
341 bool First = true) {
342 SubstExpr = SubstExpr->IgnoreParenImpCasts();
343 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
344 switch (BO->getOpcode()) {
345 // These two cases will in practice only be reached when using fold
346 // expressions with || and &&, since otherwise the || and && will have been
347 // broken down into atomic constraints during satisfaction checking.
348 case BO_LOr:
349 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
350 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
351 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
352 /*First=*/false);
353 return;
354 case BO_LAnd:
355 bool LHSSatisfied;
356 BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
357 if (LHSSatisfied) {
358 // LHS is true, so RHS must be false.
359 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
360 return;
361 }
362 // LHS is false
363 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
364
365 // RHS might also be false
366 bool RHSSatisfied;
367 BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
368 if (!RHSSatisfied)
369 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
370 /*First=*/false);
371 return;
372 case BO_GE:
373 case BO_LE:
374 case BO_GT:
375 case BO_LT:
376 case BO_EQ:
377 case BO_NE:
378 if (BO->getLHS()->getType()->isIntegerType() &&
379 BO->getRHS()->getType()->isIntegerType()) {
380 Expr::EvalResult SimplifiedLHS;
381 Expr::EvalResult SimplifiedRHS;
382 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
383 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
384 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
385 S.Diag(SubstExpr->getBeginLoc(),
386 diag::note_atomic_constraint_evaluated_to_false_elaborated)
387 << (int)First << SubstExpr
388 << SimplifiedLHS.Val.getInt().toString(10)
389 << BinaryOperator::getOpcodeStr(BO->getOpcode())
390 << SimplifiedRHS.Val.getInt().toString(10);
391 return;
392 }
393 }
394 break;
395
396 default:
397 break;
398 }
399 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
400 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
401 S.Diag(
402 CSE->getSourceRange().getBegin(),
403 diag::
404 note_single_arg_concept_specialization_constraint_evaluated_to_false)
405 << (int)First
406 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
407 << CSE->getNamedConcept();
408 } else {
409 S.Diag(SubstExpr->getSourceRange().getBegin(),
410 diag::note_concept_specialization_constraint_evaluated_to_false)
411 << (int)First << CSE;
412 }
413 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
414 return;
415 }
416
417 S.Diag(SubstExpr->getSourceRange().getBegin(),
418 diag::note_atomic_constraint_evaluated_to_false)
419 << (int)First << SubstExpr;
420}
421
422template<typename SubstitutionDiagnostic>
423static void diagnoseUnsatisfiedConstraintExpr(
424 Sema &S, const Expr *E,
425 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
426 bool First = true) {
427 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
428 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
429 << Diag->second;
430 return;
431 }
432
433 diagnoseWellFormedUnsatisfiedConstraintExpr(S,
434 Record.template get<Expr *>(), First);
435}
436
Saar Razbaa84d82020-01-18 14:58:01 +0200437void Sema::DiagnoseUnsatisfiedConstraint(
438 const ConstraintSatisfaction& Satisfaction) {
Saar Razfdf80e82019-12-06 01:30:21 +0200439 assert(!Satisfaction.IsSatisfied &&
440 "Attempted to diagnose a satisfied constraint");
Saar Razbaa84d82020-01-18 14:58:01 +0200441 bool First = true;
Saar Razfdf80e82019-12-06 01:30:21 +0200442 for (auto &Pair : Satisfaction.Details) {
443 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
444 First = false;
445 }
446}
447
448void Sema::DiagnoseUnsatisfiedConstraint(
Saar Razbaa84d82020-01-18 14:58:01 +0200449 const ASTConstraintSatisfaction &Satisfaction) {
Saar Razfdf80e82019-12-06 01:30:21 +0200450 assert(!Satisfaction.IsSatisfied &&
451 "Attempted to diagnose a satisfied constraint");
Saar Razbaa84d82020-01-18 14:58:01 +0200452 bool First = true;
Saar Razfdf80e82019-12-06 01:30:21 +0200453 for (auto &Pair : Satisfaction) {
454 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
455 First = false;
456 }
Saar Razdf061c32019-12-23 08:37:35 +0200457}
458
Saar Razb65b1f32020-01-09 15:07:51 +0200459const NormalizedConstraint *
460Sema::getNormalizedAssociatedConstraints(
461 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
462 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
463 if (CacheEntry == NormalizationCache.end()) {
464 auto Normalized =
465 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
466 AssociatedConstraints);
467 CacheEntry =
468 NormalizationCache
469 .try_emplace(ConstrainedDecl,
470 Normalized
471 ? new (Context) NormalizedConstraint(
472 std::move(*Normalized))
473 : nullptr)
474 .first;
Saar Razdf061c32019-12-23 08:37:35 +0200475 }
Saar Razb65b1f32020-01-09 15:07:51 +0200476 return CacheEntry->second;
477}
Saar Razdf061c32019-12-23 08:37:35 +0200478
479static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
480 ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
481 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
482 if (!N.isAtomic()) {
483 if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
484 ArgsAsWritten))
485 return true;
486 return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
487 ArgsAsWritten);
488 }
489 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
490
491 AtomicConstraint &Atomic = *N.getAtomicConstraint();
492 TemplateArgumentListInfo SubstArgs;
493 MultiLevelTemplateArgumentList MLTAL;
494 MLTAL.addOuterTemplateArguments(TemplateArgs);
495 if (!Atomic.ParameterMapping) {
496 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
497 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
498 /*Depth=*/0, OccurringIndices);
Saar Razb65b1f32020-01-09 15:07:51 +0200499 Atomic.ParameterMapping.emplace(
500 MutableArrayRef<TemplateArgumentLoc>(
501 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
502 OccurringIndices.count()));
503 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
Saar Razdf061c32019-12-23 08:37:35 +0200504 if (OccurringIndices[I])
Saar Razb65b1f32020-01-09 15:07:51 +0200505 new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
Saar Razdf061c32019-12-23 08:37:35 +0200506 S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
507 // Here we assume we do not support things like
508 // template<typename A, typename B>
509 // concept C = ...;
510 //
511 // template<typename... Ts> requires C<Ts...>
512 // struct S { };
513 // The above currently yields a diagnostic.
514 // We still might have default arguments for concept parameters.
515 ArgsAsWritten->NumTemplateArgs > I ?
516 ArgsAsWritten->arguments()[I].getLocation() :
517 SourceLocation()));
518 }
519 Sema::InstantiatingTemplate Inst(
520 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
521 Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
522 SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
523 ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
524 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
525 return true;
526 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
527 N.getAtomicConstraint()->ParameterMapping->begin());
528 return false;
529}
530
Saar Razb65b1f32020-01-09 15:07:51 +0200531Optional<NormalizedConstraint>
532NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
533 ArrayRef<const Expr *> E) {
534 assert(E.size() != 0);
535 auto First = fromConstraintExpr(S, D, E[0]);
536 if (E.size() == 1)
537 return First;
538 auto Second = fromConstraintExpr(S, D, E[1]);
539 if (!Second)
540 return None;
541 llvm::Optional<NormalizedConstraint> Conjunction;
542 Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
543 CCK_Conjunction);
544 for (unsigned I = 2; I < E.size(); ++I) {
545 auto Next = fromConstraintExpr(S, D, E[I]);
546 if (!Next)
547 return llvm::Optional<NormalizedConstraint>{};
548 NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
549 std::move(*Next), CCK_Conjunction);
550 *Conjunction = std::move(NewConjunction);
551 }
552 return Conjunction;
553}
554
Saar Razdf061c32019-12-23 08:37:35 +0200555llvm::Optional<NormalizedConstraint>
556NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
557 assert(E != nullptr);
558
559 // C++ [temp.constr.normal]p1.1
560 // [...]
561 // - The normal form of an expression (E) is the normal form of E.
562 // [...]
563 E = E->IgnoreParenImpCasts();
564 if (auto *BO = dyn_cast<const BinaryOperator>(E)) {
565 if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
566 auto LHS = fromConstraintExpr(S, D, BO->getLHS());
567 if (!LHS)
568 return None;
569 auto RHS = fromConstraintExpr(S, D, BO->getRHS());
570 if (!RHS)
571 return None;
572
573 return NormalizedConstraint(
Saar Razb65b1f32020-01-09 15:07:51 +0200574 S.Context, std::move(*LHS), std::move(*RHS),
Saar Razdf061c32019-12-23 08:37:35 +0200575 BO->getOpcode() == BO_LAnd ? CCK_Conjunction : CCK_Disjunction);
576 }
577 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
Saar Razb65b1f32020-01-09 15:07:51 +0200578 const NormalizedConstraint *SubNF;
Saar Razdf061c32019-12-23 08:37:35 +0200579 {
580 Sema::InstantiatingTemplate Inst(
581 S, CSE->getExprLoc(),
582 Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
583 CSE->getSourceRange());
584 // C++ [temp.constr.normal]p1.1
585 // [...]
586 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
587 // where C names a concept, is the normal form of the
588 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
589 // respective template parameters in the parameter mappings in each atomic
590 // constraint. If any such substitution results in an invalid type or
591 // expression, the program is ill-formed; no diagnostic is required.
592 // [...]
Saar Razb65b1f32020-01-09 15:07:51 +0200593 ConceptDecl *CD = CSE->getNamedConcept();
594 SubNF = S.getNormalizedAssociatedConstraints(CD,
595 {CD->getConstraintExpr()});
Saar Razdf061c32019-12-23 08:37:35 +0200596 if (!SubNF)
597 return None;
598 }
599
Saar Razb65b1f32020-01-09 15:07:51 +0200600 Optional<NormalizedConstraint> New;
601 New.emplace(S.Context, *SubNF);
602
Saar Razdf061c32019-12-23 08:37:35 +0200603 if (substituteParameterMappings(
Saar Razb65b1f32020-01-09 15:07:51 +0200604 S, *New, CSE->getNamedConcept(),
Saar Razdf061c32019-12-23 08:37:35 +0200605 CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
606 return None;
607
Saar Razb65b1f32020-01-09 15:07:51 +0200608 return New;
Saar Razdf061c32019-12-23 08:37:35 +0200609 }
610 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
611}
612
Saar Razdf061c32019-12-23 08:37:35 +0200613using NormalForm =
614 llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
615
616static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
617 if (Normalized.isAtomic())
618 return {{Normalized.getAtomicConstraint()}};
619
620 NormalForm LCNF = makeCNF(Normalized.getLHS());
621 NormalForm RCNF = makeCNF(Normalized.getRHS());
622 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
623 LCNF.reserve(LCNF.size() + RCNF.size());
624 while (!RCNF.empty())
625 LCNF.push_back(RCNF.pop_back_val());
626 return LCNF;
627 }
628
629 // Disjunction
630 NormalForm Res;
631 Res.reserve(LCNF.size() * RCNF.size());
632 for (auto &LDisjunction : LCNF)
633 for (auto &RDisjunction : RCNF) {
634 NormalForm::value_type Combined;
635 Combined.reserve(LDisjunction.size() + RDisjunction.size());
636 std::copy(LDisjunction.begin(), LDisjunction.end(),
637 std::back_inserter(Combined));
638 std::copy(RDisjunction.begin(), RDisjunction.end(),
639 std::back_inserter(Combined));
640 Res.emplace_back(Combined);
641 }
642 return Res;
643}
644
645static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
646 if (Normalized.isAtomic())
647 return {{Normalized.getAtomicConstraint()}};
648
649 NormalForm LDNF = makeDNF(Normalized.getLHS());
650 NormalForm RDNF = makeDNF(Normalized.getRHS());
651 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
652 LDNF.reserve(LDNF.size() + RDNF.size());
653 while (!RDNF.empty())
654 LDNF.push_back(RDNF.pop_back_val());
655 return LDNF;
656 }
657
658 // Conjunction
659 NormalForm Res;
660 Res.reserve(LDNF.size() * RDNF.size());
661 for (auto &LConjunction : LDNF) {
662 for (auto &RConjunction : RDNF) {
663 NormalForm::value_type Combined;
664 Combined.reserve(LConjunction.size() + RConjunction.size());
665 std::copy(LConjunction.begin(), LConjunction.end(),
666 std::back_inserter(Combined));
667 std::copy(RConjunction.begin(), RConjunction.end(),
668 std::back_inserter(Combined));
669 Res.emplace_back(Combined);
670 }
671 }
672 return Res;
673}
674
Saar Razb65b1f32020-01-09 15:07:51 +0200675template<typename AtomicSubsumptionEvaluator>
676static bool subsumes(NormalForm PDNF, NormalForm QCNF,
677 AtomicSubsumptionEvaluator E) {
Saar Razdf061c32019-12-23 08:37:35 +0200678 // C++ [temp.constr.order] p2
679 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
680 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
681 // the conjuctive normal form of Q, where [...]
682 for (const auto &Pi : PDNF) {
683 for (const auto &Qj : QCNF) {
684 // C++ [temp.constr.order] p2
685 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
686 // and only if there exists an atomic constraint Pia in Pi for which
687 // there exists an atomic constraint, Qjb, in Qj such that Pia
688 // subsumes Qjb.
689 bool Found = false;
690 for (const AtomicConstraint *Pia : Pi) {
691 for (const AtomicConstraint *Qjb : Qj) {
Saar Razb65b1f32020-01-09 15:07:51 +0200692 if (E(*Pia, *Qjb)) {
Saar Razdf061c32019-12-23 08:37:35 +0200693 Found = true;
694 break;
695 }
696 }
697 if (Found)
698 break;
699 }
Saar Razb65b1f32020-01-09 15:07:51 +0200700 if (!Found)
Saar Razdf061c32019-12-23 08:37:35 +0200701 return false;
Saar Razdf061c32019-12-23 08:37:35 +0200702 }
703 }
Saar Razb65b1f32020-01-09 15:07:51 +0200704 return true;
705}
706
707template<typename AtomicSubsumptionEvaluator>
708static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
709 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
710 AtomicSubsumptionEvaluator E) {
711 // C++ [temp.constr.order] p2
712 // In order to determine if a constraint P subsumes a constraint Q, P is
713 // transformed into disjunctive normal form, and Q is transformed into
714 // conjunctive normal form. [...]
715 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
716 if (!PNormalized)
717 return true;
718 const NormalForm PDNF = makeDNF(*PNormalized);
719
720 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
721 if (!QNormalized)
722 return true;
723 const NormalForm QCNF = makeCNF(*QNormalized);
724
725 Subsumes = subsumes(PDNF, QCNF, E);
Saar Razdf061c32019-12-23 08:37:35 +0200726 return false;
727}
728
729bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
730 NamedDecl *D2, ArrayRef<const Expr *> AC2,
731 bool &Result) {
732 if (AC1.empty()) {
733 Result = AC2.empty();
734 return false;
735 }
736 if (AC2.empty()) {
737 // TD1 has associated constraints and TD2 does not.
738 Result = true;
739 return false;
740 }
741
742 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
743 auto CacheEntry = SubsumptionCache.find(Key);
744 if (CacheEntry != SubsumptionCache.end()) {
745 Result = CacheEntry->second;
746 return false;
747 }
Saar Razb65b1f32020-01-09 15:07:51 +0200748
749 if (subsumes(*this, D1, AC1, D2, AC2, Result,
750 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
751 return A.subsumes(Context, B);
752 }))
Saar Razdf061c32019-12-23 08:37:35 +0200753 return true;
754 SubsumptionCache.try_emplace(Key, Result);
755 return false;
Saar Razb65b1f32020-01-09 15:07:51 +0200756}
757
758bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
759 ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
760 if (isSFINAEContext())
761 // No need to work here because our notes would be discarded.
762 return false;
763
764 if (AC1.empty() || AC2.empty())
765 return false;
766
767 auto NormalExprEvaluator =
768 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
769 return A.subsumes(Context, B);
770 };
771
772 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
773 auto IdenticalExprEvaluator =
774 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
775 if (!A.hasMatchingParameterMapping(Context, B))
776 return false;
777 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
778 if (EA == EB)
779 return true;
780
781 // Not the same source level expression - are the expressions
782 // identical?
783 llvm::FoldingSetNodeID IDA, IDB;
784 EA->Profile(IDA, Context, /*Cannonical=*/true);
785 EB->Profile(IDB, Context, /*Cannonical=*/true);
786 if (IDA != IDB)
787 return false;
788
789 AmbiguousAtomic1 = EA;
790 AmbiguousAtomic2 = EB;
791 return true;
792 };
793
794 {
795 // The subsumption checks might cause diagnostics
796 SFINAETrap Trap(*this);
797 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
798 if (!Normalized1)
799 return false;
800 const NormalForm DNF1 = makeDNF(*Normalized1);
801 const NormalForm CNF1 = makeCNF(*Normalized1);
802
803 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
804 if (!Normalized2)
805 return false;
806 const NormalForm DNF2 = makeDNF(*Normalized2);
807 const NormalForm CNF2 = makeCNF(*Normalized2);
808
809 bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
810 bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
811 bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
812 bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
813 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
814 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
815 // Same result - no ambiguity was caused by identical atomic expressions.
816 return false;
817 }
818
819 // A different result! Some ambiguous atomic constraint(s) caused a difference
820 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
821
822 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
823 << AmbiguousAtomic1->getSourceRange();
824 Diag(AmbiguousAtomic2->getBeginLoc(),
825 diag::note_ambiguous_atomic_constraints_similar_expression)
826 << AmbiguousAtomic2->getSourceRange();
827 return true;
828}