blob: 8fdc6023040ff07164f73130e75d4e2da9232a92 [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 Raza0f50d72020-01-18 09:11:43 +020020#include "clang/Sema/Overload.h"
21#include "clang/Sema/Initialization.h"
22#include "clang/Sema/SemaInternal.h"
23#include "clang/AST/ExprConcepts.h"
Saar Razdf061c32019-12-23 08:37:35 +020024#include "clang/AST/RecursiveASTVisitor.h"
Saar Razb65b1f32020-01-09 15:07:51 +020025#include "clang/Basic/OperatorPrecedence.h"
Saar Razfdf80e82019-12-06 01:30:21 +020026#include "llvm/ADT/DenseMap.h"
27#include "llvm/ADT/PointerUnion.h"
Saar Raz5d98ba62019-10-15 15:24:26 +000028using namespace clang;
29using namespace sema;
30
Saar Razb65b1f32020-01-09 15:07:51 +020031bool
32Sema::CheckConstraintExpression(Expr *ConstraintExpression, Token NextToken,
33 bool *PossibleNonPrimary,
34 bool IsTrailingRequiresClause) {
Saar Raz5d98ba62019-10-15 15:24:26 +000035 // C++2a [temp.constr.atomic]p1
36 // ..E shall be a constant expression of type bool.
37
38 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
39
40 if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
41 if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
Saar Razb65b1f32020-01-09 15:07:51 +020042 return CheckConstraintExpression(BinOp->getLHS(), NextToken,
43 PossibleNonPrimary) &&
44 CheckConstraintExpression(BinOp->getRHS(), NextToken,
45 PossibleNonPrimary);
Saar Raz5d98ba62019-10-15 15:24:26 +000046 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
Saar Razb65b1f32020-01-09 15:07:51 +020047 return CheckConstraintExpression(C->getSubExpr(), NextToken,
48 PossibleNonPrimary);
Saar Raz5d98ba62019-10-15 15:24:26 +000049
50 QualType Type = ConstraintExpression->getType();
Saar Razb65b1f32020-01-09 15:07:51 +020051
52 auto CheckForNonPrimary = [&] {
53 if (PossibleNonPrimary)
54 *PossibleNonPrimary =
55 // We have the following case:
56 // template<typename> requires func(0) struct S { };
57 // The user probably isn't aware of the parentheses required around
58 // the function call, and we're only going to parse 'func' as the
59 // primary-expression, and complain that it is of non-bool type.
60 (NextToken.is(tok::l_paren) &&
61 (IsTrailingRequiresClause ||
62 (Type->isDependentType() &&
63 IsDependentFunctionNameExpr(ConstraintExpression)) ||
64 Type->isFunctionType() ||
65 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
66 // We have the following case:
67 // template<typename T> requires size_<T> == 0 struct S { };
68 // The user probably isn't aware of the parentheses required around
69 // the binary operator, and we're only going to parse 'func' as the
70 // first operand, and complain that it is of non-bool type.
71 getBinOpPrecedence(NextToken.getKind(),
72 /*GreaterThanIsOperator=*/true,
73 getLangOpts().CPlusPlus11) > prec::LogicalAnd;
74 };
75
76 // An atomic constraint!
77 if (ConstraintExpression->isTypeDependent()) {
78 CheckForNonPrimary();
79 return true;
80 }
81
Saar Raz5d98ba62019-10-15 15:24:26 +000082 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
83 Diag(ConstraintExpression->getExprLoc(),
84 diag::err_non_bool_atomic_constraint) << Type
85 << ConstraintExpression->getSourceRange();
Saar Razb65b1f32020-01-09 15:07:51 +020086 CheckForNonPrimary();
Saar Raz5d98ba62019-10-15 15:24:26 +000087 return false;
88 }
Saar Razb65b1f32020-01-09 15:07:51 +020089
90 if (PossibleNonPrimary)
91 *PossibleNonPrimary = false;
Saar Raz5d98ba62019-10-15 15:24:26 +000092 return true;
93}
94
Saar Razfdf80e82019-12-06 01:30:21 +020095template <typename AtomicEvaluator>
96static bool
97calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
98 ConstraintSatisfaction &Satisfaction,
99 AtomicEvaluator &&Evaluator) {
Saar Raz5d98ba62019-10-15 15:24:26 +0000100 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
101
102 if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
Saar Razfdf80e82019-12-06 01:30:21 +0200103 if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
104 if (calculateConstraintSatisfaction(S, BO->getLHS(), Satisfaction,
105 Evaluator))
Saar Raz5d98ba62019-10-15 15:24:26 +0000106 return true;
Saar Razfdf80e82019-12-06 01:30:21 +0200107
108 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
109
110 if (BO->getOpcode() == BO_LOr && IsLHSSatisfied)
111 // [temp.constr.op] p3
112 // A disjunction is a constraint taking two operands. To determine if
113 // a disjunction is satisfied, the satisfaction of the first operand
114 // is checked. If that is satisfied, the disjunction is satisfied.
115 // Otherwise, the disjunction is satisfied if and only if the second
116 // operand is satisfied.
Saar Raz5d98ba62019-10-15 15:24:26 +0000117 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200118
119 if (BO->getOpcode() == BO_LAnd && !IsLHSSatisfied)
120 // [temp.constr.op] p2
121 // A conjunction is a constraint taking two operands. To determine if
122 // a conjunction is satisfied, the satisfaction of the first operand
123 // is checked. If that is not satisfied, the conjunction is not
124 // satisfied. Otherwise, the conjunction is satisfied if and only if
125 // the second operand is satisfied.
Saar Raz5d98ba62019-10-15 15:24:26 +0000126 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200127
128 return calculateConstraintSatisfaction(S, BO->getRHS(), Satisfaction,
129 std::forward<AtomicEvaluator>(Evaluator));
Saar Raz5d98ba62019-10-15 15:24:26 +0000130 }
131 }
132 else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
Saar Razfdf80e82019-12-06 01:30:21 +0200133 return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
134 std::forward<AtomicEvaluator>(Evaluator));
Saar Razffa214e2019-10-25 00:09:37 +0300135
Saar Razfdf80e82019-12-06 01:30:21 +0200136 // An atomic constraint expression
137 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
Vlad Tsyrklevich38839d02019-10-28 14:36:31 -0700138
Saar Razfdf80e82019-12-06 01:30:21 +0200139 if (SubstitutedAtomicExpr.isInvalid())
Vlad Tsyrklevich38839d02019-10-28 14:36:31 -0700140 return true;
141
Saar Razfdf80e82019-12-06 01:30:21 +0200142 if (!SubstitutedAtomicExpr.isUsable())
143 // Evaluator has decided satisfaction without yielding an expression.
144 return false;
145
146 EnterExpressionEvaluationContext ConstantEvaluated(
147 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
Saar Raz5d98ba62019-10-15 15:24:26 +0000148 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
149 Expr::EvalResult EvalResult;
150 EvalResult.Diag = &EvaluationDiags;
Saar Razfdf80e82019-12-06 01:30:21 +0200151 if (!SubstitutedAtomicExpr.get()->EvaluateAsRValue(EvalResult, S.Context)) {
152 // C++2a [temp.constr.atomic]p1
153 // ...E shall be a constant expression of type bool.
154 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
155 diag::err_non_constant_constraint_expression)
156 << SubstitutedAtomicExpr.get()->getSourceRange();
Saar Raz5d98ba62019-10-15 15:24:26 +0000157 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
Saar Razfdf80e82019-12-06 01:30:21 +0200158 S.Diag(PDiag.first, PDiag.second);
Saar Raz5d98ba62019-10-15 15:24:26 +0000159 return true;
160 }
161
Saar Razfdf80e82019-12-06 01:30:21 +0200162 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
163 if (!Satisfaction.IsSatisfied)
164 Satisfaction.Details.emplace_back(ConstraintExpr,
165 SubstitutedAtomicExpr.get());
Saar Raz5d98ba62019-10-15 15:24:26 +0000166
167 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200168}
169
Saar Razfdf80e82019-12-06 01:30:21 +0200170static bool calculateConstraintSatisfaction(
Saar Raz713562f2020-01-25 22:54:27 +0200171 Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
Saar Razfdf80e82019-12-06 01:30:21 +0200172 SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
173 const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
174 return calculateConstraintSatisfaction(
175 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
176 EnterExpressionEvaluationContext ConstantEvaluated(
177 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
178
179 // Atomic constraint - substitute arguments and check satisfaction.
180 ExprResult SubstitutedExpression;
181 {
182 TemplateDeductionInfo Info(TemplateNameLoc);
183 Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
Saar Raz713562f2020-01-25 22:54:27 +0200184 Sema::InstantiatingTemplate::ConstraintSubstitution{},
185 const_cast<NamedDecl *>(Template), Info,
186 AtomicExpr->getSourceRange());
Saar Razfdf80e82019-12-06 01:30:21 +0200187 if (Inst.isInvalid())
188 return ExprError();
189 // We do not want error diagnostics escaping here.
190 Sema::SFINAETrap Trap(S);
191 SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
192 MLTAL);
193 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
194 // C++2a [temp.constr.atomic]p1
195 // ...If substitution results in an invalid type or expression, the
196 // constraint is not satisfied.
197 if (!Trap.hasErrorOccurred())
198 // A non-SFINAE error has occured as a result of this
199 // substitution.
200 return ExprError();
201
202 PartialDiagnosticAt SubstDiag{SourceLocation(),
203 PartialDiagnostic::NullDiagnostic()};
204 Info.takeSFINAEDiagnostic(SubstDiag);
205 // FIXME: Concepts: This is an unfortunate consequence of there
206 // being no serialization code for PartialDiagnostics and the fact
207 // that serializing them would likely take a lot more storage than
208 // just storing them as strings. We would still like, in the
209 // future, to serialize the proper PartialDiagnostic as serializing
210 // it as a string defeats the purpose of the diagnostic mechanism.
211 SmallString<128> DiagString;
212 DiagString = ": ";
213 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
214 unsigned MessageSize = DiagString.size();
215 char *Mem = new (S.Context) char[MessageSize];
216 memcpy(Mem, DiagString.c_str(), MessageSize);
217 Satisfaction.Details.emplace_back(
218 AtomicExpr,
219 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
220 SubstDiag.first, StringRef(Mem, MessageSize)});
221 Satisfaction.IsSatisfied = false;
222 return ExprEmpty();
223 }
224 }
225
226 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
227 return ExprError();
228
229 return SubstitutedExpression;
230 });
231}
232
Saar Raz713562f2020-01-25 22:54:27 +0200233static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
Saar Razfdf80e82019-12-06 01:30:21 +0200234 ArrayRef<const Expr *> ConstraintExprs,
235 ArrayRef<TemplateArgument> TemplateArgs,
236 SourceRange TemplateIDRange,
237 ConstraintSatisfaction &Satisfaction) {
238 if (ConstraintExprs.empty()) {
239 Satisfaction.IsSatisfied = true;
240 return false;
241 }
242
243 for (auto& Arg : TemplateArgs)
244 if (Arg.isInstantiationDependent()) {
245 // No need to check satisfaction for dependent constraint expressions.
246 Satisfaction.IsSatisfied = true;
247 return false;
248 }
249
250 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
Saar Raz713562f2020-01-25 22:54:27 +0200251 Sema::InstantiatingTemplate::ConstraintsCheck{},
252 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
Saar Razfdf80e82019-12-06 01:30:21 +0200253 if (Inst.isInvalid())
254 return true;
255
256 MultiLevelTemplateArgumentList MLTAL;
257 MLTAL.addOuterTemplateArguments(TemplateArgs);
258
259 for (const Expr *ConstraintExpr : ConstraintExprs) {
260 if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
261 TemplateIDRange.getBegin(), MLTAL,
262 ConstraintExpr, Satisfaction))
263 return true;
264 if (!Satisfaction.IsSatisfied)
265 // [temp.constr.op] p2
266 // [...] To determine if a conjunction is satisfied, the satisfaction
267 // of the first operand is checked. If that is not satisfied, the
268 // conjunction is not satisfied. [...]
269 return false;
270 }
271 return false;
272}
273
Saar Razb933d372020-01-22 02:50:12 +0200274bool Sema::CheckConstraintSatisfaction(
Saar Raz713562f2020-01-25 22:54:27 +0200275 const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
Saar Razb933d372020-01-22 02:50:12 +0200276 ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
277 ConstraintSatisfaction &OutSatisfaction) {
278 if (ConstraintExprs.empty()) {
279 OutSatisfaction.IsSatisfied = true;
280 return false;
281 }
Saar Razfdf80e82019-12-06 01:30:21 +0200282
Saar Razb933d372020-01-22 02:50:12 +0200283 llvm::FoldingSetNodeID ID;
284 void *InsertPos;
285 ConstraintSatisfaction *Satisfaction = nullptr;
Saar Raz713562f2020-01-25 22:54:27 +0200286 bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
287 if (ShouldCache) {
Saar Razb933d372020-01-22 02:50:12 +0200288 ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
289 Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
290 if (Satisfaction) {
291 OutSatisfaction = *Satisfaction;
292 return false;
293 }
294 Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
295 } else {
296 Satisfaction = &OutSatisfaction;
297 }
Saar Raz713562f2020-01-25 22:54:27 +0200298 if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
299 TemplateArgs, TemplateIDRange,
300 *Satisfaction)) {
301 if (ShouldCache)
Saar Razb933d372020-01-22 02:50:12 +0200302 delete Satisfaction;
303 return true;
304 }
Saar Razfdf80e82019-12-06 01:30:21 +0200305
Saar Raz713562f2020-01-25 22:54:27 +0200306 if (ShouldCache) {
Saar Razb933d372020-01-22 02:50:12 +0200307 // We cannot use InsertNode here because CheckConstraintSatisfaction might
308 // have invalidated it.
309 SatisfactionCache.InsertNode(Satisfaction);
310 OutSatisfaction = *Satisfaction;
311 }
312 return false;
Saar Razfdf80e82019-12-06 01:30:21 +0200313}
314
315bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
316 ConstraintSatisfaction &Satisfaction) {
317 return calculateConstraintSatisfaction(
318 *this, ConstraintExpr, Satisfaction,
319 [](const Expr *AtomicExpr) -> ExprResult {
320 return ExprResult(const_cast<Expr *>(AtomicExpr));
321 });
322}
323
Saar Raz713562f2020-01-25 22:54:27 +0200324bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
325 ConstraintSatisfaction &Satisfaction,
326 SourceLocation UsageLoc) {
327 const Expr *RC = FD->getTrailingRequiresClause();
Saar Raza424ef99e72020-01-30 20:46:32 +0200328 if (RC->isInstantiationDependent()) {
329 Satisfaction.IsSatisfied = true;
330 return false;
331 }
Saar Raz713562f2020-01-25 22:54:27 +0200332 // We substitute with empty arguments in order to rebuild the atomic
333 // constraint in a constant-evaluated context.
334 // FIXME: Should this be a dedicated TreeTransform?
335 return CheckConstraintSatisfaction(
336 FD, {RC}, /*TemplateArgs=*/{},
337 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
338 Satisfaction);
339}
340
Saar Razfdf80e82019-12-06 01:30:21 +0200341bool Sema::EnsureTemplateArgumentListConstraints(
342 TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
343 SourceRange TemplateIDRange) {
344 ConstraintSatisfaction Satisfaction;
345 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
346 TD->getAssociatedConstraints(AssociatedConstraints);
347 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
348 TemplateIDRange, Satisfaction))
349 return true;
350
351 if (!Satisfaction.IsSatisfied) {
352 SmallString<128> TemplateArgString;
353 TemplateArgString = " ";
354 TemplateArgString += getTemplateArgumentBindingsText(
355 TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
356
357 Diag(TemplateIDRange.getBegin(),
358 diag::err_template_arg_list_constraints_not_satisfied)
359 << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
360 << TemplateArgString << TemplateIDRange;
361 DiagnoseUnsatisfiedConstraint(Satisfaction);
362 return true;
363 }
364 return false;
365}
366
Saar Raza0f50d72020-01-18 09:11:43 +0200367static void diagnoseUnsatisfiedRequirement(Sema &S,
368 concepts::ExprRequirement *Req,
369 bool First) {
370 assert(!Req->isSatisfied()
371 && "Diagnose() can only be used on an unsatisfied requirement");
372 switch (Req->getSatisfactionStatus()) {
373 case concepts::ExprRequirement::SS_Dependent:
374 llvm_unreachable("Diagnosing a dependent requirement");
375 break;
376 case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
377 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
378 if (!SubstDiag->DiagMessage.empty())
379 S.Diag(SubstDiag->DiagLoc,
380 diag::note_expr_requirement_expr_substitution_error)
381 << (int)First << SubstDiag->SubstitutedEntity
382 << SubstDiag->DiagMessage;
383 else
384 S.Diag(SubstDiag->DiagLoc,
385 diag::note_expr_requirement_expr_unknown_substitution_error)
386 << (int)First << SubstDiag->SubstitutedEntity;
387 break;
388 }
389 case concepts::ExprRequirement::SS_NoexceptNotMet:
390 S.Diag(Req->getNoexceptLoc(),
391 diag::note_expr_requirement_noexcept_not_met)
392 << (int)First << Req->getExpr();
393 break;
394 case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
395 auto *SubstDiag =
396 Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
397 if (!SubstDiag->DiagMessage.empty())
398 S.Diag(SubstDiag->DiagLoc,
399 diag::note_expr_requirement_type_requirement_substitution_error)
400 << (int)First << SubstDiag->SubstitutedEntity
401 << SubstDiag->DiagMessage;
402 else
403 S.Diag(SubstDiag->DiagLoc,
404 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
405 << (int)First << SubstDiag->SubstitutedEntity;
406 break;
407 }
408 case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
409 ConceptSpecializationExpr *ConstraintExpr =
410 Req->getReturnTypeRequirementSubstitutedConstraintExpr();
411 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1)
412 // A simple case - expr type is the type being constrained and the concept
413 // was not provided arguments.
414 S.Diag(ConstraintExpr->getBeginLoc(),
415 diag::note_expr_requirement_constraints_not_satisfied_simple)
416 << (int)First << S.BuildDecltypeType(Req->getExpr(),
417 Req->getExpr()->getBeginLoc())
418 << ConstraintExpr->getNamedConcept();
419 else
420 S.Diag(ConstraintExpr->getBeginLoc(),
421 diag::note_expr_requirement_constraints_not_satisfied)
422 << (int)First << ConstraintExpr;
423 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
424 break;
425 }
426 case concepts::ExprRequirement::SS_Satisfied:
427 llvm_unreachable("We checked this above");
428 }
429}
430
431static void diagnoseUnsatisfiedRequirement(Sema &S,
432 concepts::TypeRequirement *Req,
433 bool First) {
434 assert(!Req->isSatisfied()
435 && "Diagnose() can only be used on an unsatisfied requirement");
436 switch (Req->getSatisfactionStatus()) {
437 case concepts::TypeRequirement::SS_Dependent:
438 llvm_unreachable("Diagnosing a dependent requirement");
439 return;
440 case concepts::TypeRequirement::SS_SubstitutionFailure: {
441 auto *SubstDiag = Req->getSubstitutionDiagnostic();
442 if (!SubstDiag->DiagMessage.empty())
443 S.Diag(SubstDiag->DiagLoc,
444 diag::note_type_requirement_substitution_error) << (int)First
445 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
446 else
447 S.Diag(SubstDiag->DiagLoc,
448 diag::note_type_requirement_unknown_substitution_error)
449 << (int)First << SubstDiag->SubstitutedEntity;
450 return;
451 }
452 default:
453 llvm_unreachable("Unknown satisfaction status");
454 return;
455 }
456}
457
458static void diagnoseUnsatisfiedRequirement(Sema &S,
459 concepts::NestedRequirement *Req,
460 bool First) {
461 if (Req->isSubstitutionFailure()) {
462 concepts::Requirement::SubstitutionDiagnostic *SubstDiag =
463 Req->getSubstitutionDiagnostic();
464 if (!SubstDiag->DiagMessage.empty())
465 S.Diag(SubstDiag->DiagLoc,
466 diag::note_nested_requirement_substitution_error)
467 << (int)First << SubstDiag->SubstitutedEntity
468 << SubstDiag->DiagMessage;
469 else
470 S.Diag(SubstDiag->DiagLoc,
471 diag::note_nested_requirement_unknown_substitution_error)
472 << (int)First << SubstDiag->SubstitutedEntity;
473 return;
474 }
475 S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First);
476}
477
478
Saar Razfdf80e82019-12-06 01:30:21 +0200479static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
480 Expr *SubstExpr,
481 bool First = true) {
482 SubstExpr = SubstExpr->IgnoreParenImpCasts();
483 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
484 switch (BO->getOpcode()) {
485 // These two cases will in practice only be reached when using fold
486 // expressions with || and &&, since otherwise the || and && will have been
487 // broken down into atomic constraints during satisfaction checking.
488 case BO_LOr:
489 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
490 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
491 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
492 /*First=*/false);
493 return;
494 case BO_LAnd:
495 bool LHSSatisfied;
496 BO->getLHS()->EvaluateAsBooleanCondition(LHSSatisfied, S.Context);
497 if (LHSSatisfied) {
498 // LHS is true, so RHS must be false.
499 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
500 return;
501 }
502 // LHS is false
503 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
504
505 // RHS might also be false
506 bool RHSSatisfied;
507 BO->getRHS()->EvaluateAsBooleanCondition(RHSSatisfied, S.Context);
508 if (!RHSSatisfied)
509 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
510 /*First=*/false);
511 return;
512 case BO_GE:
513 case BO_LE:
514 case BO_GT:
515 case BO_LT:
516 case BO_EQ:
517 case BO_NE:
518 if (BO->getLHS()->getType()->isIntegerType() &&
519 BO->getRHS()->getType()->isIntegerType()) {
520 Expr::EvalResult SimplifiedLHS;
521 Expr::EvalResult SimplifiedRHS;
522 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context);
523 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context);
524 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
525 S.Diag(SubstExpr->getBeginLoc(),
526 diag::note_atomic_constraint_evaluated_to_false_elaborated)
527 << (int)First << SubstExpr
528 << SimplifiedLHS.Val.getInt().toString(10)
529 << BinaryOperator::getOpcodeStr(BO->getOpcode())
530 << SimplifiedRHS.Val.getInt().toString(10);
531 return;
532 }
533 }
534 break;
535
536 default:
537 break;
538 }
539 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
540 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
541 S.Diag(
542 CSE->getSourceRange().getBegin(),
543 diag::
544 note_single_arg_concept_specialization_constraint_evaluated_to_false)
545 << (int)First
546 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
547 << CSE->getNamedConcept();
548 } else {
549 S.Diag(SubstExpr->getSourceRange().getBegin(),
550 diag::note_concept_specialization_constraint_evaluated_to_false)
551 << (int)First << CSE;
552 }
553 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
554 return;
Saar Raza0f50d72020-01-18 09:11:43 +0200555 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
556 for (concepts::Requirement *Req : RE->getRequirements())
557 if (!Req->isDependent() && !Req->isSatisfied()) {
558 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
559 diagnoseUnsatisfiedRequirement(S, E, First);
560 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
561 diagnoseUnsatisfiedRequirement(S, T, First);
562 else
563 diagnoseUnsatisfiedRequirement(
564 S, cast<concepts::NestedRequirement>(Req), First);
565 break;
566 }
567 return;
Saar Razfdf80e82019-12-06 01:30:21 +0200568 }
569
570 S.Diag(SubstExpr->getSourceRange().getBegin(),
571 diag::note_atomic_constraint_evaluated_to_false)
572 << (int)First << SubstExpr;
573}
574
575template<typename SubstitutionDiagnostic>
576static void diagnoseUnsatisfiedConstraintExpr(
577 Sema &S, const Expr *E,
578 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
579 bool First = true) {
580 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
581 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
582 << Diag->second;
583 return;
584 }
585
586 diagnoseWellFormedUnsatisfiedConstraintExpr(S,
587 Record.template get<Expr *>(), First);
588}
589
Saar Raza0f50d72020-01-18 09:11:43 +0200590void
591Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
592 bool First) {
Saar Razfdf80e82019-12-06 01:30:21 +0200593 assert(!Satisfaction.IsSatisfied &&
594 "Attempted to diagnose a satisfied constraint");
Saar Razfdf80e82019-12-06 01:30:21 +0200595 for (auto &Pair : Satisfaction.Details) {
596 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
597 First = false;
598 }
599}
600
601void Sema::DiagnoseUnsatisfiedConstraint(
Saar Raza0f50d72020-01-18 09:11:43 +0200602 const ASTConstraintSatisfaction &Satisfaction,
603 bool First) {
Saar Razfdf80e82019-12-06 01:30:21 +0200604 assert(!Satisfaction.IsSatisfied &&
605 "Attempted to diagnose a satisfied constraint");
Saar Razfdf80e82019-12-06 01:30:21 +0200606 for (auto &Pair : Satisfaction) {
607 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
608 First = false;
609 }
Saar Razdf061c32019-12-23 08:37:35 +0200610}
611
Saar Razb65b1f32020-01-09 15:07:51 +0200612const NormalizedConstraint *
613Sema::getNormalizedAssociatedConstraints(
614 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
615 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
616 if (CacheEntry == NormalizationCache.end()) {
617 auto Normalized =
618 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
619 AssociatedConstraints);
620 CacheEntry =
621 NormalizationCache
622 .try_emplace(ConstrainedDecl,
623 Normalized
624 ? new (Context) NormalizedConstraint(
625 std::move(*Normalized))
626 : nullptr)
627 .first;
Saar Razdf061c32019-12-23 08:37:35 +0200628 }
Saar Razb65b1f32020-01-09 15:07:51 +0200629 return CacheEntry->second;
630}
Saar Razdf061c32019-12-23 08:37:35 +0200631
632static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
633 ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
634 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
635 if (!N.isAtomic()) {
636 if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
637 ArgsAsWritten))
638 return true;
639 return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
640 ArgsAsWritten);
641 }
642 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
643
644 AtomicConstraint &Atomic = *N.getAtomicConstraint();
645 TemplateArgumentListInfo SubstArgs;
646 MultiLevelTemplateArgumentList MLTAL;
647 MLTAL.addOuterTemplateArguments(TemplateArgs);
648 if (!Atomic.ParameterMapping) {
649 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
650 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
651 /*Depth=*/0, OccurringIndices);
Saar Razb65b1f32020-01-09 15:07:51 +0200652 Atomic.ParameterMapping.emplace(
653 MutableArrayRef<TemplateArgumentLoc>(
654 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
655 OccurringIndices.count()));
656 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
Saar Razdf061c32019-12-23 08:37:35 +0200657 if (OccurringIndices[I])
Saar Razb65b1f32020-01-09 15:07:51 +0200658 new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
Saar Razdf061c32019-12-23 08:37:35 +0200659 S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
660 // Here we assume we do not support things like
661 // template<typename A, typename B>
662 // concept C = ...;
663 //
664 // template<typename... Ts> requires C<Ts...>
665 // struct S { };
666 // The above currently yields a diagnostic.
667 // We still might have default arguments for concept parameters.
668 ArgsAsWritten->NumTemplateArgs > I ?
669 ArgsAsWritten->arguments()[I].getLocation() :
670 SourceLocation()));
671 }
672 Sema::InstantiatingTemplate Inst(
673 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
674 Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
675 SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
676 ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
677 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
678 return true;
679 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
680 N.getAtomicConstraint()->ParameterMapping->begin());
681 return false;
682}
683
Saar Razb65b1f32020-01-09 15:07:51 +0200684Optional<NormalizedConstraint>
685NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
686 ArrayRef<const Expr *> E) {
687 assert(E.size() != 0);
688 auto First = fromConstraintExpr(S, D, E[0]);
689 if (E.size() == 1)
690 return First;
691 auto Second = fromConstraintExpr(S, D, E[1]);
692 if (!Second)
693 return None;
694 llvm::Optional<NormalizedConstraint> Conjunction;
695 Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
696 CCK_Conjunction);
697 for (unsigned I = 2; I < E.size(); ++I) {
698 auto Next = fromConstraintExpr(S, D, E[I]);
699 if (!Next)
700 return llvm::Optional<NormalizedConstraint>{};
701 NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
702 std::move(*Next), CCK_Conjunction);
703 *Conjunction = std::move(NewConjunction);
704 }
705 return Conjunction;
706}
707
Saar Razdf061c32019-12-23 08:37:35 +0200708llvm::Optional<NormalizedConstraint>
709NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
710 assert(E != nullptr);
711
712 // C++ [temp.constr.normal]p1.1
713 // [...]
714 // - The normal form of an expression (E) is the normal form of E.
715 // [...]
716 E = E->IgnoreParenImpCasts();
717 if (auto *BO = dyn_cast<const BinaryOperator>(E)) {
718 if (BO->getOpcode() == BO_LAnd || BO->getOpcode() == BO_LOr) {
719 auto LHS = fromConstraintExpr(S, D, BO->getLHS());
720 if (!LHS)
721 return None;
722 auto RHS = fromConstraintExpr(S, D, BO->getRHS());
723 if (!RHS)
724 return None;
725
726 return NormalizedConstraint(
Saar Razb65b1f32020-01-09 15:07:51 +0200727 S.Context, std::move(*LHS), std::move(*RHS),
Saar Razdf061c32019-12-23 08:37:35 +0200728 BO->getOpcode() == BO_LAnd ? CCK_Conjunction : CCK_Disjunction);
729 }
730 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
Saar Razb65b1f32020-01-09 15:07:51 +0200731 const NormalizedConstraint *SubNF;
Saar Razdf061c32019-12-23 08:37:35 +0200732 {
733 Sema::InstantiatingTemplate Inst(
734 S, CSE->getExprLoc(),
735 Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
736 CSE->getSourceRange());
737 // C++ [temp.constr.normal]p1.1
738 // [...]
739 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
740 // where C names a concept, is the normal form of the
741 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
742 // respective template parameters in the parameter mappings in each atomic
743 // constraint. If any such substitution results in an invalid type or
744 // expression, the program is ill-formed; no diagnostic is required.
745 // [...]
Saar Razb65b1f32020-01-09 15:07:51 +0200746 ConceptDecl *CD = CSE->getNamedConcept();
747 SubNF = S.getNormalizedAssociatedConstraints(CD,
748 {CD->getConstraintExpr()});
Saar Razdf061c32019-12-23 08:37:35 +0200749 if (!SubNF)
750 return None;
751 }
752
Saar Razb65b1f32020-01-09 15:07:51 +0200753 Optional<NormalizedConstraint> New;
754 New.emplace(S.Context, *SubNF);
755
Saar Razdf061c32019-12-23 08:37:35 +0200756 if (substituteParameterMappings(
Saar Razb65b1f32020-01-09 15:07:51 +0200757 S, *New, CSE->getNamedConcept(),
Saar Razdf061c32019-12-23 08:37:35 +0200758 CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
759 return None;
760
Saar Razb65b1f32020-01-09 15:07:51 +0200761 return New;
Saar Razdf061c32019-12-23 08:37:35 +0200762 }
763 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
764}
765
Saar Razdf061c32019-12-23 08:37:35 +0200766using NormalForm =
767 llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
768
769static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
770 if (Normalized.isAtomic())
771 return {{Normalized.getAtomicConstraint()}};
772
773 NormalForm LCNF = makeCNF(Normalized.getLHS());
774 NormalForm RCNF = makeCNF(Normalized.getRHS());
775 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
776 LCNF.reserve(LCNF.size() + RCNF.size());
777 while (!RCNF.empty())
778 LCNF.push_back(RCNF.pop_back_val());
779 return LCNF;
780 }
781
782 // Disjunction
783 NormalForm Res;
784 Res.reserve(LCNF.size() * RCNF.size());
785 for (auto &LDisjunction : LCNF)
786 for (auto &RDisjunction : RCNF) {
787 NormalForm::value_type Combined;
788 Combined.reserve(LDisjunction.size() + RDisjunction.size());
789 std::copy(LDisjunction.begin(), LDisjunction.end(),
790 std::back_inserter(Combined));
791 std::copy(RDisjunction.begin(), RDisjunction.end(),
792 std::back_inserter(Combined));
793 Res.emplace_back(Combined);
794 }
795 return Res;
796}
797
798static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
799 if (Normalized.isAtomic())
800 return {{Normalized.getAtomicConstraint()}};
801
802 NormalForm LDNF = makeDNF(Normalized.getLHS());
803 NormalForm RDNF = makeDNF(Normalized.getRHS());
804 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
805 LDNF.reserve(LDNF.size() + RDNF.size());
806 while (!RDNF.empty())
807 LDNF.push_back(RDNF.pop_back_val());
808 return LDNF;
809 }
810
811 // Conjunction
812 NormalForm Res;
813 Res.reserve(LDNF.size() * RDNF.size());
814 for (auto &LConjunction : LDNF) {
815 for (auto &RConjunction : RDNF) {
816 NormalForm::value_type Combined;
817 Combined.reserve(LConjunction.size() + RConjunction.size());
818 std::copy(LConjunction.begin(), LConjunction.end(),
819 std::back_inserter(Combined));
820 std::copy(RConjunction.begin(), RConjunction.end(),
821 std::back_inserter(Combined));
822 Res.emplace_back(Combined);
823 }
824 }
825 return Res;
826}
827
Saar Razb65b1f32020-01-09 15:07:51 +0200828template<typename AtomicSubsumptionEvaluator>
829static bool subsumes(NormalForm PDNF, NormalForm QCNF,
830 AtomicSubsumptionEvaluator E) {
Saar Razdf061c32019-12-23 08:37:35 +0200831 // C++ [temp.constr.order] p2
832 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
833 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
834 // the conjuctive normal form of Q, where [...]
835 for (const auto &Pi : PDNF) {
836 for (const auto &Qj : QCNF) {
837 // C++ [temp.constr.order] p2
838 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
839 // and only if there exists an atomic constraint Pia in Pi for which
840 // there exists an atomic constraint, Qjb, in Qj such that Pia
841 // subsumes Qjb.
842 bool Found = false;
843 for (const AtomicConstraint *Pia : Pi) {
844 for (const AtomicConstraint *Qjb : Qj) {
Saar Razb65b1f32020-01-09 15:07:51 +0200845 if (E(*Pia, *Qjb)) {
Saar Razdf061c32019-12-23 08:37:35 +0200846 Found = true;
847 break;
848 }
849 }
850 if (Found)
851 break;
852 }
Saar Razb65b1f32020-01-09 15:07:51 +0200853 if (!Found)
Saar Razdf061c32019-12-23 08:37:35 +0200854 return false;
Saar Razdf061c32019-12-23 08:37:35 +0200855 }
856 }
Saar Razb65b1f32020-01-09 15:07:51 +0200857 return true;
858}
859
860template<typename AtomicSubsumptionEvaluator>
861static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
862 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
863 AtomicSubsumptionEvaluator E) {
864 // C++ [temp.constr.order] p2
865 // In order to determine if a constraint P subsumes a constraint Q, P is
866 // transformed into disjunctive normal form, and Q is transformed into
867 // conjunctive normal form. [...]
868 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
869 if (!PNormalized)
870 return true;
871 const NormalForm PDNF = makeDNF(*PNormalized);
872
873 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
874 if (!QNormalized)
875 return true;
876 const NormalForm QCNF = makeCNF(*QNormalized);
877
878 Subsumes = subsumes(PDNF, QCNF, E);
Saar Razdf061c32019-12-23 08:37:35 +0200879 return false;
880}
881
882bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
883 NamedDecl *D2, ArrayRef<const Expr *> AC2,
884 bool &Result) {
885 if (AC1.empty()) {
886 Result = AC2.empty();
887 return false;
888 }
889 if (AC2.empty()) {
890 // TD1 has associated constraints and TD2 does not.
891 Result = true;
892 return false;
893 }
894
895 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
896 auto CacheEntry = SubsumptionCache.find(Key);
897 if (CacheEntry != SubsumptionCache.end()) {
898 Result = CacheEntry->second;
899 return false;
900 }
Saar Razb65b1f32020-01-09 15:07:51 +0200901
902 if (subsumes(*this, D1, AC1, D2, AC2, Result,
903 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
904 return A.subsumes(Context, B);
905 }))
Saar Razdf061c32019-12-23 08:37:35 +0200906 return true;
907 SubsumptionCache.try_emplace(Key, Result);
908 return false;
Saar Razb65b1f32020-01-09 15:07:51 +0200909}
910
911bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
912 ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
913 if (isSFINAEContext())
914 // No need to work here because our notes would be discarded.
915 return false;
916
917 if (AC1.empty() || AC2.empty())
918 return false;
919
920 auto NormalExprEvaluator =
921 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
922 return A.subsumes(Context, B);
923 };
924
925 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
926 auto IdenticalExprEvaluator =
927 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
928 if (!A.hasMatchingParameterMapping(Context, B))
929 return false;
930 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
931 if (EA == EB)
932 return true;
933
934 // Not the same source level expression - are the expressions
935 // identical?
936 llvm::FoldingSetNodeID IDA, IDB;
937 EA->Profile(IDA, Context, /*Cannonical=*/true);
938 EB->Profile(IDB, Context, /*Cannonical=*/true);
939 if (IDA != IDB)
940 return false;
941
942 AmbiguousAtomic1 = EA;
943 AmbiguousAtomic2 = EB;
944 return true;
945 };
946
947 {
948 // The subsumption checks might cause diagnostics
949 SFINAETrap Trap(*this);
950 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
951 if (!Normalized1)
952 return false;
953 const NormalForm DNF1 = makeDNF(*Normalized1);
954 const NormalForm CNF1 = makeCNF(*Normalized1);
955
956 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
957 if (!Normalized2)
958 return false;
959 const NormalForm DNF2 = makeDNF(*Normalized2);
960 const NormalForm CNF2 = makeCNF(*Normalized2);
961
962 bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
963 bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
964 bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
965 bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
966 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
967 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
968 // Same result - no ambiguity was caused by identical atomic expressions.
969 return false;
970 }
971
972 // A different result! Some ambiguous atomic constraint(s) caused a difference
973 assert(AmbiguousAtomic1 && AmbiguousAtomic2);
974
975 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
976 << AmbiguousAtomic1->getSourceRange();
977 Diag(AmbiguousAtomic2->getBeginLoc(),
978 diag::note_ambiguous_atomic_constraints_similar_expression)
979 << AmbiguousAtomic2->getSourceRange();
980 return true;
981}
Saar Raza0f50d72020-01-18 09:11:43 +0200982
983concepts::ExprRequirement::ExprRequirement(
984 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
985 ReturnTypeRequirement Req, SatisfactionStatus Status,
986 ConceptSpecializationExpr *SubstitutedConstraintExpr) :
987 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
988 Status == SS_Dependent &&
989 (E->containsUnexpandedParameterPack() ||
990 Req.containsUnexpandedParameterPack()),
991 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
992 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
993 Status(Status) {
994 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
995 "Simple requirement must not have a return type requirement or a "
996 "noexcept specification");
997 assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==
998 (SubstitutedConstraintExpr != nullptr));
999}
1000
1001concepts::ExprRequirement::ExprRequirement(
1002 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1003 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1004 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1005 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1006 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1007 Status(SS_ExprSubstitutionFailure) {
1008 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&
1009 "Simple requirement must not have a return type requirement or a "
1010 "noexcept specification");
1011}
1012
1013concepts::ExprRequirement::ReturnTypeRequirement::
1014ReturnTypeRequirement(TemplateParameterList *TPL) :
1015 TypeConstraintInfo(TPL, 0) {
1016 assert(TPL->size() == 1);
1017 const TypeConstraint *TC =
1018 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
1019 assert(TC &&
1020 "TPL must have a template type parameter with a type constraint");
1021 auto *Constraint =
1022 cast_or_null<ConceptSpecializationExpr>(
1023 TC->getImmediatelyDeclaredConstraint());
1024 bool Dependent = false;
1025 if (Constraint->getTemplateArgsAsWritten()) {
1026 for (auto &ArgLoc :
1027 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)) {
1028 if (ArgLoc.getArgument().isDependent()) {
1029 Dependent = true;
1030 break;
1031 }
1032 }
1033 }
1034 TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1035}
1036
1037concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1038 Requirement(RK_Type, T->getType()->isDependentType(),
1039 T->getType()->containsUnexpandedParameterPack(),
1040 // We reach this ctor with either dependent types (in which
1041 // IsSatisfied doesn't matter) or with non-dependent type in
1042 // which the existence of the type indicates satisfaction.
1043 /*IsSatisfied=*/true
1044 ), Value(T),
1045 Status(T->getType()->isDependentType() ? SS_Dependent : SS_Satisfied) {}