Bug Summary

File:clang/lib/Sema/SemaConcept.cpp
Warning:line 1079, column 7
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name SemaConcept.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -relaxed-aliasing -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/tools/clang/lib/Sema -resource-dir /usr/lib/llvm-13/lib/clang/13.0.0 -D CLANG_ROUND_TRIP_CC1_ARGS=ON -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/tools/clang/lib/Sema -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/include -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/include -I /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/include -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-13/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/build-llvm/tools/clang/lib/Sema -fdebug-prefix-map=/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c=. -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-07-26-235520-9401-1 -x c++ /build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp
1//===-- 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
14#include "clang/Sema/SemaConcept.h"
15#include "clang/Sema/Sema.h"
16#include "clang/Sema/SemaInternal.h"
17#include "clang/Sema/SemaDiagnostic.h"
18#include "clang/Sema/TemplateDeduction.h"
19#include "clang/Sema/Template.h"
20#include "clang/Sema/Overload.h"
21#include "clang/Sema/Initialization.h"
22#include "clang/Sema/SemaInternal.h"
23#include "clang/AST/ExprConcepts.h"
24#include "clang/AST/RecursiveASTVisitor.h"
25#include "clang/Basic/OperatorPrecedence.h"
26#include "llvm/ADT/DenseMap.h"
27#include "llvm/ADT/PointerUnion.h"
28#include "llvm/ADT/StringExtras.h"
29
30using namespace clang;
31using namespace sema;
32
33namespace {
34class LogicalBinOp {
35 OverloadedOperatorKind Op = OO_None;
36 const Expr *LHS = nullptr;
37 const Expr *RHS = nullptr;
38
39public:
40 LogicalBinOp(const Expr *E) {
41 if (auto *BO = dyn_cast<BinaryOperator>(E)) {
42 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode());
43 LHS = BO->getLHS();
44 RHS = BO->getRHS();
45 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) {
46 // If OO is not || or && it might not have exactly 2 arguments.
47 if (OO->getNumArgs() == 2) {
48 Op = OO->getOperator();
49 LHS = OO->getArg(0);
50 RHS = OO->getArg(1);
51 }
52 }
53 }
54
55 bool isAnd() const { return Op == OO_AmpAmp; }
56 bool isOr() const { return Op == OO_PipePipe; }
57 explicit operator bool() const { return isAnd() || isOr(); }
58
59 const Expr *getLHS() const { return LHS; }
60 const Expr *getRHS() const { return RHS; }
61};
62}
63
64bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression,
65 Token NextToken, bool *PossibleNonPrimary,
66 bool IsTrailingRequiresClause) {
67 // C++2a [temp.constr.atomic]p1
68 // ..E shall be a constant expression of type bool.
69
70 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
71
72 if (LogicalBinOp BO = ConstraintExpression) {
73 return CheckConstraintExpression(BO.getLHS(), NextToken,
74 PossibleNonPrimary) &&
75 CheckConstraintExpression(BO.getRHS(), NextToken,
76 PossibleNonPrimary);
77 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
78 return CheckConstraintExpression(C->getSubExpr(), NextToken,
79 PossibleNonPrimary);
80
81 QualType Type = ConstraintExpression->getType();
82
83 auto CheckForNonPrimary = [&] {
84 if (PossibleNonPrimary)
85 *PossibleNonPrimary =
86 // We have the following case:
87 // template<typename> requires func(0) struct S { };
88 // The user probably isn't aware of the parentheses required around
89 // the function call, and we're only going to parse 'func' as the
90 // primary-expression, and complain that it is of non-bool type.
91 (NextToken.is(tok::l_paren) &&
92 (IsTrailingRequiresClause ||
93 (Type->isDependentType() &&
94 isa<UnresolvedLookupExpr>(ConstraintExpression)) ||
95 Type->isFunctionType() ||
96 Type->isSpecificBuiltinType(BuiltinType::Overload))) ||
97 // We have the following case:
98 // template<typename T> requires size_<T> == 0 struct S { };
99 // The user probably isn't aware of the parentheses required around
100 // the binary operator, and we're only going to parse 'func' as the
101 // first operand, and complain that it is of non-bool type.
102 getBinOpPrecedence(NextToken.getKind(),
103 /*GreaterThanIsOperator=*/true,
104 getLangOpts().CPlusPlus11) > prec::LogicalAnd;
105 };
106
107 // An atomic constraint!
108 if (ConstraintExpression->isTypeDependent()) {
109 CheckForNonPrimary();
110 return true;
111 }
112
113 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
114 Diag(ConstraintExpression->getExprLoc(),
115 diag::err_non_bool_atomic_constraint) << Type
116 << ConstraintExpression->getSourceRange();
117 CheckForNonPrimary();
118 return false;
119 }
120
121 if (PossibleNonPrimary)
122 *PossibleNonPrimary = false;
123 return true;
124}
125
126template <typename AtomicEvaluator>
127static bool
128calculateConstraintSatisfaction(Sema &S, const Expr *ConstraintExpr,
129 ConstraintSatisfaction &Satisfaction,
130 AtomicEvaluator &&Evaluator) {
131 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
132
133 if (LogicalBinOp BO = ConstraintExpr) {
134 if (calculateConstraintSatisfaction(S, BO.getLHS(), Satisfaction,
135 Evaluator))
136 return true;
137
138 bool IsLHSSatisfied = Satisfaction.IsSatisfied;
139
140 if (BO.isOr() && IsLHSSatisfied)
141 // [temp.constr.op] p3
142 // A disjunction is a constraint taking two operands. To determine if
143 // a disjunction is satisfied, the satisfaction of the first operand
144 // is checked. If that is satisfied, the disjunction is satisfied.
145 // Otherwise, the disjunction is satisfied if and only if the second
146 // operand is satisfied.
147 return false;
148
149 if (BO.isAnd() && !IsLHSSatisfied)
150 // [temp.constr.op] p2
151 // A conjunction is a constraint taking two operands. To determine if
152 // a conjunction is satisfied, the satisfaction of the first operand
153 // is checked. If that is not satisfied, the conjunction is not
154 // satisfied. Otherwise, the conjunction is satisfied if and only if
155 // the second operand is satisfied.
156 return false;
157
158 return calculateConstraintSatisfaction(
159 S, BO.getRHS(), Satisfaction, std::forward<AtomicEvaluator>(Evaluator));
160 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) {
161 return calculateConstraintSatisfaction(S, C->getSubExpr(), Satisfaction,
162 std::forward<AtomicEvaluator>(Evaluator));
163 }
164
165 // An atomic constraint expression
166 ExprResult SubstitutedAtomicExpr = Evaluator(ConstraintExpr);
167
168 if (SubstitutedAtomicExpr.isInvalid())
169 return true;
170
171 if (!SubstitutedAtomicExpr.isUsable())
172 // Evaluator has decided satisfaction without yielding an expression.
173 return false;
174
175 EnterExpressionEvaluationContext ConstantEvaluated(
176 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
177 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
178 Expr::EvalResult EvalResult;
179 EvalResult.Diag = &EvaluationDiags;
180 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult,
181 S.Context) ||
182 !EvaluationDiags.empty()) {
183 // C++2a [temp.constr.atomic]p1
184 // ...E shall be a constant expression of type bool.
185 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(),
186 diag::err_non_constant_constraint_expression)
187 << SubstitutedAtomicExpr.get()->getSourceRange();
188 for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
189 S.Diag(PDiag.first, PDiag.second);
190 return true;
191 }
192
193 assert(EvalResult.Val.isInt() &&(static_cast <bool> (EvalResult.Val.isInt() && "evaluating bool expression didn't produce int"
) ? void (0) : __assert_fail ("EvalResult.Val.isInt() && \"evaluating bool expression didn't produce int\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 194, __extension__ __PRETTY_FUNCTION__))
194 "evaluating bool expression didn't produce int")(static_cast <bool> (EvalResult.Val.isInt() && "evaluating bool expression didn't produce int"
) ? void (0) : __assert_fail ("EvalResult.Val.isInt() && \"evaluating bool expression didn't produce int\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 194, __extension__ __PRETTY_FUNCTION__))
;
195 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue();
196 if (!Satisfaction.IsSatisfied)
197 Satisfaction.Details.emplace_back(ConstraintExpr,
198 SubstitutedAtomicExpr.get());
199
200 return false;
201}
202
203static bool calculateConstraintSatisfaction(
204 Sema &S, const NamedDecl *Template, ArrayRef<TemplateArgument> TemplateArgs,
205 SourceLocation TemplateNameLoc, MultiLevelTemplateArgumentList &MLTAL,
206 const Expr *ConstraintExpr, ConstraintSatisfaction &Satisfaction) {
207 return calculateConstraintSatisfaction(
208 S, ConstraintExpr, Satisfaction, [&](const Expr *AtomicExpr) {
209 EnterExpressionEvaluationContext ConstantEvaluated(
210 S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
211
212 // Atomic constraint - substitute arguments and check satisfaction.
213 ExprResult SubstitutedExpression;
214 {
215 TemplateDeductionInfo Info(TemplateNameLoc);
216 Sema::InstantiatingTemplate Inst(S, AtomicExpr->getBeginLoc(),
217 Sema::InstantiatingTemplate::ConstraintSubstitution{},
218 const_cast<NamedDecl *>(Template), Info,
219 AtomicExpr->getSourceRange());
220 if (Inst.isInvalid())
221 return ExprError();
222 // We do not want error diagnostics escaping here.
223 Sema::SFINAETrap Trap(S);
224 SubstitutedExpression = S.SubstExpr(const_cast<Expr *>(AtomicExpr),
225 MLTAL);
226 // Substitution might have stripped off a contextual conversion to
227 // bool if this is the operand of an '&&' or '||'. For example, we
228 // might lose an lvalue-to-rvalue conversion here. If so, put it back
229 // before we try to evaluate.
230 if (!SubstitutedExpression.isInvalid())
231 SubstitutedExpression =
232 S.PerformContextuallyConvertToBool(SubstitutedExpression.get());
233 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) {
234 // C++2a [temp.constr.atomic]p1
235 // ...If substitution results in an invalid type or expression, the
236 // constraint is not satisfied.
237 if (!Trap.hasErrorOccurred())
238 // A non-SFINAE error has occured as a result of this
239 // substitution.
240 return ExprError();
241
242 PartialDiagnosticAt SubstDiag{SourceLocation(),
243 PartialDiagnostic::NullDiagnostic()};
244 Info.takeSFINAEDiagnostic(SubstDiag);
245 // FIXME: Concepts: This is an unfortunate consequence of there
246 // being no serialization code for PartialDiagnostics and the fact
247 // that serializing them would likely take a lot more storage than
248 // just storing them as strings. We would still like, in the
249 // future, to serialize the proper PartialDiagnostic as serializing
250 // it as a string defeats the purpose of the diagnostic mechanism.
251 SmallString<128> DiagString;
252 DiagString = ": ";
253 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString);
254 unsigned MessageSize = DiagString.size();
255 char *Mem = new (S.Context) char[MessageSize];
256 memcpy(Mem, DiagString.c_str(), MessageSize);
257 Satisfaction.Details.emplace_back(
258 AtomicExpr,
259 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{
260 SubstDiag.first, StringRef(Mem, MessageSize)});
261 Satisfaction.IsSatisfied = false;
262 return ExprEmpty();
263 }
264 }
265
266 if (!S.CheckConstraintExpression(SubstitutedExpression.get()))
267 return ExprError();
268
269 return SubstitutedExpression;
270 });
271}
272
273static bool CheckConstraintSatisfaction(Sema &S, const NamedDecl *Template,
274 ArrayRef<const Expr *> ConstraintExprs,
275 ArrayRef<TemplateArgument> TemplateArgs,
276 SourceRange TemplateIDRange,
277 ConstraintSatisfaction &Satisfaction) {
278 if (ConstraintExprs.empty()) {
279 Satisfaction.IsSatisfied = true;
280 return false;
281 }
282
283 for (auto& Arg : TemplateArgs)
284 if (Arg.isInstantiationDependent()) {
285 // No need to check satisfaction for dependent constraint expressions.
286 Satisfaction.IsSatisfied = true;
287 return false;
288 }
289
290 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(),
291 Sema::InstantiatingTemplate::ConstraintsCheck{},
292 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange);
293 if (Inst.isInvalid())
294 return true;
295
296 MultiLevelTemplateArgumentList MLTAL;
297 MLTAL.addOuterTemplateArguments(TemplateArgs);
298
299 for (const Expr *ConstraintExpr : ConstraintExprs) {
300 if (calculateConstraintSatisfaction(S, Template, TemplateArgs,
301 TemplateIDRange.getBegin(), MLTAL,
302 ConstraintExpr, Satisfaction))
303 return true;
304 if (!Satisfaction.IsSatisfied)
305 // [temp.constr.op] p2
306 // [...] To determine if a conjunction is satisfied, the satisfaction
307 // of the first operand is checked. If that is not satisfied, the
308 // conjunction is not satisfied. [...]
309 return false;
310 }
311 return false;
312}
313
314bool Sema::CheckConstraintSatisfaction(
315 const NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
316 ArrayRef<TemplateArgument> TemplateArgs, SourceRange TemplateIDRange,
317 ConstraintSatisfaction &OutSatisfaction) {
318 if (ConstraintExprs.empty()) {
319 OutSatisfaction.IsSatisfied = true;
320 return false;
321 }
322
323 llvm::FoldingSetNodeID ID;
324 void *InsertPos;
325 ConstraintSatisfaction *Satisfaction = nullptr;
326 bool ShouldCache = LangOpts.ConceptSatisfactionCaching && Template;
327 if (ShouldCache) {
328 ConstraintSatisfaction::Profile(ID, Context, Template, TemplateArgs);
329 Satisfaction = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos);
330 if (Satisfaction) {
331 OutSatisfaction = *Satisfaction;
332 return false;
333 }
334 Satisfaction = new ConstraintSatisfaction(Template, TemplateArgs);
335 } else {
336 Satisfaction = &OutSatisfaction;
337 }
338 if (::CheckConstraintSatisfaction(*this, Template, ConstraintExprs,
339 TemplateArgs, TemplateIDRange,
340 *Satisfaction)) {
341 if (ShouldCache)
342 delete Satisfaction;
343 return true;
344 }
345
346 if (ShouldCache) {
347 // We cannot use InsertNode here because CheckConstraintSatisfaction might
348 // have invalidated it.
349 SatisfactionCache.InsertNode(Satisfaction);
350 OutSatisfaction = *Satisfaction;
351 }
352 return false;
353}
354
355bool Sema::CheckConstraintSatisfaction(const Expr *ConstraintExpr,
356 ConstraintSatisfaction &Satisfaction) {
357 return calculateConstraintSatisfaction(
358 *this, ConstraintExpr, Satisfaction,
359 [](const Expr *AtomicExpr) -> ExprResult {
360 return ExprResult(const_cast<Expr *>(AtomicExpr));
361 });
362}
363
364bool Sema::CheckFunctionConstraints(const FunctionDecl *FD,
365 ConstraintSatisfaction &Satisfaction,
366 SourceLocation UsageLoc) {
367 const Expr *RC = FD->getTrailingRequiresClause();
368 if (RC->isInstantiationDependent()) {
369 Satisfaction.IsSatisfied = true;
370 return false;
371 }
372 Qualifiers ThisQuals;
373 CXXRecordDecl *Record = nullptr;
374 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) {
375 ThisQuals = Method->getMethodQualifiers();
376 Record = const_cast<CXXRecordDecl *>(Method->getParent());
377 }
378 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr);
379 // We substitute with empty arguments in order to rebuild the atomic
380 // constraint in a constant-evaluated context.
381 // FIXME: Should this be a dedicated TreeTransform?
382 return CheckConstraintSatisfaction(
383 FD, {RC}, /*TemplateArgs=*/{},
384 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()),
385 Satisfaction);
386}
387
388bool Sema::EnsureTemplateArgumentListConstraints(
389 TemplateDecl *TD, ArrayRef<TemplateArgument> TemplateArgs,
390 SourceRange TemplateIDRange) {
391 ConstraintSatisfaction Satisfaction;
392 llvm::SmallVector<const Expr *, 3> AssociatedConstraints;
393 TD->getAssociatedConstraints(AssociatedConstraints);
394 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgs,
395 TemplateIDRange, Satisfaction))
396 return true;
397
398 if (!Satisfaction.IsSatisfied) {
399 SmallString<128> TemplateArgString;
400 TemplateArgString = " ";
401 TemplateArgString += getTemplateArgumentBindingsText(
402 TD->getTemplateParameters(), TemplateArgs.data(), TemplateArgs.size());
403
404 Diag(TemplateIDRange.getBegin(),
405 diag::err_template_arg_list_constraints_not_satisfied)
406 << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD
407 << TemplateArgString << TemplateIDRange;
408 DiagnoseUnsatisfiedConstraint(Satisfaction);
409 return true;
410 }
411 return false;
412}
413
414static void diagnoseUnsatisfiedRequirement(Sema &S,
415 concepts::ExprRequirement *Req,
416 bool First) {
417 assert(!Req->isSatisfied()(static_cast <bool> (!Req->isSatisfied() && "Diagnose() can only be used on an unsatisfied requirement"
) ? void (0) : __assert_fail ("!Req->isSatisfied() && \"Diagnose() can only be used on an unsatisfied requirement\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 418, __extension__ __PRETTY_FUNCTION__))
418 && "Diagnose() can only be used on an unsatisfied requirement")(static_cast <bool> (!Req->isSatisfied() && "Diagnose() can only be used on an unsatisfied requirement"
) ? void (0) : __assert_fail ("!Req->isSatisfied() && \"Diagnose() can only be used on an unsatisfied requirement\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 418, __extension__ __PRETTY_FUNCTION__))
;
419 switch (Req->getSatisfactionStatus()) {
420 case concepts::ExprRequirement::SS_Dependent:
421 llvm_unreachable("Diagnosing a dependent requirement")::llvm::llvm_unreachable_internal("Diagnosing a dependent requirement"
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 421)
;
422 break;
423 case concepts::ExprRequirement::SS_ExprSubstitutionFailure: {
424 auto *SubstDiag = Req->getExprSubstitutionDiagnostic();
425 if (!SubstDiag->DiagMessage.empty())
426 S.Diag(SubstDiag->DiagLoc,
427 diag::note_expr_requirement_expr_substitution_error)
428 << (int)First << SubstDiag->SubstitutedEntity
429 << SubstDiag->DiagMessage;
430 else
431 S.Diag(SubstDiag->DiagLoc,
432 diag::note_expr_requirement_expr_unknown_substitution_error)
433 << (int)First << SubstDiag->SubstitutedEntity;
434 break;
435 }
436 case concepts::ExprRequirement::SS_NoexceptNotMet:
437 S.Diag(Req->getNoexceptLoc(),
438 diag::note_expr_requirement_noexcept_not_met)
439 << (int)First << Req->getExpr();
440 break;
441 case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: {
442 auto *SubstDiag =
443 Req->getReturnTypeRequirement().getSubstitutionDiagnostic();
444 if (!SubstDiag->DiagMessage.empty())
445 S.Diag(SubstDiag->DiagLoc,
446 diag::note_expr_requirement_type_requirement_substitution_error)
447 << (int)First << SubstDiag->SubstitutedEntity
448 << SubstDiag->DiagMessage;
449 else
450 S.Diag(SubstDiag->DiagLoc,
451 diag::note_expr_requirement_type_requirement_unknown_substitution_error)
452 << (int)First << SubstDiag->SubstitutedEntity;
453 break;
454 }
455 case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: {
456 ConceptSpecializationExpr *ConstraintExpr =
457 Req->getReturnTypeRequirementSubstitutedConstraintExpr();
458 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
459 // A simple case - expr type is the type being constrained and the concept
460 // was not provided arguments.
461 Expr *e = Req->getExpr();
462 S.Diag(e->getBeginLoc(),
463 diag::note_expr_requirement_constraints_not_satisfied_simple)
464 << (int)First << S.getDecltypeForParenthesizedExpr(e)
465 << ConstraintExpr->getNamedConcept();
466 } else {
467 S.Diag(ConstraintExpr->getBeginLoc(),
468 diag::note_expr_requirement_constraints_not_satisfied)
469 << (int)First << ConstraintExpr;
470 }
471 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction());
472 break;
473 }
474 case concepts::ExprRequirement::SS_Satisfied:
475 llvm_unreachable("We checked this above")::llvm::llvm_unreachable_internal("We checked this above", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 475)
;
476 }
477}
478
479static void diagnoseUnsatisfiedRequirement(Sema &S,
480 concepts::TypeRequirement *Req,
481 bool First) {
482 assert(!Req->isSatisfied()(static_cast <bool> (!Req->isSatisfied() && "Diagnose() can only be used on an unsatisfied requirement"
) ? void (0) : __assert_fail ("!Req->isSatisfied() && \"Diagnose() can only be used on an unsatisfied requirement\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 483, __extension__ __PRETTY_FUNCTION__))
483 && "Diagnose() can only be used on an unsatisfied requirement")(static_cast <bool> (!Req->isSatisfied() && "Diagnose() can only be used on an unsatisfied requirement"
) ? void (0) : __assert_fail ("!Req->isSatisfied() && \"Diagnose() can only be used on an unsatisfied requirement\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 483, __extension__ __PRETTY_FUNCTION__))
;
484 switch (Req->getSatisfactionStatus()) {
485 case concepts::TypeRequirement::SS_Dependent:
486 llvm_unreachable("Diagnosing a dependent requirement")::llvm::llvm_unreachable_internal("Diagnosing a dependent requirement"
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 486)
;
487 return;
488 case concepts::TypeRequirement::SS_SubstitutionFailure: {
489 auto *SubstDiag = Req->getSubstitutionDiagnostic();
490 if (!SubstDiag->DiagMessage.empty())
491 S.Diag(SubstDiag->DiagLoc,
492 diag::note_type_requirement_substitution_error) << (int)First
493 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage;
494 else
495 S.Diag(SubstDiag->DiagLoc,
496 diag::note_type_requirement_unknown_substitution_error)
497 << (int)First << SubstDiag->SubstitutedEntity;
498 return;
499 }
500 default:
501 llvm_unreachable("Unknown satisfaction status")::llvm::llvm_unreachable_internal("Unknown satisfaction status"
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 501)
;
502 return;
503 }
504}
505
506static void diagnoseUnsatisfiedRequirement(Sema &S,
507 concepts::NestedRequirement *Req,
508 bool First) {
509 if (Req->isSubstitutionFailure()) {
510 concepts::Requirement::SubstitutionDiagnostic *SubstDiag =
511 Req->getSubstitutionDiagnostic();
512 if (!SubstDiag->DiagMessage.empty())
513 S.Diag(SubstDiag->DiagLoc,
514 diag::note_nested_requirement_substitution_error)
515 << (int)First << SubstDiag->SubstitutedEntity
516 << SubstDiag->DiagMessage;
517 else
518 S.Diag(SubstDiag->DiagLoc,
519 diag::note_nested_requirement_unknown_substitution_error)
520 << (int)First << SubstDiag->SubstitutedEntity;
521 return;
522 }
523 S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First);
524}
525
526
527static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S,
528 Expr *SubstExpr,
529 bool First = true) {
530 SubstExpr = SubstExpr->IgnoreParenImpCasts();
531 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) {
532 switch (BO->getOpcode()) {
533 // These two cases will in practice only be reached when using fold
534 // expressions with || and &&, since otherwise the || and && will have been
535 // broken down into atomic constraints during satisfaction checking.
536 case BO_LOr:
537 // Or evaluated to false - meaning both RHS and LHS evaluated to false.
538 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
539 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
540 /*First=*/false);
541 return;
542 case BO_LAnd: {
543 bool LHSSatisfied =
544 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
545 if (LHSSatisfied) {
546 // LHS is true, so RHS must be false.
547 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First);
548 return;
549 }
550 // LHS is false
551 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First);
552
553 // RHS might also be false
554 bool RHSSatisfied =
555 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue();
556 if (!RHSSatisfied)
557 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(),
558 /*First=*/false);
559 return;
560 }
561 case BO_GE:
562 case BO_LE:
563 case BO_GT:
564 case BO_LT:
565 case BO_EQ:
566 case BO_NE:
567 if (BO->getLHS()->getType()->isIntegerType() &&
568 BO->getRHS()->getType()->isIntegerType()) {
569 Expr::EvalResult SimplifiedLHS;
570 Expr::EvalResult SimplifiedRHS;
571 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context,
572 Expr::SE_NoSideEffects,
573 /*InConstantContext=*/true);
574 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context,
575 Expr::SE_NoSideEffects,
576 /*InConstantContext=*/true);
577 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) {
578 S.Diag(SubstExpr->getBeginLoc(),
579 diag::note_atomic_constraint_evaluated_to_false_elaborated)
580 << (int)First << SubstExpr
581 << toString(SimplifiedLHS.Val.getInt(), 10)
582 << BinaryOperator::getOpcodeStr(BO->getOpcode())
583 << toString(SimplifiedRHS.Val.getInt(), 10);
584 return;
585 }
586 }
587 break;
588
589 default:
590 break;
591 }
592 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) {
593 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) {
594 S.Diag(
595 CSE->getSourceRange().getBegin(),
596 diag::
597 note_single_arg_concept_specialization_constraint_evaluated_to_false)
598 << (int)First
599 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument()
600 << CSE->getNamedConcept();
601 } else {
602 S.Diag(SubstExpr->getSourceRange().getBegin(),
603 diag::note_concept_specialization_constraint_evaluated_to_false)
604 << (int)First << CSE;
605 }
606 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction());
607 return;
608 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) {
609 for (concepts::Requirement *Req : RE->getRequirements())
610 if (!Req->isDependent() && !Req->isSatisfied()) {
611 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req))
612 diagnoseUnsatisfiedRequirement(S, E, First);
613 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req))
614 diagnoseUnsatisfiedRequirement(S, T, First);
615 else
616 diagnoseUnsatisfiedRequirement(
617 S, cast<concepts::NestedRequirement>(Req), First);
618 break;
619 }
620 return;
621 }
622
623 S.Diag(SubstExpr->getSourceRange().getBegin(),
624 diag::note_atomic_constraint_evaluated_to_false)
625 << (int)First << SubstExpr;
626}
627
628template<typename SubstitutionDiagnostic>
629static void diagnoseUnsatisfiedConstraintExpr(
630 Sema &S, const Expr *E,
631 const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record,
632 bool First = true) {
633 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()){
634 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed)
635 << Diag->second;
636 return;
637 }
638
639 diagnoseWellFormedUnsatisfiedConstraintExpr(S,
640 Record.template get<Expr *>(), First);
641}
642
643void
644Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction,
645 bool First) {
646 assert(!Satisfaction.IsSatisfied &&(static_cast <bool> (!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint") ? void (0) :
__assert_fail ("!Satisfaction.IsSatisfied && \"Attempted to diagnose a satisfied constraint\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 647, __extension__ __PRETTY_FUNCTION__))
647 "Attempted to diagnose a satisfied constraint")(static_cast <bool> (!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint") ? void (0) :
__assert_fail ("!Satisfaction.IsSatisfied && \"Attempted to diagnose a satisfied constraint\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 647, __extension__ __PRETTY_FUNCTION__))
;
648 for (auto &Pair : Satisfaction.Details) {
649 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
650 First = false;
651 }
652}
653
654void Sema::DiagnoseUnsatisfiedConstraint(
655 const ASTConstraintSatisfaction &Satisfaction,
656 bool First) {
657 assert(!Satisfaction.IsSatisfied &&(static_cast <bool> (!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint") ? void (0) :
__assert_fail ("!Satisfaction.IsSatisfied && \"Attempted to diagnose a satisfied constraint\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 658, __extension__ __PRETTY_FUNCTION__))
658 "Attempted to diagnose a satisfied constraint")(static_cast <bool> (!Satisfaction.IsSatisfied &&
"Attempted to diagnose a satisfied constraint") ? void (0) :
__assert_fail ("!Satisfaction.IsSatisfied && \"Attempted to diagnose a satisfied constraint\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 658, __extension__ __PRETTY_FUNCTION__))
;
659 for (auto &Pair : Satisfaction) {
660 diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First);
661 First = false;
662 }
663}
664
665const NormalizedConstraint *
666Sema::getNormalizedAssociatedConstraints(
667 NamedDecl *ConstrainedDecl, ArrayRef<const Expr *> AssociatedConstraints) {
668 auto CacheEntry = NormalizationCache.find(ConstrainedDecl);
669 if (CacheEntry == NormalizationCache.end()) {
670 auto Normalized =
671 NormalizedConstraint::fromConstraintExprs(*this, ConstrainedDecl,
672 AssociatedConstraints);
673 CacheEntry =
674 NormalizationCache
675 .try_emplace(ConstrainedDecl,
676 Normalized
677 ? new (Context) NormalizedConstraint(
678 std::move(*Normalized))
679 : nullptr)
680 .first;
681 }
682 return CacheEntry->second;
683}
684
685static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N,
686 ConceptDecl *Concept, ArrayRef<TemplateArgument> TemplateArgs,
687 const ASTTemplateArgumentListInfo *ArgsAsWritten) {
688 if (!N.isAtomic()) {
689 if (substituteParameterMappings(S, N.getLHS(), Concept, TemplateArgs,
690 ArgsAsWritten))
691 return true;
692 return substituteParameterMappings(S, N.getRHS(), Concept, TemplateArgs,
693 ArgsAsWritten);
694 }
695 TemplateParameterList *TemplateParams = Concept->getTemplateParameters();
696
697 AtomicConstraint &Atomic = *N.getAtomicConstraint();
698 TemplateArgumentListInfo SubstArgs;
699 MultiLevelTemplateArgumentList MLTAL;
700 MLTAL.addOuterTemplateArguments(TemplateArgs);
701 if (!Atomic.ParameterMapping) {
702 llvm::SmallBitVector OccurringIndices(TemplateParams->size());
703 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false,
704 /*Depth=*/0, OccurringIndices);
705 Atomic.ParameterMapping.emplace(
706 MutableArrayRef<TemplateArgumentLoc>(
707 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()],
708 OccurringIndices.count()));
709 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I)
710 if (OccurringIndices[I])
711 new (&(*Atomic.ParameterMapping)[J++]) TemplateArgumentLoc(
712 S.getIdentityTemplateArgumentLoc(TemplateParams->begin()[I],
713 // Here we assume we do not support things like
714 // template<typename A, typename B>
715 // concept C = ...;
716 //
717 // template<typename... Ts> requires C<Ts...>
718 // struct S { };
719 // The above currently yields a diagnostic.
720 // We still might have default arguments for concept parameters.
721 ArgsAsWritten->NumTemplateArgs > I ?
722 ArgsAsWritten->arguments()[I].getLocation() :
723 SourceLocation()));
724 }
725 Sema::InstantiatingTemplate Inst(
726 S, ArgsAsWritten->arguments().front().getSourceRange().getBegin(),
727 Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, Concept,
728 SourceRange(ArgsAsWritten->arguments()[0].getSourceRange().getBegin(),
729 ArgsAsWritten->arguments().back().getSourceRange().getEnd()));
730 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs))
731 return true;
732 Atomic.ParameterMapping.emplace(
733 MutableArrayRef<TemplateArgumentLoc>(
734 new (S.Context) TemplateArgumentLoc[SubstArgs.size()],
735 SubstArgs.size()));
736 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(),
737 N.getAtomicConstraint()->ParameterMapping->begin());
738 return false;
739}
740
741Optional<NormalizedConstraint>
742NormalizedConstraint::fromConstraintExprs(Sema &S, NamedDecl *D,
743 ArrayRef<const Expr *> E) {
744 assert(E.size() != 0)(static_cast <bool> (E.size() != 0) ? void (0) : __assert_fail
("E.size() != 0", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 744, __extension__ __PRETTY_FUNCTION__))
;
745 auto First = fromConstraintExpr(S, D, E[0]);
746 if (E.size() == 1)
747 return First;
748 auto Second = fromConstraintExpr(S, D, E[1]);
749 if (!Second)
750 return None;
751 llvm::Optional<NormalizedConstraint> Conjunction;
752 Conjunction.emplace(S.Context, std::move(*First), std::move(*Second),
753 CCK_Conjunction);
754 for (unsigned I = 2; I < E.size(); ++I) {
755 auto Next = fromConstraintExpr(S, D, E[I]);
756 if (!Next)
757 return llvm::Optional<NormalizedConstraint>{};
758 NormalizedConstraint NewConjunction(S.Context, std::move(*Conjunction),
759 std::move(*Next), CCK_Conjunction);
760 *Conjunction = std::move(NewConjunction);
761 }
762 return Conjunction;
763}
764
765llvm::Optional<NormalizedConstraint>
766NormalizedConstraint::fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E) {
767 assert(E != nullptr)(static_cast <bool> (E != nullptr) ? void (0) : __assert_fail
("E != nullptr", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 767, __extension__ __PRETTY_FUNCTION__))
;
768
769 // C++ [temp.constr.normal]p1.1
770 // [...]
771 // - The normal form of an expression (E) is the normal form of E.
772 // [...]
773 E = E->IgnoreParenImpCasts();
774 if (LogicalBinOp BO = E) {
775 auto LHS = fromConstraintExpr(S, D, BO.getLHS());
776 if (!LHS)
777 return None;
778 auto RHS = fromConstraintExpr(S, D, BO.getRHS());
779 if (!RHS)
780 return None;
781
782 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS),
783 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction);
784 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) {
785 const NormalizedConstraint *SubNF;
786 {
787 Sema::InstantiatingTemplate Inst(
788 S, CSE->getExprLoc(),
789 Sema::InstantiatingTemplate::ConstraintNormalization{}, D,
790 CSE->getSourceRange());
791 // C++ [temp.constr.normal]p1.1
792 // [...]
793 // The normal form of an id-expression of the form C<A1, A2, ..., AN>,
794 // where C names a concept, is the normal form of the
795 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s
796 // respective template parameters in the parameter mappings in each atomic
797 // constraint. If any such substitution results in an invalid type or
798 // expression, the program is ill-formed; no diagnostic is required.
799 // [...]
800 ConceptDecl *CD = CSE->getNamedConcept();
801 SubNF = S.getNormalizedAssociatedConstraints(CD,
802 {CD->getConstraintExpr()});
803 if (!SubNF)
804 return None;
805 }
806
807 Optional<NormalizedConstraint> New;
808 New.emplace(S.Context, *SubNF);
809
810 if (substituteParameterMappings(
811 S, *New, CSE->getNamedConcept(),
812 CSE->getTemplateArguments(), CSE->getTemplateArgsAsWritten()))
813 return None;
814
815 return New;
816 }
817 return NormalizedConstraint{new (S.Context) AtomicConstraint(S, E)};
818}
819
820using NormalForm =
821 llvm::SmallVector<llvm::SmallVector<AtomicConstraint *, 2>, 4>;
822
823static NormalForm makeCNF(const NormalizedConstraint &Normalized) {
824 if (Normalized.isAtomic())
825 return {{Normalized.getAtomicConstraint()}};
826
827 NormalForm LCNF = makeCNF(Normalized.getLHS());
828 NormalForm RCNF = makeCNF(Normalized.getRHS());
829 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Conjunction) {
830 LCNF.reserve(LCNF.size() + RCNF.size());
831 while (!RCNF.empty())
832 LCNF.push_back(RCNF.pop_back_val());
833 return LCNF;
834 }
835
836 // Disjunction
837 NormalForm Res;
838 Res.reserve(LCNF.size() * RCNF.size());
839 for (auto &LDisjunction : LCNF)
840 for (auto &RDisjunction : RCNF) {
841 NormalForm::value_type Combined;
842 Combined.reserve(LDisjunction.size() + RDisjunction.size());
843 std::copy(LDisjunction.begin(), LDisjunction.end(),
844 std::back_inserter(Combined));
845 std::copy(RDisjunction.begin(), RDisjunction.end(),
846 std::back_inserter(Combined));
847 Res.emplace_back(Combined);
848 }
849 return Res;
850}
851
852static NormalForm makeDNF(const NormalizedConstraint &Normalized) {
853 if (Normalized.isAtomic())
854 return {{Normalized.getAtomicConstraint()}};
855
856 NormalForm LDNF = makeDNF(Normalized.getLHS());
857 NormalForm RDNF = makeDNF(Normalized.getRHS());
858 if (Normalized.getCompoundKind() == NormalizedConstraint::CCK_Disjunction) {
859 LDNF.reserve(LDNF.size() + RDNF.size());
860 while (!RDNF.empty())
861 LDNF.push_back(RDNF.pop_back_val());
862 return LDNF;
863 }
864
865 // Conjunction
866 NormalForm Res;
867 Res.reserve(LDNF.size() * RDNF.size());
868 for (auto &LConjunction : LDNF) {
869 for (auto &RConjunction : RDNF) {
870 NormalForm::value_type Combined;
871 Combined.reserve(LConjunction.size() + RConjunction.size());
872 std::copy(LConjunction.begin(), LConjunction.end(),
873 std::back_inserter(Combined));
874 std::copy(RConjunction.begin(), RConjunction.end(),
875 std::back_inserter(Combined));
876 Res.emplace_back(Combined);
877 }
878 }
879 return Res;
880}
881
882template<typename AtomicSubsumptionEvaluator>
883static bool subsumes(NormalForm PDNF, NormalForm QCNF,
884 AtomicSubsumptionEvaluator E) {
885 // C++ [temp.constr.order] p2
886 // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
887 // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
888 // the conjuctive normal form of Q, where [...]
889 for (const auto &Pi : PDNF) {
890 for (const auto &Qj : QCNF) {
891 // C++ [temp.constr.order] p2
892 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
893 // and only if there exists an atomic constraint Pia in Pi for which
894 // there exists an atomic constraint, Qjb, in Qj such that Pia
895 // subsumes Qjb.
896 bool Found = false;
897 for (const AtomicConstraint *Pia : Pi) {
898 for (const AtomicConstraint *Qjb : Qj) {
899 if (E(*Pia, *Qjb)) {
900 Found = true;
901 break;
902 }
903 }
904 if (Found)
905 break;
906 }
907 if (!Found)
908 return false;
909 }
910 }
911 return true;
912}
913
914template<typename AtomicSubsumptionEvaluator>
915static bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P,
916 NamedDecl *DQ, ArrayRef<const Expr *> Q, bool &Subsumes,
917 AtomicSubsumptionEvaluator E) {
918 // C++ [temp.constr.order] p2
919 // In order to determine if a constraint P subsumes a constraint Q, P is
920 // transformed into disjunctive normal form, and Q is transformed into
921 // conjunctive normal form. [...]
922 auto *PNormalized = S.getNormalizedAssociatedConstraints(DP, P);
923 if (!PNormalized)
924 return true;
925 const NormalForm PDNF = makeDNF(*PNormalized);
926
927 auto *QNormalized = S.getNormalizedAssociatedConstraints(DQ, Q);
928 if (!QNormalized)
929 return true;
930 const NormalForm QCNF = makeCNF(*QNormalized);
931
932 Subsumes = subsumes(PDNF, QCNF, E);
933 return false;
934}
935
936bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, ArrayRef<const Expr *> AC1,
937 NamedDecl *D2, ArrayRef<const Expr *> AC2,
938 bool &Result) {
939 if (AC1.empty()) {
940 Result = AC2.empty();
941 return false;
942 }
943 if (AC2.empty()) {
944 // TD1 has associated constraints and TD2 does not.
945 Result = true;
946 return false;
947 }
948
949 std::pair<NamedDecl *, NamedDecl *> Key{D1, D2};
950 auto CacheEntry = SubsumptionCache.find(Key);
951 if (CacheEntry != SubsumptionCache.end()) {
952 Result = CacheEntry->second;
953 return false;
954 }
955
956 if (subsumes(*this, D1, AC1, D2, AC2, Result,
957 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
958 return A.subsumes(Context, B);
959 }))
960 return true;
961 SubsumptionCache.try_emplace(Key, Result);
962 return false;
963}
964
965bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1,
966 ArrayRef<const Expr *> AC1, NamedDecl *D2, ArrayRef<const Expr *> AC2) {
967 if (isSFINAEContext())
968 // No need to work here because our notes would be discarded.
969 return false;
970
971 if (AC1.empty() || AC2.empty())
972 return false;
973
974 auto NormalExprEvaluator =
975 [this] (const AtomicConstraint &A, const AtomicConstraint &B) {
976 return A.subsumes(Context, B);
977 };
978
979 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr;
980 auto IdenticalExprEvaluator =
981 [&] (const AtomicConstraint &A, const AtomicConstraint &B) {
982 if (!A.hasMatchingParameterMapping(Context, B))
983 return false;
984 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr;
985 if (EA == EB)
986 return true;
987
988 // Not the same source level expression - are the expressions
989 // identical?
990 llvm::FoldingSetNodeID IDA, IDB;
991 EA->Profile(IDA, Context, /*Cannonical=*/true);
992 EB->Profile(IDB, Context, /*Cannonical=*/true);
993 if (IDA != IDB)
994 return false;
995
996 AmbiguousAtomic1 = EA;
997 AmbiguousAtomic2 = EB;
998 return true;
999 };
1000
1001 {
1002 // The subsumption checks might cause diagnostics
1003 SFINAETrap Trap(*this);
1004 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1);
1005 if (!Normalized1)
1006 return false;
1007 const NormalForm DNF1 = makeDNF(*Normalized1);
1008 const NormalForm CNF1 = makeCNF(*Normalized1);
1009
1010 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2);
1011 if (!Normalized2)
1012 return false;
1013 const NormalForm DNF2 = makeDNF(*Normalized2);
1014 const NormalForm CNF2 = makeCNF(*Normalized2);
1015
1016 bool Is1AtLeastAs2Normally = subsumes(DNF1, CNF2, NormalExprEvaluator);
1017 bool Is2AtLeastAs1Normally = subsumes(DNF2, CNF1, NormalExprEvaluator);
1018 bool Is1AtLeastAs2 = subsumes(DNF1, CNF2, IdenticalExprEvaluator);
1019 bool Is2AtLeastAs1 = subsumes(DNF2, CNF1, IdenticalExprEvaluator);
1020 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally &&
1021 Is2AtLeastAs1 == Is2AtLeastAs1Normally)
1022 // Same result - no ambiguity was caused by identical atomic expressions.
1023 return false;
1024 }
1025
1026 // A different result! Some ambiguous atomic constraint(s) caused a difference
1027 assert(AmbiguousAtomic1 && AmbiguousAtomic2)(static_cast <bool> (AmbiguousAtomic1 && AmbiguousAtomic2
) ? void (0) : __assert_fail ("AmbiguousAtomic1 && AmbiguousAtomic2"
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1027, __extension__ __PRETTY_FUNCTION__))
;
1028
1029 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints)
1030 << AmbiguousAtomic1->getSourceRange();
1031 Diag(AmbiguousAtomic2->getBeginLoc(),
1032 diag::note_ambiguous_atomic_constraints_similar_expression)
1033 << AmbiguousAtomic2->getSourceRange();
1034 return true;
1035}
1036
1037concepts::ExprRequirement::ExprRequirement(
1038 Expr *E, bool IsSimple, SourceLocation NoexceptLoc,
1039 ReturnTypeRequirement Req, SatisfactionStatus Status,
1040 ConceptSpecializationExpr *SubstitutedConstraintExpr) :
1041 Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,
1042 Status == SS_Dependent &&
1043 (E->containsUnexpandedParameterPack() ||
1044 Req.containsUnexpandedParameterPack()),
1045 Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc),
1046 TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr),
1047 Status(Status) {
1048 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&(static_cast <bool> ((!IsSimple || (Req.isEmpty() &&
NoexceptLoc.isInvalid())) && "Simple requirement must not have a return type requirement or a "
"noexcept specification") ? void (0) : __assert_fail ("(!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && \"Simple requirement must not have a return type requirement or a \" \"noexcept specification\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1050, __extension__ __PRETTY_FUNCTION__))
1049 "Simple requirement must not have a return type requirement or a "(static_cast <bool> ((!IsSimple || (Req.isEmpty() &&
NoexceptLoc.isInvalid())) && "Simple requirement must not have a return type requirement or a "
"noexcept specification") ? void (0) : __assert_fail ("(!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && \"Simple requirement must not have a return type requirement or a \" \"noexcept specification\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1050, __extension__ __PRETTY_FUNCTION__))
1050 "noexcept specification")(static_cast <bool> ((!IsSimple || (Req.isEmpty() &&
NoexceptLoc.isInvalid())) && "Simple requirement must not have a return type requirement or a "
"noexcept specification") ? void (0) : __assert_fail ("(!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && \"Simple requirement must not have a return type requirement or a \" \"noexcept specification\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1050, __extension__ __PRETTY_FUNCTION__))
;
1051 assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) ==(static_cast <bool> ((Status > SS_TypeRequirementSubstitutionFailure
&& Req.isTypeConstraint()) == (SubstitutedConstraintExpr
!= nullptr)) ? void (0) : __assert_fail ("(Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == (SubstitutedConstraintExpr != nullptr)"
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1052, __extension__ __PRETTY_FUNCTION__))
1052 (SubstitutedConstraintExpr != nullptr))(static_cast <bool> ((Status > SS_TypeRequirementSubstitutionFailure
&& Req.isTypeConstraint()) == (SubstitutedConstraintExpr
!= nullptr)) ? void (0) : __assert_fail ("(Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == (SubstitutedConstraintExpr != nullptr)"
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1052, __extension__ __PRETTY_FUNCTION__))
;
1053}
1054
1055concepts::ExprRequirement::ExprRequirement(
1056 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,
1057 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) :
1058 Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),
1059 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),
1060 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),
1061 Status(SS_ExprSubstitutionFailure) {
1062 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&(static_cast <bool> ((!IsSimple || (Req.isEmpty() &&
NoexceptLoc.isInvalid())) && "Simple requirement must not have a return type requirement or a "
"noexcept specification") ? void (0) : __assert_fail ("(!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && \"Simple requirement must not have a return type requirement or a \" \"noexcept specification\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1064, __extension__ __PRETTY_FUNCTION__))
1063 "Simple requirement must not have a return type requirement or a "(static_cast <bool> ((!IsSimple || (Req.isEmpty() &&
NoexceptLoc.isInvalid())) && "Simple requirement must not have a return type requirement or a "
"noexcept specification") ? void (0) : __assert_fail ("(!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && \"Simple requirement must not have a return type requirement or a \" \"noexcept specification\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1064, __extension__ __PRETTY_FUNCTION__))
1064 "noexcept specification")(static_cast <bool> ((!IsSimple || (Req.isEmpty() &&
NoexceptLoc.isInvalid())) && "Simple requirement must not have a return type requirement or a "
"noexcept specification") ? void (0) : __assert_fail ("(!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && \"Simple requirement must not have a return type requirement or a \" \"noexcept specification\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1064, __extension__ __PRETTY_FUNCTION__))
;
1065}
1066
1067concepts::ExprRequirement::ReturnTypeRequirement::
1068ReturnTypeRequirement(TemplateParameterList *TPL) :
1069 TypeConstraintInfo(TPL, 0) {
1070 assert(TPL->size() == 1)(static_cast <bool> (TPL->size() == 1) ? void (0) : __assert_fail
("TPL->size() == 1", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1070, __extension__ __PRETTY_FUNCTION__))
;
1
Assuming the condition is true
2
'?' condition is true
1071 const TypeConstraint *TC =
1072 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();
3
The object is a 'TemplateTypeParmDecl'
1073 assert(TC &&(static_cast <bool> (TC && "TPL must have a template type parameter with a type constraint"
) ? void (0) : __assert_fail ("TC && \"TPL must have a template type parameter with a type constraint\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1074, __extension__ __PRETTY_FUNCTION__))
4
'?' condition is true
1074 "TPL must have a template type parameter with a type constraint")(static_cast <bool> (TC && "TPL must have a template type parameter with a type constraint"
) ? void (0) : __assert_fail ("TC && \"TPL must have a template type parameter with a type constraint\""
, "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/clang/lib/Sema/SemaConcept.cpp"
, 1074, __extension__ __PRETTY_FUNCTION__))
;
1075 auto *Constraint =
6
'Constraint' initialized to a null pointer value
1076 cast_or_null<ConceptSpecializationExpr>(
5
Assuming null pointer is passed into cast
1077 TC->getImmediatelyDeclaredConstraint());
1078 bool Dependent =
1079 Constraint->getTemplateArgsAsWritten() &&
7
Called C++ object pointer is null
1080 TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
1081 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));
1082 TypeConstraintInfo.setInt(Dependent ? 1 : 0);
1083}
1084
1085concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) :
1086 Requirement(RK_Type, T->getType()->isInstantiationDependentType(),
1087 T->getType()->containsUnexpandedParameterPack(),
1088 // We reach this ctor with either dependent types (in which
1089 // IsSatisfied doesn't matter) or with non-dependent type in
1090 // which the existence of the type indicates satisfaction.
1091 /*IsSatisfied=*/true),
1092 Value(T),
1093 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent
1094 : SS_Satisfied) {}