1 //===-- SemaConcept.cpp - Semantic Analysis for Constraints and Concepts --===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements semantic analysis for C++ constraints and concepts. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/Sema/SemaConcept.h" 14 #include "TreeTransform.h" 15 #include "clang/AST/ASTLambda.h" 16 #include "clang/AST/DeclCXX.h" 17 #include "clang/AST/ExprConcepts.h" 18 #include "clang/Basic/OperatorPrecedence.h" 19 #include "clang/Sema/EnterExpressionEvaluationContext.h" 20 #include "clang/Sema/Initialization.h" 21 #include "clang/Sema/Overload.h" 22 #include "clang/Sema/ScopeInfo.h" 23 #include "clang/Sema/Sema.h" 24 #include "clang/Sema/SemaInternal.h" 25 #include "clang/Sema/Template.h" 26 #include "clang/Sema/TemplateDeduction.h" 27 #include "llvm/ADT/DenseMap.h" 28 #include "llvm/ADT/PointerUnion.h" 29 #include "llvm/ADT/StringExtras.h" 30 #include <optional> 31 32 using namespace clang; 33 using namespace sema; 34 35 namespace { 36 class LogicalBinOp { 37 SourceLocation Loc; 38 OverloadedOperatorKind Op = OO_None; 39 const Expr *LHS = nullptr; 40 const Expr *RHS = nullptr; 41 42 public: 43 LogicalBinOp(const Expr *E) { 44 if (auto *BO = dyn_cast<BinaryOperator>(E)) { 45 Op = BinaryOperator::getOverloadedOperator(BO->getOpcode()); 46 LHS = BO->getLHS(); 47 RHS = BO->getRHS(); 48 Loc = BO->getExprLoc(); 49 } else if (auto *OO = dyn_cast<CXXOperatorCallExpr>(E)) { 50 // If OO is not || or && it might not have exactly 2 arguments. 51 if (OO->getNumArgs() == 2) { 52 Op = OO->getOperator(); 53 LHS = OO->getArg(0); 54 RHS = OO->getArg(1); 55 Loc = OO->getOperatorLoc(); 56 } 57 } 58 } 59 60 bool isAnd() const { return Op == OO_AmpAmp; } 61 bool isOr() const { return Op == OO_PipePipe; } 62 explicit operator bool() const { return isAnd() || isOr(); } 63 64 const Expr *getLHS() const { return LHS; } 65 const Expr *getRHS() const { return RHS; } 66 OverloadedOperatorKind getOp() const { return Op; } 67 68 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS) const { 69 return recreateBinOp(SemaRef, LHS, const_cast<Expr *>(getRHS())); 70 } 71 72 ExprResult recreateBinOp(Sema &SemaRef, ExprResult LHS, 73 ExprResult RHS) const { 74 assert((isAnd() || isOr()) && "Not the right kind of op?"); 75 assert((!LHS.isInvalid() && !RHS.isInvalid()) && "not good expressions?"); 76 77 if (!LHS.isUsable() || !RHS.isUsable()) 78 return ExprEmpty(); 79 80 // We should just be able to 'normalize' these to the builtin Binary 81 // Operator, since that is how they are evaluated in constriant checks. 82 return BinaryOperator::Create(SemaRef.Context, LHS.get(), RHS.get(), 83 BinaryOperator::getOverloadedOpcode(Op), 84 SemaRef.Context.BoolTy, VK_PRValue, 85 OK_Ordinary, Loc, FPOptionsOverride{}); 86 } 87 }; 88 } 89 90 bool Sema::CheckConstraintExpression(const Expr *ConstraintExpression, 91 Token NextToken, bool *PossibleNonPrimary, 92 bool IsTrailingRequiresClause) { 93 // C++2a [temp.constr.atomic]p1 94 // ..E shall be a constant expression of type bool. 95 96 ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts(); 97 98 if (LogicalBinOp BO = ConstraintExpression) { 99 return CheckConstraintExpression(BO.getLHS(), NextToken, 100 PossibleNonPrimary) && 101 CheckConstraintExpression(BO.getRHS(), NextToken, 102 PossibleNonPrimary); 103 } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression)) 104 return CheckConstraintExpression(C->getSubExpr(), NextToken, 105 PossibleNonPrimary); 106 107 QualType Type = ConstraintExpression->getType(); 108 109 auto CheckForNonPrimary = [&] { 110 if (!PossibleNonPrimary) 111 return; 112 113 *PossibleNonPrimary = 114 // We have the following case: 115 // template<typename> requires func(0) struct S { }; 116 // The user probably isn't aware of the parentheses required around 117 // the function call, and we're only going to parse 'func' as the 118 // primary-expression, and complain that it is of non-bool type. 119 // 120 // However, if we're in a lambda, this might also be: 121 // []<typename> requires var () {}; 122 // Which also looks like a function call due to the lambda parentheses, 123 // but unlike the first case, isn't an error, so this check is skipped. 124 (NextToken.is(tok::l_paren) && 125 (IsTrailingRequiresClause || 126 (Type->isDependentType() && 127 isa<UnresolvedLookupExpr>(ConstraintExpression) && 128 !dyn_cast_if_present<LambdaScopeInfo>(getCurFunction())) || 129 Type->isFunctionType() || 130 Type->isSpecificBuiltinType(BuiltinType::Overload))) || 131 // We have the following case: 132 // template<typename T> requires size_<T> == 0 struct S { }; 133 // The user probably isn't aware of the parentheses required around 134 // the binary operator, and we're only going to parse 'func' as the 135 // first operand, and complain that it is of non-bool type. 136 getBinOpPrecedence(NextToken.getKind(), 137 /*GreaterThanIsOperator=*/true, 138 getLangOpts().CPlusPlus11) > prec::LogicalAnd; 139 }; 140 141 // An atomic constraint! 142 if (ConstraintExpression->isTypeDependent()) { 143 CheckForNonPrimary(); 144 return true; 145 } 146 147 if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) { 148 Diag(ConstraintExpression->getExprLoc(), 149 diag::err_non_bool_atomic_constraint) << Type 150 << ConstraintExpression->getSourceRange(); 151 CheckForNonPrimary(); 152 return false; 153 } 154 155 if (PossibleNonPrimary) 156 *PossibleNonPrimary = false; 157 return true; 158 } 159 160 namespace { 161 struct SatisfactionStackRAII { 162 Sema &SemaRef; 163 bool Inserted = false; 164 SatisfactionStackRAII(Sema &SemaRef, const NamedDecl *ND, 165 const llvm::FoldingSetNodeID &FSNID) 166 : SemaRef(SemaRef) { 167 if (ND) { 168 SemaRef.PushSatisfactionStackEntry(ND, FSNID); 169 Inserted = true; 170 } 171 } 172 ~SatisfactionStackRAII() { 173 if (Inserted) 174 SemaRef.PopSatisfactionStackEntry(); 175 } 176 }; 177 } // namespace 178 179 static bool 180 DiagRecursiveConstraintEval(Sema &S, llvm::FoldingSetNodeID &ID, 181 const NamedDecl *Templ, const Expr *E, 182 const MultiLevelTemplateArgumentList &MLTAL) { 183 E->Profile(ID, S.Context, /*Canonical=*/true); 184 for (const auto &List : MLTAL) 185 for (const auto &TemplateArg : List.Args) 186 TemplateArg.Profile(ID, S.Context); 187 188 // Note that we have to do this with our own collection, because there are 189 // times where a constraint-expression check can cause us to need to evaluate 190 // other constriants that are unrelated, such as when evaluating a recovery 191 // expression, or when trying to determine the constexpr-ness of special 192 // members. Otherwise we could just use the 193 // Sema::InstantiatingTemplate::isAlreadyBeingInstantiated function. 194 if (S.SatisfactionStackContains(Templ, ID)) { 195 S.Diag(E->getExprLoc(), diag::err_constraint_depends_on_self) 196 << const_cast<Expr *>(E) << E->getSourceRange(); 197 return true; 198 } 199 200 return false; 201 } 202 203 static ExprResult EvaluateAtomicConstraint( 204 Sema &S, const Expr *AtomicExpr, const NamedDecl *Template, 205 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, 206 ConstraintSatisfaction &Satisfaction) { 207 EnterExpressionEvaluationContext ConstantEvaluated( 208 S, Sema::ExpressionEvaluationContext::ConstantEvaluated, 209 Sema::ReuseLambdaContextDecl); 210 211 // Atomic constraint - substitute arguments and check satisfaction. 212 ExprResult SubstitutedExpression; 213 { 214 TemplateDeductionInfo Info(TemplateNameLoc); 215 Sema::InstantiatingTemplate Inst( 216 S, AtomicExpr->getBeginLoc(), 217 Sema::InstantiatingTemplate::ConstraintSubstitution{}, 218 // FIXME: improve const-correctness of InstantiatingTemplate 219 const_cast<NamedDecl *>(Template), Info, AtomicExpr->getSourceRange()); 220 if (Inst.isInvalid()) 221 return ExprError(); 222 223 llvm::FoldingSetNodeID ID; 224 if (Template && 225 DiagRecursiveConstraintEval(S, ID, Template, AtomicExpr, MLTAL)) { 226 Satisfaction.IsSatisfied = false; 227 Satisfaction.ContainsErrors = true; 228 return ExprEmpty(); 229 } 230 231 SatisfactionStackRAII StackRAII(S, Template, ID); 232 233 // We do not want error diagnostics escaping here. 234 Sema::SFINAETrap Trap(S); 235 SubstitutedExpression = 236 S.SubstConstraintExpr(const_cast<Expr *>(AtomicExpr), MLTAL); 237 238 if (SubstitutedExpression.isInvalid() || Trap.hasErrorOccurred()) { 239 // C++2a [temp.constr.atomic]p1 240 // ...If substitution results in an invalid type or expression, the 241 // constraint is not satisfied. 242 if (!Trap.hasErrorOccurred()) 243 // A non-SFINAE error has occurred as a result of this 244 // substitution. 245 return ExprError(); 246 247 PartialDiagnosticAt SubstDiag{SourceLocation(), 248 PartialDiagnostic::NullDiagnostic()}; 249 Info.takeSFINAEDiagnostic(SubstDiag); 250 // FIXME: Concepts: This is an unfortunate consequence of there 251 // being no serialization code for PartialDiagnostics and the fact 252 // that serializing them would likely take a lot more storage than 253 // just storing them as strings. We would still like, in the 254 // future, to serialize the proper PartialDiagnostic as serializing 255 // it as a string defeats the purpose of the diagnostic mechanism. 256 SmallString<128> DiagString; 257 DiagString = ": "; 258 SubstDiag.second.EmitToString(S.getDiagnostics(), DiagString); 259 unsigned MessageSize = DiagString.size(); 260 char *Mem = new (S.Context) char[MessageSize]; 261 memcpy(Mem, DiagString.c_str(), MessageSize); 262 Satisfaction.Details.emplace_back( 263 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 264 SubstDiag.first, StringRef(Mem, MessageSize)}); 265 Satisfaction.IsSatisfied = false; 266 return ExprEmpty(); 267 } 268 } 269 270 if (!S.CheckConstraintExpression(SubstitutedExpression.get())) 271 return ExprError(); 272 273 // [temp.constr.atomic]p3: To determine if an atomic constraint is 274 // satisfied, the parameter mapping and template arguments are first 275 // substituted into its expression. If substitution results in an 276 // invalid type or expression, the constraint is not satisfied. 277 // Otherwise, the lvalue-to-rvalue conversion is performed if necessary, 278 // and E shall be a constant expression of type bool. 279 // 280 // Perform the L to R Value conversion if necessary. We do so for all 281 // non-PRValue categories, else we fail to extend the lifetime of 282 // temporaries, and that fails the constant expression check. 283 if (!SubstitutedExpression.get()->isPRValue()) 284 SubstitutedExpression = ImplicitCastExpr::Create( 285 S.Context, SubstitutedExpression.get()->getType(), CK_LValueToRValue, 286 SubstitutedExpression.get(), 287 /*BasePath=*/nullptr, VK_PRValue, FPOptionsOverride()); 288 289 return SubstitutedExpression; 290 } 291 292 static UnsignedOrNone EvaluateFoldExpandedConstraintSize( 293 Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template, 294 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, 295 ConstraintSatisfaction &Satisfaction) { 296 297 // We should ignore errors in the presence of packs of different size. 298 Sema::SFINAETrap Trap(S); 299 300 Expr *Pattern = FE->getPattern(); 301 302 SmallVector<UnexpandedParameterPack, 2> Unexpanded; 303 S.collectUnexpandedParameterPacks(Pattern, Unexpanded); 304 assert(!Unexpanded.empty() && "Pack expansion without parameter packs?"); 305 bool Expand = true; 306 bool RetainExpansion = false; 307 UnsignedOrNone NumExpansions = FE->getNumExpansions(); 308 if (S.CheckParameterPacksForExpansion( 309 FE->getEllipsisLoc(), Pattern->getSourceRange(), Unexpanded, MLTAL, 310 Expand, RetainExpansion, NumExpansions) || 311 !Expand || RetainExpansion) 312 return std::nullopt; 313 314 if (NumExpansions && S.getLangOpts().BracketDepth < *NumExpansions) { 315 S.Diag(FE->getEllipsisLoc(), 316 clang::diag::err_fold_expression_limit_exceeded) 317 << *NumExpansions << S.getLangOpts().BracketDepth 318 << FE->getSourceRange(); 319 S.Diag(FE->getEllipsisLoc(), diag::note_bracket_depth); 320 return std::nullopt; 321 } 322 return NumExpansions; 323 } 324 325 static ExprResult calculateConstraintSatisfaction( 326 Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template, 327 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, 328 ConstraintSatisfaction &Satisfaction); 329 330 static ExprResult calculateConstraintSatisfaction( 331 Sema &S, const Expr *LHS, OverloadedOperatorKind Op, const Expr *RHS, 332 const NamedDecl *Template, SourceLocation TemplateNameLoc, 333 const MultiLevelTemplateArgumentList &MLTAL, 334 ConstraintSatisfaction &Satisfaction) { 335 size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 336 337 ExprResult LHSRes = calculateConstraintSatisfaction( 338 S, LHS, Template, TemplateNameLoc, MLTAL, Satisfaction); 339 340 if (LHSRes.isInvalid()) 341 return ExprError(); 342 343 bool IsLHSSatisfied = Satisfaction.IsSatisfied; 344 345 if (Op == clang::OO_PipePipe && IsLHSSatisfied) 346 // [temp.constr.op] p3 347 // A disjunction is a constraint taking two operands. To determine if 348 // a disjunction is satisfied, the satisfaction of the first operand 349 // is checked. If that is satisfied, the disjunction is satisfied. 350 // Otherwise, the disjunction is satisfied if and only if the second 351 // operand is satisfied. 352 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 353 return LHSRes; 354 355 if (Op == clang::OO_AmpAmp && !IsLHSSatisfied) 356 // [temp.constr.op] p2 357 // A conjunction is a constraint taking two operands. To determine if 358 // a conjunction is satisfied, the satisfaction of the first operand 359 // is checked. If that is not satisfied, the conjunction is not 360 // satisfied. Otherwise, the conjunction is satisfied if and only if 361 // the second operand is satisfied. 362 // LHS is instantiated while RHS is not. Skip creating invalid BinaryOp. 363 return LHSRes; 364 365 ExprResult RHSRes = calculateConstraintSatisfaction( 366 S, RHS, Template, TemplateNameLoc, MLTAL, Satisfaction); 367 if (RHSRes.isInvalid()) 368 return ExprError(); 369 370 bool IsRHSSatisfied = Satisfaction.IsSatisfied; 371 // Current implementation adds diagnostic information about the falsity 372 // of each false atomic constraint expression when it evaluates them. 373 // When the evaluation results to `false || true`, the information 374 // generated during the evaluation of left-hand side is meaningless 375 // because the whole expression evaluates to true. 376 // The following code removes the irrelevant diagnostic information. 377 // FIXME: We should probably delay the addition of diagnostic information 378 // until we know the entire expression is false. 379 if (Op == clang::OO_PipePipe && IsRHSSatisfied) { 380 auto EffectiveDetailEnd = Satisfaction.Details.begin(); 381 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 382 Satisfaction.Details.erase(EffectiveDetailEnd, Satisfaction.Details.end()); 383 } 384 385 if (!LHSRes.isUsable() || !RHSRes.isUsable()) 386 return ExprEmpty(); 387 388 return BinaryOperator::Create(S.Context, LHSRes.get(), RHSRes.get(), 389 BinaryOperator::getOverloadedOpcode(Op), 390 S.Context.BoolTy, VK_PRValue, OK_Ordinary, 391 LHS->getBeginLoc(), FPOptionsOverride{}); 392 } 393 394 static ExprResult calculateConstraintSatisfaction( 395 Sema &S, const CXXFoldExpr *FE, const NamedDecl *Template, 396 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, 397 ConstraintSatisfaction &Satisfaction) { 398 bool Conjunction = FE->getOperator() == BinaryOperatorKind::BO_LAnd; 399 size_t EffectiveDetailEndIndex = Satisfaction.Details.size(); 400 401 ExprResult Out; 402 if (FE->isLeftFold() && FE->getInit()) { 403 Out = calculateConstraintSatisfaction(S, FE->getInit(), Template, 404 TemplateNameLoc, MLTAL, Satisfaction); 405 if (Out.isInvalid()) 406 return ExprError(); 407 408 // If the first clause of a conjunction is not satisfied, 409 // or if the first clause of a disjection is satisfied, 410 // we have established satisfaction of the whole constraint 411 // and we should not continue further. 412 if (Conjunction != Satisfaction.IsSatisfied) 413 return Out; 414 } 415 UnsignedOrNone NumExpansions = EvaluateFoldExpandedConstraintSize( 416 S, FE, Template, TemplateNameLoc, MLTAL, Satisfaction); 417 if (!NumExpansions) 418 return ExprError(); 419 for (unsigned I = 0; I < *NumExpansions; I++) { 420 Sema::ArgPackSubstIndexRAII SubstIndex(S, I); 421 ExprResult Res = calculateConstraintSatisfaction( 422 S, FE->getPattern(), Template, TemplateNameLoc, MLTAL, Satisfaction); 423 if (Res.isInvalid()) 424 return ExprError(); 425 bool IsRHSSatisfied = Satisfaction.IsSatisfied; 426 if (!Conjunction && IsRHSSatisfied) { 427 auto EffectiveDetailEnd = Satisfaction.Details.begin(); 428 std::advance(EffectiveDetailEnd, EffectiveDetailEndIndex); 429 Satisfaction.Details.erase(EffectiveDetailEnd, 430 Satisfaction.Details.end()); 431 } 432 if (Out.isUnset()) 433 Out = Res; 434 else if (!Res.isUnset()) { 435 Out = BinaryOperator::Create( 436 S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy, 437 VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{}); 438 } 439 if (Conjunction != IsRHSSatisfied) 440 return Out; 441 } 442 443 if (FE->isRightFold() && FE->getInit()) { 444 ExprResult Res = calculateConstraintSatisfaction( 445 S, FE->getInit(), Template, TemplateNameLoc, MLTAL, Satisfaction); 446 if (Out.isInvalid()) 447 return ExprError(); 448 449 if (Out.isUnset()) 450 Out = Res; 451 else if (!Res.isUnset()) { 452 Out = BinaryOperator::Create( 453 S.Context, Out.get(), Res.get(), FE->getOperator(), S.Context.BoolTy, 454 VK_PRValue, OK_Ordinary, FE->getBeginLoc(), FPOptionsOverride{}); 455 } 456 } 457 458 if (Out.isUnset()) { 459 Satisfaction.IsSatisfied = Conjunction; 460 Out = S.BuildEmptyCXXFoldExpr(FE->getBeginLoc(), FE->getOperator()); 461 } 462 return Out; 463 } 464 465 static ExprResult calculateConstraintSatisfaction( 466 Sema &S, const Expr *ConstraintExpr, const NamedDecl *Template, 467 SourceLocation TemplateNameLoc, const MultiLevelTemplateArgumentList &MLTAL, 468 ConstraintSatisfaction &Satisfaction) { 469 ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts(); 470 471 if (LogicalBinOp BO = ConstraintExpr) 472 return calculateConstraintSatisfaction( 473 S, BO.getLHS(), BO.getOp(), BO.getRHS(), Template, TemplateNameLoc, 474 MLTAL, Satisfaction); 475 476 if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr)) { 477 // These aren't evaluated, so we don't care about cleanups, so we can just 478 // evaluate these as if the cleanups didn't exist. 479 return calculateConstraintSatisfaction( 480 S, C->getSubExpr(), Template, TemplateNameLoc, MLTAL, Satisfaction); 481 } 482 483 if (auto *FE = dyn_cast<CXXFoldExpr>(ConstraintExpr); 484 FE && S.getLangOpts().CPlusPlus26 && 485 (FE->getOperator() == BinaryOperatorKind::BO_LAnd || 486 FE->getOperator() == BinaryOperatorKind::BO_LOr)) { 487 return calculateConstraintSatisfaction(S, FE, Template, TemplateNameLoc, 488 MLTAL, Satisfaction); 489 } 490 491 // FIXME: We should not treat ConceptSpecializationExpr as atomic constraints. 492 493 // An atomic constraint expression 494 ExprResult SubstitutedAtomicExpr = EvaluateAtomicConstraint( 495 S, ConstraintExpr, Template, TemplateNameLoc, MLTAL, Satisfaction); 496 497 if (SubstitutedAtomicExpr.isInvalid()) 498 return ExprError(); 499 500 if (!SubstitutedAtomicExpr.isUsable()) 501 // Evaluator has decided satisfaction without yielding an expression. 502 return ExprEmpty(); 503 504 // We don't have the ability to evaluate this, since it contains a 505 // RecoveryExpr, so we want to fail overload resolution. Otherwise, 506 // we'd potentially pick up a different overload, and cause confusing 507 // diagnostics. SO, add a failure detail that will cause us to make this 508 // overload set not viable. 509 if (SubstitutedAtomicExpr.get()->containsErrors()) { 510 Satisfaction.IsSatisfied = false; 511 Satisfaction.ContainsErrors = true; 512 513 PartialDiagnostic Msg = S.PDiag(diag::note_constraint_references_error); 514 SmallString<128> DiagString; 515 DiagString = ": "; 516 Msg.EmitToString(S.getDiagnostics(), DiagString); 517 unsigned MessageSize = DiagString.size(); 518 char *Mem = new (S.Context) char[MessageSize]; 519 memcpy(Mem, DiagString.c_str(), MessageSize); 520 Satisfaction.Details.emplace_back( 521 new (S.Context) ConstraintSatisfaction::SubstitutionDiagnostic{ 522 SubstitutedAtomicExpr.get()->getBeginLoc(), 523 StringRef(Mem, MessageSize)}); 524 return SubstitutedAtomicExpr; 525 } 526 527 EnterExpressionEvaluationContext ConstantEvaluated( 528 S, Sema::ExpressionEvaluationContext::ConstantEvaluated); 529 SmallVector<PartialDiagnosticAt, 2> EvaluationDiags; 530 Expr::EvalResult EvalResult; 531 EvalResult.Diag = &EvaluationDiags; 532 if (!SubstitutedAtomicExpr.get()->EvaluateAsConstantExpr(EvalResult, 533 S.Context) || 534 !EvaluationDiags.empty()) { 535 // C++2a [temp.constr.atomic]p1 536 // ...E shall be a constant expression of type bool. 537 S.Diag(SubstitutedAtomicExpr.get()->getBeginLoc(), 538 diag::err_non_constant_constraint_expression) 539 << SubstitutedAtomicExpr.get()->getSourceRange(); 540 for (const PartialDiagnosticAt &PDiag : EvaluationDiags) 541 S.Diag(PDiag.first, PDiag.second); 542 return ExprError(); 543 } 544 545 assert(EvalResult.Val.isInt() && 546 "evaluating bool expression didn't produce int"); 547 Satisfaction.IsSatisfied = EvalResult.Val.getInt().getBoolValue(); 548 if (!Satisfaction.IsSatisfied) 549 Satisfaction.Details.emplace_back(SubstitutedAtomicExpr.get()); 550 551 return SubstitutedAtomicExpr; 552 } 553 554 static ExprResult calculateConstraintSatisfaction( 555 Sema &S, const NamedDecl *Template, SourceLocation TemplateNameLoc, 556 const MultiLevelTemplateArgumentList &MLTAL, const Expr *ConstraintExpr, 557 ConstraintSatisfaction &Satisfaction) { 558 559 return calculateConstraintSatisfaction(S, ConstraintExpr, Template, 560 TemplateNameLoc, MLTAL, Satisfaction); 561 } 562 563 static bool CheckConstraintSatisfaction( 564 Sema &S, const NamedDecl *Template, 565 ArrayRef<AssociatedConstraint> AssociatedConstraints, 566 llvm::SmallVectorImpl<Expr *> &Converted, 567 const MultiLevelTemplateArgumentList &TemplateArgsLists, 568 SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { 569 if (AssociatedConstraints.empty()) { 570 Satisfaction.IsSatisfied = true; 571 return false; 572 } 573 574 if (TemplateArgsLists.isAnyArgInstantiationDependent()) { 575 // No need to check satisfaction for dependent constraint expressions. 576 Satisfaction.IsSatisfied = true; 577 return false; 578 } 579 580 ArrayRef<TemplateArgument> TemplateArgs = 581 TemplateArgsLists.getNumSubstitutedLevels() > 0 582 ? TemplateArgsLists.getOutermost() 583 : ArrayRef<TemplateArgument>{}; 584 Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), 585 Sema::InstantiatingTemplate::ConstraintsCheck{}, 586 const_cast<NamedDecl *>(Template), TemplateArgs, TemplateIDRange); 587 if (Inst.isInvalid()) 588 return true; 589 590 for (const AssociatedConstraint &AC : AssociatedConstraints) { 591 Sema::ArgPackSubstIndexRAII _(S, AC.ArgPackSubstIndex); 592 ExprResult Res = calculateConstraintSatisfaction( 593 S, Template, TemplateIDRange.getBegin(), TemplateArgsLists, 594 AC.ConstraintExpr, Satisfaction); 595 if (Res.isInvalid()) 596 return true; 597 598 Converted.push_back(Res.get()); 599 if (!Satisfaction.IsSatisfied) { 600 // Backfill the 'converted' list with nulls so we can keep the Converted 601 // and unconverted lists in sync. 602 Converted.append(AssociatedConstraints.size() - Converted.size(), 603 nullptr); 604 // [temp.constr.op] p2 605 // [...] To determine if a conjunction is satisfied, the satisfaction 606 // of the first operand is checked. If that is not satisfied, the 607 // conjunction is not satisfied. [...] 608 return false; 609 } 610 } 611 return false; 612 } 613 614 bool Sema::CheckConstraintSatisfaction( 615 const NamedDecl *Template, 616 ArrayRef<AssociatedConstraint> AssociatedConstraints, 617 llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, 618 const MultiLevelTemplateArgumentList &TemplateArgsLists, 619 SourceRange TemplateIDRange, ConstraintSatisfaction &OutSatisfaction) { 620 if (AssociatedConstraints.empty()) { 621 OutSatisfaction.IsSatisfied = true; 622 return false; 623 } 624 if (!Template) { 625 return ::CheckConstraintSatisfaction( 626 *this, nullptr, AssociatedConstraints, ConvertedConstraints, 627 TemplateArgsLists, TemplateIDRange, OutSatisfaction); 628 } 629 // Invalid templates could make their way here. Substituting them could result 630 // in dependent expressions. 631 if (Template->isInvalidDecl()) { 632 OutSatisfaction.IsSatisfied = false; 633 return true; 634 } 635 636 // A list of the template argument list flattened in a predictible manner for 637 // the purposes of caching. The ConstraintSatisfaction type is in AST so it 638 // has no access to the MultiLevelTemplateArgumentList, so this has to happen 639 // here. 640 llvm::SmallVector<TemplateArgument, 4> FlattenedArgs; 641 for (auto List : TemplateArgsLists) 642 llvm::append_range(FlattenedArgs, List.Args); 643 644 llvm::FoldingSetNodeID ID; 645 ConstraintSatisfaction::Profile(ID, Context, Template, FlattenedArgs); 646 void *InsertPos; 647 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 648 OutSatisfaction = *Cached; 649 return false; 650 } 651 652 auto Satisfaction = 653 std::make_unique<ConstraintSatisfaction>(Template, FlattenedArgs); 654 if (::CheckConstraintSatisfaction(*this, Template, AssociatedConstraints, 655 ConvertedConstraints, TemplateArgsLists, 656 TemplateIDRange, *Satisfaction)) { 657 OutSatisfaction = *Satisfaction; 658 return true; 659 } 660 661 if (auto *Cached = SatisfactionCache.FindNodeOrInsertPos(ID, InsertPos)) { 662 // The evaluation of this constraint resulted in us trying to re-evaluate it 663 // recursively. This isn't really possible, except we try to form a 664 // RecoveryExpr as a part of the evaluation. If this is the case, just 665 // return the 'cached' version (which will have the same result), and save 666 // ourselves the extra-insert. If it ever becomes possible to legitimately 667 // recursively check a constraint, we should skip checking the 'inner' one 668 // above, and replace the cached version with this one, as it would be more 669 // specific. 670 OutSatisfaction = *Cached; 671 return false; 672 } 673 674 // Else we can simply add this satisfaction to the list. 675 OutSatisfaction = *Satisfaction; 676 // We cannot use InsertPos here because CheckConstraintSatisfaction might have 677 // invalidated it. 678 // Note that entries of SatisfactionCache are deleted in Sema's destructor. 679 SatisfactionCache.InsertNode(Satisfaction.release()); 680 return false; 681 } 682 683 bool Sema::CheckConstraintSatisfaction( 684 const ConceptSpecializationExpr *ConstraintExpr, 685 ConstraintSatisfaction &Satisfaction) { 686 687 MultiLevelTemplateArgumentList MLTAL(ConstraintExpr->getNamedConcept(), 688 ConstraintExpr->getTemplateArguments(), 689 true); 690 691 return calculateConstraintSatisfaction( 692 *this, ConstraintExpr, ConstraintExpr->getNamedConcept(), 693 ConstraintExpr->getConceptNameLoc(), MLTAL, Satisfaction) 694 .isInvalid(); 695 } 696 697 bool Sema::SetupConstraintScope( 698 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 699 const MultiLevelTemplateArgumentList &MLTAL, 700 LocalInstantiationScope &Scope) { 701 assert(!isLambdaCallOperator(FD) && 702 "Use LambdaScopeForCallOperatorInstantiationRAII to handle lambda " 703 "instantiations"); 704 if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { 705 FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); 706 InstantiatingTemplate Inst( 707 *this, FD->getPointOfInstantiation(), 708 Sema::InstantiatingTemplate::ConstraintsCheck{}, PrimaryTemplate, 709 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 710 SourceRange()); 711 if (Inst.isInvalid()) 712 return true; 713 714 // addInstantiatedParametersToScope creates a map of 'uninstantiated' to 715 // 'instantiated' parameters and adds it to the context. For the case where 716 // this function is a template being instantiated NOW, we also need to add 717 // the list of current template arguments to the list so that they also can 718 // be picked out of the map. 719 if (auto *SpecArgs = FD->getTemplateSpecializationArgs()) { 720 MultiLevelTemplateArgumentList JustTemplArgs(FD, SpecArgs->asArray(), 721 /*Final=*/false); 722 if (addInstantiatedParametersToScope( 723 FD, PrimaryTemplate->getTemplatedDecl(), Scope, JustTemplArgs)) 724 return true; 725 } 726 727 // If this is a member function, make sure we get the parameters that 728 // reference the original primary template. 729 if (FunctionTemplateDecl *FromMemTempl = 730 PrimaryTemplate->getInstantiatedFromMemberTemplate()) { 731 if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), 732 Scope, MLTAL)) 733 return true; 734 } 735 736 return false; 737 } 738 739 if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || 740 FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { 741 FunctionDecl *InstantiatedFrom = 742 FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization 743 ? FD->getInstantiatedFromMemberFunction() 744 : FD->getInstantiatedFromDecl(); 745 746 InstantiatingTemplate Inst( 747 *this, FD->getPointOfInstantiation(), 748 Sema::InstantiatingTemplate::ConstraintsCheck{}, InstantiatedFrom, 749 TemplateArgs ? *TemplateArgs : ArrayRef<TemplateArgument>{}, 750 SourceRange()); 751 if (Inst.isInvalid()) 752 return true; 753 754 // Case where this was not a template, but instantiated as a 755 // child-function. 756 if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL)) 757 return true; 758 } 759 760 return false; 761 } 762 763 // This function collects all of the template arguments for the purposes of 764 // constraint-instantiation and checking. 765 std::optional<MultiLevelTemplateArgumentList> 766 Sema::SetupConstraintCheckingTemplateArgumentsAndScope( 767 FunctionDecl *FD, std::optional<ArrayRef<TemplateArgument>> TemplateArgs, 768 LocalInstantiationScope &Scope) { 769 MultiLevelTemplateArgumentList MLTAL; 770 771 // Collect the list of template arguments relative to the 'primary' template. 772 // We need the entire list, since the constraint is completely uninstantiated 773 // at this point. 774 MLTAL = 775 getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), 776 /*Final=*/false, /*Innermost=*/std::nullopt, 777 /*RelativeToPrimary=*/true, 778 /*Pattern=*/nullptr, 779 /*ForConstraintInstantiation=*/true); 780 // Lambdas are handled by LambdaScopeForCallOperatorInstantiationRAII. 781 if (isLambdaCallOperator(FD)) 782 return MLTAL; 783 if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) 784 return std::nullopt; 785 786 return MLTAL; 787 } 788 789 bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, 790 ConstraintSatisfaction &Satisfaction, 791 SourceLocation UsageLoc, 792 bool ForOverloadResolution) { 793 // Don't check constraints if the function is dependent. Also don't check if 794 // this is a function template specialization, as the call to 795 // CheckFunctionTemplateConstraints after this will check it 796 // better. 797 if (FD->isDependentContext() || 798 FD->getTemplatedKind() == 799 FunctionDecl::TK_FunctionTemplateSpecialization) { 800 Satisfaction.IsSatisfied = true; 801 return false; 802 } 803 804 // A lambda conversion operator has the same constraints as the call operator 805 // and constraints checking relies on whether we are in a lambda call operator 806 // (and may refer to its parameters), so check the call operator instead. 807 // Note that the declarations outside of the lambda should also be 808 // considered. Turning on the 'ForOverloadResolution' flag results in the 809 // LocalInstantiationScope not looking into its parents, but we can still 810 // access Decls from the parents while building a lambda RAII scope later. 811 if (const auto *MD = dyn_cast<CXXConversionDecl>(FD); 812 MD && isLambdaConversionOperator(const_cast<CXXConversionDecl *>(MD))) 813 return CheckFunctionConstraints(MD->getParent()->getLambdaCallOperator(), 814 Satisfaction, UsageLoc, 815 /*ShouldAddDeclsFromParentScope=*/true); 816 817 DeclContext *CtxToSave = const_cast<FunctionDecl *>(FD); 818 819 while (isLambdaCallOperator(CtxToSave) || FD->isTransparentContext()) { 820 if (isLambdaCallOperator(CtxToSave)) 821 CtxToSave = CtxToSave->getParent()->getParent(); 822 else 823 CtxToSave = CtxToSave->getNonTransparentContext(); 824 } 825 826 ContextRAII SavedContext{*this, CtxToSave}; 827 LocalInstantiationScope Scope(*this, !ForOverloadResolution); 828 std::optional<MultiLevelTemplateArgumentList> MLTAL = 829 SetupConstraintCheckingTemplateArgumentsAndScope( 830 const_cast<FunctionDecl *>(FD), {}, Scope); 831 832 if (!MLTAL) 833 return true; 834 835 Qualifiers ThisQuals; 836 CXXRecordDecl *Record = nullptr; 837 if (auto *Method = dyn_cast<CXXMethodDecl>(FD)) { 838 ThisQuals = Method->getMethodQualifiers(); 839 Record = const_cast<CXXRecordDecl *>(Method->getParent()); 840 } 841 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 842 843 LambdaScopeForCallOperatorInstantiationRAII LambdaScope( 844 *this, const_cast<FunctionDecl *>(FD), *MLTAL, Scope, 845 ForOverloadResolution); 846 847 return CheckConstraintSatisfaction( 848 FD, FD->getTrailingRequiresClause(), *MLTAL, 849 SourceRange(UsageLoc.isValid() ? UsageLoc : FD->getLocation()), 850 Satisfaction); 851 } 852 853 854 // Figure out the to-translation-unit depth for this function declaration for 855 // the purpose of seeing if they differ by constraints. This isn't the same as 856 // getTemplateDepth, because it includes already instantiated parents. 857 static unsigned 858 CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, 859 bool SkipForSpecialization = false) { 860 MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 861 ND, ND->getLexicalDeclContext(), /*Final=*/false, 862 /*Innermost=*/std::nullopt, 863 /*RelativeToPrimary=*/true, 864 /*Pattern=*/nullptr, 865 /*ForConstraintInstantiation=*/true, SkipForSpecialization); 866 return MLTAL.getNumLevels(); 867 } 868 869 namespace { 870 class AdjustConstraintDepth : public TreeTransform<AdjustConstraintDepth> { 871 unsigned TemplateDepth = 0; 872 public: 873 using inherited = TreeTransform<AdjustConstraintDepth>; 874 AdjustConstraintDepth(Sema &SemaRef, unsigned TemplateDepth) 875 : inherited(SemaRef), TemplateDepth(TemplateDepth) {} 876 877 using inherited::TransformTemplateTypeParmType; 878 QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, 879 TemplateTypeParmTypeLoc TL, bool) { 880 const TemplateTypeParmType *T = TL.getTypePtr(); 881 882 TemplateTypeParmDecl *NewTTPDecl = nullptr; 883 if (TemplateTypeParmDecl *OldTTPDecl = T->getDecl()) 884 NewTTPDecl = cast_or_null<TemplateTypeParmDecl>( 885 TransformDecl(TL.getNameLoc(), OldTTPDecl)); 886 887 QualType Result = getSema().Context.getTemplateTypeParmType( 888 T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(), 889 NewTTPDecl); 890 TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); 891 NewTL.setNameLoc(TL.getNameLoc()); 892 return Result; 893 } 894 }; 895 } // namespace 896 897 static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( 898 Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, 899 const Expr *ConstrExpr) { 900 MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 901 DeclInfo.getDecl(), DeclInfo.getDeclContext(), /*Final=*/false, 902 /*Innermost=*/std::nullopt, 903 /*RelativeToPrimary=*/true, 904 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, 905 /*SkipForSpecialization*/ false); 906 907 if (MLTAL.getNumSubstitutedLevels() == 0) 908 return ConstrExpr; 909 910 Sema::SFINAETrap SFINAE(S); 911 912 Sema::InstantiatingTemplate Inst( 913 S, DeclInfo.getLocation(), 914 Sema::InstantiatingTemplate::ConstraintNormalization{}, 915 const_cast<NamedDecl *>(DeclInfo.getDecl()), SourceRange{}); 916 if (Inst.isInvalid()) 917 return nullptr; 918 919 // Set up a dummy 'instantiation' scope in the case of reference to function 920 // parameters that the surrounding function hasn't been instantiated yet. Note 921 // this may happen while we're comparing two templates' constraint 922 // equivalence. 923 std::optional<LocalInstantiationScope> ScopeForParameters; 924 if (const NamedDecl *ND = DeclInfo.getDecl(); 925 ND && ND->isFunctionOrFunctionTemplate()) { 926 ScopeForParameters.emplace(S, /*CombineWithOuterScope=*/true); 927 const FunctionDecl *FD = ND->getAsFunction(); 928 for (auto *PVD : FD->parameters()) { 929 if (!PVD->isParameterPack()) { 930 ScopeForParameters->InstantiatedLocal(PVD, PVD); 931 continue; 932 } 933 // This is hacky: we're mapping the parameter pack to a size-of-1 argument 934 // to avoid building SubstTemplateTypeParmPackTypes for 935 // PackExpansionTypes. The SubstTemplateTypeParmPackType node would 936 // otherwise reference the AssociatedDecl of the template arguments, which 937 // is, in this case, the template declaration. 938 // 939 // However, as we are in the process of comparing potential 940 // re-declarations, the canonical declaration is the declaration itself at 941 // this point. So if we didn't expand these packs, we would end up with an 942 // incorrect profile difference because we will be profiling the 943 // canonical types! 944 // 945 // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so 946 // that we can eliminate the Scope in the cases where the declarations are 947 // not necessarily instantiated. It would also benefit the noexcept 948 // specifier comparison. 949 ScopeForParameters->MakeInstantiatedLocalArgPack(PVD); 950 ScopeForParameters->InstantiatedLocalPackArg(PVD, PVD); 951 } 952 } 953 954 std::optional<Sema::CXXThisScopeRAII> ThisScope; 955 956 // See TreeTransform::RebuildTemplateSpecializationType. A context scope is 957 // essential for having an injected class as the canonical type for a template 958 // specialization type at the rebuilding stage. This guarantees that, for 959 // out-of-line definitions, injected class name types and their equivalent 960 // template specializations can be profiled to the same value, which makes it 961 // possible that e.g. constraints involving C<Class<T>> and C<Class> are 962 // perceived identical. 963 std::optional<Sema::ContextRAII> ContextScope; 964 const DeclContext *DC = [&] { 965 if (!DeclInfo.getDecl()) 966 return DeclInfo.getDeclContext(); 967 return DeclInfo.getDecl()->getFriendObjectKind() 968 ? DeclInfo.getLexicalDeclContext() 969 : DeclInfo.getDeclContext(); 970 }(); 971 if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { 972 ThisScope.emplace(S, const_cast<CXXRecordDecl *>(RD), Qualifiers()); 973 ContextScope.emplace(S, const_cast<DeclContext *>(cast<DeclContext>(RD)), 974 /*NewThisContext=*/false); 975 } 976 EnterExpressionEvaluationContext UnevaluatedContext( 977 S, Sema::ExpressionEvaluationContext::Unevaluated, 978 Sema::ReuseLambdaContextDecl); 979 ExprResult SubstConstr = S.SubstConstraintExprWithoutSatisfaction( 980 const_cast<clang::Expr *>(ConstrExpr), MLTAL); 981 if (SFINAE.hasErrorOccurred() || !SubstConstr.isUsable()) 982 return nullptr; 983 return SubstConstr.get(); 984 } 985 986 bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, 987 const Expr *OldConstr, 988 const TemplateCompareNewDeclInfo &New, 989 const Expr *NewConstr) { 990 if (OldConstr == NewConstr) 991 return true; 992 // C++ [temp.constr.decl]p4 993 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) && 994 Old->getLexicalDeclContext() != New.getLexicalDeclContext()) { 995 if (const Expr *SubstConstr = 996 SubstituteConstraintExpressionWithoutSatisfaction(*this, Old, 997 OldConstr)) 998 OldConstr = SubstConstr; 999 else 1000 return false; 1001 if (const Expr *SubstConstr = 1002 SubstituteConstraintExpressionWithoutSatisfaction(*this, New, 1003 NewConstr)) 1004 NewConstr = SubstConstr; 1005 else 1006 return false; 1007 } 1008 1009 llvm::FoldingSetNodeID ID1, ID2; 1010 OldConstr->Profile(ID1, Context, /*Canonical=*/true); 1011 NewConstr->Profile(ID2, Context, /*Canonical=*/true); 1012 return ID1 == ID2; 1013 } 1014 1015 bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { 1016 assert(FD->getFriendObjectKind() && "Must be a friend!"); 1017 1018 // The logic for non-templates is handled in ASTContext::isSameEntity, so we 1019 // don't have to bother checking 'DependsOnEnclosingTemplate' for a 1020 // non-function-template. 1021 assert(FD->getDescribedFunctionTemplate() && 1022 "Non-function templates don't need to be checked"); 1023 1024 SmallVector<AssociatedConstraint, 3> ACs; 1025 FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); 1026 1027 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); 1028 for (const AssociatedConstraint &AC : ACs) 1029 if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, 1030 AC.ConstraintExpr)) 1031 return true; 1032 1033 return false; 1034 } 1035 1036 bool Sema::EnsureTemplateArgumentListConstraints( 1037 TemplateDecl *TD, const MultiLevelTemplateArgumentList &TemplateArgsLists, 1038 SourceRange TemplateIDRange) { 1039 ConstraintSatisfaction Satisfaction; 1040 llvm::SmallVector<AssociatedConstraint, 3> AssociatedConstraints; 1041 TD->getAssociatedConstraints(AssociatedConstraints); 1042 if (CheckConstraintSatisfaction(TD, AssociatedConstraints, TemplateArgsLists, 1043 TemplateIDRange, Satisfaction)) 1044 return true; 1045 1046 if (!Satisfaction.IsSatisfied) { 1047 SmallString<128> TemplateArgString; 1048 TemplateArgString = " "; 1049 TemplateArgString += getTemplateArgumentBindingsText( 1050 TD->getTemplateParameters(), TemplateArgsLists.getInnermost().data(), 1051 TemplateArgsLists.getInnermost().size()); 1052 1053 Diag(TemplateIDRange.getBegin(), 1054 diag::err_template_arg_list_constraints_not_satisfied) 1055 << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << TD 1056 << TemplateArgString << TemplateIDRange; 1057 DiagnoseUnsatisfiedConstraint(Satisfaction); 1058 return true; 1059 } 1060 return false; 1061 } 1062 1063 static bool CheckFunctionConstraintsWithoutInstantiation( 1064 Sema &SemaRef, SourceLocation PointOfInstantiation, 1065 FunctionTemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, 1066 ConstraintSatisfaction &Satisfaction) { 1067 SmallVector<AssociatedConstraint, 3> TemplateAC; 1068 Template->getAssociatedConstraints(TemplateAC); 1069 if (TemplateAC.empty()) { 1070 Satisfaction.IsSatisfied = true; 1071 return false; 1072 } 1073 1074 LocalInstantiationScope Scope(SemaRef); 1075 1076 FunctionDecl *FD = Template->getTemplatedDecl(); 1077 // Collect the list of template arguments relative to the 'primary' 1078 // template. We need the entire list, since the constraint is completely 1079 // uninstantiated at this point. 1080 1081 MultiLevelTemplateArgumentList MLTAL; 1082 { 1083 // getTemplateInstantiationArgs uses this instantiation context to find out 1084 // template arguments for uninstantiated functions. 1085 // We don't want this RAII object to persist, because there would be 1086 // otherwise duplicate diagnostic notes. 1087 Sema::InstantiatingTemplate Inst( 1088 SemaRef, PointOfInstantiation, 1089 Sema::InstantiatingTemplate::ConstraintsCheck{}, Template, TemplateArgs, 1090 PointOfInstantiation); 1091 if (Inst.isInvalid()) 1092 return true; 1093 MLTAL = SemaRef.getTemplateInstantiationArgs( 1094 /*D=*/FD, FD, 1095 /*Final=*/false, /*Innermost=*/{}, /*RelativeToPrimary=*/true, 1096 /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); 1097 } 1098 1099 Sema::ContextRAII SavedContext(SemaRef, FD); 1100 return SemaRef.CheckConstraintSatisfaction( 1101 Template, TemplateAC, MLTAL, PointOfInstantiation, Satisfaction); 1102 } 1103 1104 bool Sema::CheckFunctionTemplateConstraints( 1105 SourceLocation PointOfInstantiation, FunctionDecl *Decl, 1106 ArrayRef<TemplateArgument> TemplateArgs, 1107 ConstraintSatisfaction &Satisfaction) { 1108 // In most cases we're not going to have constraints, so check for that first. 1109 FunctionTemplateDecl *Template = Decl->getPrimaryTemplate(); 1110 1111 if (!Template) 1112 return ::CheckFunctionConstraintsWithoutInstantiation( 1113 *this, PointOfInstantiation, Decl->getDescribedFunctionTemplate(), 1114 TemplateArgs, Satisfaction); 1115 1116 // Note - code synthesis context for the constraints check is created 1117 // inside CheckConstraintsSatisfaction. 1118 SmallVector<AssociatedConstraint, 3> TemplateAC; 1119 Template->getAssociatedConstraints(TemplateAC); 1120 if (TemplateAC.empty()) { 1121 Satisfaction.IsSatisfied = true; 1122 return false; 1123 } 1124 1125 // Enter the scope of this instantiation. We don't use 1126 // PushDeclContext because we don't have a scope. 1127 Sema::ContextRAII savedContext(*this, Decl); 1128 LocalInstantiationScope Scope(*this); 1129 1130 std::optional<MultiLevelTemplateArgumentList> MLTAL = 1131 SetupConstraintCheckingTemplateArgumentsAndScope(Decl, TemplateArgs, 1132 Scope); 1133 1134 if (!MLTAL) 1135 return true; 1136 1137 Qualifiers ThisQuals; 1138 CXXRecordDecl *Record = nullptr; 1139 if (auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 1140 ThisQuals = Method->getMethodQualifiers(); 1141 Record = Method->getParent(); 1142 } 1143 1144 CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); 1145 LambdaScopeForCallOperatorInstantiationRAII LambdaScope(*this, Decl, *MLTAL, 1146 Scope); 1147 1148 return CheckConstraintSatisfaction(Template, TemplateAC, *MLTAL, 1149 PointOfInstantiation, Satisfaction); 1150 } 1151 1152 static void diagnoseUnsatisfiedRequirement(Sema &S, 1153 concepts::ExprRequirement *Req, 1154 bool First) { 1155 assert(!Req->isSatisfied() 1156 && "Diagnose() can only be used on an unsatisfied requirement"); 1157 switch (Req->getSatisfactionStatus()) { 1158 case concepts::ExprRequirement::SS_Dependent: 1159 llvm_unreachable("Diagnosing a dependent requirement"); 1160 break; 1161 case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { 1162 auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); 1163 if (!SubstDiag->DiagMessage.empty()) 1164 S.Diag(SubstDiag->DiagLoc, 1165 diag::note_expr_requirement_expr_substitution_error) 1166 << (int)First << SubstDiag->SubstitutedEntity 1167 << SubstDiag->DiagMessage; 1168 else 1169 S.Diag(SubstDiag->DiagLoc, 1170 diag::note_expr_requirement_expr_unknown_substitution_error) 1171 << (int)First << SubstDiag->SubstitutedEntity; 1172 break; 1173 } 1174 case concepts::ExprRequirement::SS_NoexceptNotMet: 1175 S.Diag(Req->getNoexceptLoc(), 1176 diag::note_expr_requirement_noexcept_not_met) 1177 << (int)First << Req->getExpr(); 1178 break; 1179 case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { 1180 auto *SubstDiag = 1181 Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); 1182 if (!SubstDiag->DiagMessage.empty()) 1183 S.Diag(SubstDiag->DiagLoc, 1184 diag::note_expr_requirement_type_requirement_substitution_error) 1185 << (int)First << SubstDiag->SubstitutedEntity 1186 << SubstDiag->DiagMessage; 1187 else 1188 S.Diag(SubstDiag->DiagLoc, 1189 diag::note_expr_requirement_type_requirement_unknown_substitution_error) 1190 << (int)First << SubstDiag->SubstitutedEntity; 1191 break; 1192 } 1193 case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { 1194 ConceptSpecializationExpr *ConstraintExpr = 1195 Req->getReturnTypeRequirementSubstitutedConstraintExpr(); 1196 if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1197 // A simple case - expr type is the type being constrained and the concept 1198 // was not provided arguments. 1199 Expr *e = Req->getExpr(); 1200 S.Diag(e->getBeginLoc(), 1201 diag::note_expr_requirement_constraints_not_satisfied_simple) 1202 << (int)First << S.Context.getReferenceQualifiedType(e) 1203 << ConstraintExpr->getNamedConcept(); 1204 } else { 1205 S.Diag(ConstraintExpr->getBeginLoc(), 1206 diag::note_expr_requirement_constraints_not_satisfied) 1207 << (int)First << ConstraintExpr; 1208 } 1209 S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); 1210 break; 1211 } 1212 case concepts::ExprRequirement::SS_Satisfied: 1213 llvm_unreachable("We checked this above"); 1214 } 1215 } 1216 1217 static void diagnoseUnsatisfiedRequirement(Sema &S, 1218 concepts::TypeRequirement *Req, 1219 bool First) { 1220 assert(!Req->isSatisfied() 1221 && "Diagnose() can only be used on an unsatisfied requirement"); 1222 switch (Req->getSatisfactionStatus()) { 1223 case concepts::TypeRequirement::SS_Dependent: 1224 llvm_unreachable("Diagnosing a dependent requirement"); 1225 return; 1226 case concepts::TypeRequirement::SS_SubstitutionFailure: { 1227 auto *SubstDiag = Req->getSubstitutionDiagnostic(); 1228 if (!SubstDiag->DiagMessage.empty()) 1229 S.Diag(SubstDiag->DiagLoc, 1230 diag::note_type_requirement_substitution_error) << (int)First 1231 << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; 1232 else 1233 S.Diag(SubstDiag->DiagLoc, 1234 diag::note_type_requirement_unknown_substitution_error) 1235 << (int)First << SubstDiag->SubstitutedEntity; 1236 return; 1237 } 1238 default: 1239 llvm_unreachable("Unknown satisfaction status"); 1240 return; 1241 } 1242 } 1243 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1244 Expr *SubstExpr, 1245 bool First = true); 1246 1247 static void diagnoseUnsatisfiedRequirement(Sema &S, 1248 concepts::NestedRequirement *Req, 1249 bool First) { 1250 using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; 1251 for (auto &Record : Req->getConstraintSatisfaction()) { 1252 if (auto *SubstDiag = Record.dyn_cast<SubstitutionDiagnostic *>()) 1253 S.Diag(SubstDiag->first, diag::note_nested_requirement_substitution_error) 1254 << (int)First << Req->getInvalidConstraintEntity() 1255 << SubstDiag->second; 1256 else 1257 diagnoseWellFormedUnsatisfiedConstraintExpr(S, Record.dyn_cast<Expr *>(), 1258 First); 1259 First = false; 1260 } 1261 } 1262 1263 static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, 1264 Expr *SubstExpr, 1265 bool First) { 1266 SubstExpr = SubstExpr->IgnoreParenImpCasts(); 1267 if (BinaryOperator *BO = dyn_cast<BinaryOperator>(SubstExpr)) { 1268 switch (BO->getOpcode()) { 1269 // These two cases will in practice only be reached when using fold 1270 // expressions with || and &&, since otherwise the || and && will have been 1271 // broken down into atomic constraints during satisfaction checking. 1272 case BO_LOr: 1273 // Or evaluated to false - meaning both RHS and LHS evaluated to false. 1274 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1275 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1276 /*First=*/false); 1277 return; 1278 case BO_LAnd: { 1279 bool LHSSatisfied = 1280 BO->getLHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1281 if (LHSSatisfied) { 1282 // LHS is true, so RHS must be false. 1283 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), First); 1284 return; 1285 } 1286 // LHS is false 1287 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getLHS(), First); 1288 1289 // RHS might also be false 1290 bool RHSSatisfied = 1291 BO->getRHS()->EvaluateKnownConstInt(S.Context).getBoolValue(); 1292 if (!RHSSatisfied) 1293 diagnoseWellFormedUnsatisfiedConstraintExpr(S, BO->getRHS(), 1294 /*First=*/false); 1295 return; 1296 } 1297 case BO_GE: 1298 case BO_LE: 1299 case BO_GT: 1300 case BO_LT: 1301 case BO_EQ: 1302 case BO_NE: 1303 if (BO->getLHS()->getType()->isIntegerType() && 1304 BO->getRHS()->getType()->isIntegerType()) { 1305 Expr::EvalResult SimplifiedLHS; 1306 Expr::EvalResult SimplifiedRHS; 1307 BO->getLHS()->EvaluateAsInt(SimplifiedLHS, S.Context, 1308 Expr::SE_NoSideEffects, 1309 /*InConstantContext=*/true); 1310 BO->getRHS()->EvaluateAsInt(SimplifiedRHS, S.Context, 1311 Expr::SE_NoSideEffects, 1312 /*InConstantContext=*/true); 1313 if (!SimplifiedLHS.Diag && ! SimplifiedRHS.Diag) { 1314 S.Diag(SubstExpr->getBeginLoc(), 1315 diag::note_atomic_constraint_evaluated_to_false_elaborated) 1316 << (int)First << SubstExpr 1317 << toString(SimplifiedLHS.Val.getInt(), 10) 1318 << BinaryOperator::getOpcodeStr(BO->getOpcode()) 1319 << toString(SimplifiedRHS.Val.getInt(), 10); 1320 return; 1321 } 1322 } 1323 break; 1324 1325 default: 1326 break; 1327 } 1328 } else if (auto *CSE = dyn_cast<ConceptSpecializationExpr>(SubstExpr)) { 1329 if (CSE->getTemplateArgsAsWritten()->NumTemplateArgs == 1) { 1330 S.Diag( 1331 CSE->getSourceRange().getBegin(), 1332 diag:: 1333 note_single_arg_concept_specialization_constraint_evaluated_to_false) 1334 << (int)First 1335 << CSE->getTemplateArgsAsWritten()->arguments()[0].getArgument() 1336 << CSE->getNamedConcept(); 1337 } else { 1338 S.Diag(SubstExpr->getSourceRange().getBegin(), 1339 diag::note_concept_specialization_constraint_evaluated_to_false) 1340 << (int)First << CSE; 1341 } 1342 S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); 1343 return; 1344 } else if (auto *RE = dyn_cast<RequiresExpr>(SubstExpr)) { 1345 // FIXME: RequiresExpr should store dependent diagnostics. 1346 for (concepts::Requirement *Req : RE->getRequirements()) 1347 if (!Req->isDependent() && !Req->isSatisfied()) { 1348 if (auto *E = dyn_cast<concepts::ExprRequirement>(Req)) 1349 diagnoseUnsatisfiedRequirement(S, E, First); 1350 else if (auto *T = dyn_cast<concepts::TypeRequirement>(Req)) 1351 diagnoseUnsatisfiedRequirement(S, T, First); 1352 else 1353 diagnoseUnsatisfiedRequirement( 1354 S, cast<concepts::NestedRequirement>(Req), First); 1355 break; 1356 } 1357 return; 1358 } else if (auto *TTE = dyn_cast<TypeTraitExpr>(SubstExpr); 1359 TTE && TTE->getTrait() == clang::TypeTrait::BTT_IsDeducible) { 1360 assert(TTE->getNumArgs() == 2); 1361 S.Diag(SubstExpr->getSourceRange().getBegin(), 1362 diag::note_is_deducible_constraint_evaluated_to_false) 1363 << TTE->getArg(0)->getType() << TTE->getArg(1)->getType(); 1364 return; 1365 } 1366 1367 S.Diag(SubstExpr->getSourceRange().getBegin(), 1368 diag::note_atomic_constraint_evaluated_to_false) 1369 << (int)First << SubstExpr; 1370 S.DiagnoseTypeTraitDetails(SubstExpr); 1371 } 1372 1373 template <typename SubstitutionDiagnostic> 1374 static void diagnoseUnsatisfiedConstraintExpr( 1375 Sema &S, const llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> &Record, 1376 bool First = true) { 1377 if (auto *Diag = Record.template dyn_cast<SubstitutionDiagnostic *>()) { 1378 S.Diag(Diag->first, diag::note_substituted_constraint_expr_is_ill_formed) 1379 << Diag->second; 1380 return; 1381 } 1382 1383 diagnoseWellFormedUnsatisfiedConstraintExpr(S, cast<Expr *>(Record), First); 1384 } 1385 1386 void 1387 Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, 1388 bool First) { 1389 assert(!Satisfaction.IsSatisfied && 1390 "Attempted to diagnose a satisfied constraint"); 1391 for (auto &Record : Satisfaction.Details) { 1392 diagnoseUnsatisfiedConstraintExpr(*this, Record, First); 1393 First = false; 1394 } 1395 } 1396 1397 void Sema::DiagnoseUnsatisfiedConstraint( 1398 const ASTConstraintSatisfaction &Satisfaction, 1399 bool First) { 1400 assert(!Satisfaction.IsSatisfied && 1401 "Attempted to diagnose a satisfied constraint"); 1402 for (auto &Record : Satisfaction) { 1403 diagnoseUnsatisfiedConstraintExpr(*this, Record, First); 1404 First = false; 1405 } 1406 } 1407 1408 const NormalizedConstraint *Sema::getNormalizedAssociatedConstraints( 1409 const NamedDecl *ConstrainedDecl, 1410 ArrayRef<AssociatedConstraint> AssociatedConstraints) { 1411 // In case the ConstrainedDecl comes from modules, it is necessary to use 1412 // the canonical decl to avoid different atomic constraints with the 'same' 1413 // declarations. 1414 ConstrainedDecl = cast<NamedDecl>(ConstrainedDecl->getCanonicalDecl()); 1415 1416 auto CacheEntry = NormalizationCache.find(ConstrainedDecl); 1417 if (CacheEntry == NormalizationCache.end()) { 1418 auto Normalized = NormalizedConstraint::fromAssociatedConstraints( 1419 *this, ConstrainedDecl, AssociatedConstraints); 1420 CacheEntry = 1421 NormalizationCache 1422 .try_emplace(ConstrainedDecl, 1423 Normalized 1424 ? new (Context) NormalizedConstraint( 1425 std::move(*Normalized)) 1426 : nullptr) 1427 .first; 1428 } 1429 return CacheEntry->second; 1430 } 1431 1432 const NormalizedConstraint *clang::getNormalizedAssociatedConstraints( 1433 Sema &S, const NamedDecl *ConstrainedDecl, 1434 ArrayRef<AssociatedConstraint> AssociatedConstraints) { 1435 return S.getNormalizedAssociatedConstraints(ConstrainedDecl, 1436 AssociatedConstraints); 1437 } 1438 1439 static bool 1440 substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1441 ConceptDecl *Concept, 1442 const MultiLevelTemplateArgumentList &MLTAL, 1443 const ASTTemplateArgumentListInfo *ArgsAsWritten) { 1444 1445 if (N.isCompound()) { 1446 if (substituteParameterMappings(S, N.getLHS(), Concept, MLTAL, 1447 ArgsAsWritten)) 1448 return true; 1449 return substituteParameterMappings(S, N.getRHS(), Concept, MLTAL, 1450 ArgsAsWritten); 1451 } 1452 1453 if (N.isFoldExpanded()) { 1454 Sema::ArgPackSubstIndexRAII _(S, std::nullopt); 1455 return substituteParameterMappings( 1456 S, N.getFoldExpandedConstraint()->Constraint, Concept, MLTAL, 1457 ArgsAsWritten); 1458 } 1459 1460 TemplateParameterList *TemplateParams = Concept->getTemplateParameters(); 1461 1462 AtomicConstraint &Atomic = *N.getAtomicConstraint(); 1463 TemplateArgumentListInfo SubstArgs; 1464 if (!Atomic.ParameterMapping) { 1465 llvm::SmallBitVector OccurringIndices(TemplateParams->size()); 1466 S.MarkUsedTemplateParameters(Atomic.ConstraintExpr, /*OnlyDeduced=*/false, 1467 /*Depth=*/0, OccurringIndices); 1468 TemplateArgumentLoc *TempArgs = 1469 new (S.Context) TemplateArgumentLoc[OccurringIndices.count()]; 1470 for (unsigned I = 0, J = 0, C = TemplateParams->size(); I != C; ++I) 1471 if (OccurringIndices[I]) 1472 new (&(TempArgs)[J++]) 1473 TemplateArgumentLoc(S.getIdentityTemplateArgumentLoc( 1474 TemplateParams->begin()[I], 1475 // Here we assume we do not support things like 1476 // template<typename A, typename B> 1477 // concept C = ...; 1478 // 1479 // template<typename... Ts> requires C<Ts...> 1480 // struct S { }; 1481 // The above currently yields a diagnostic. 1482 // We still might have default arguments for concept parameters. 1483 ArgsAsWritten->NumTemplateArgs > I 1484 ? ArgsAsWritten->arguments()[I].getLocation() 1485 : SourceLocation())); 1486 Atomic.ParameterMapping.emplace(TempArgs, OccurringIndices.count()); 1487 } 1488 SourceLocation InstLocBegin = 1489 ArgsAsWritten->arguments().empty() 1490 ? ArgsAsWritten->getLAngleLoc() 1491 : ArgsAsWritten->arguments().front().getSourceRange().getBegin(); 1492 SourceLocation InstLocEnd = 1493 ArgsAsWritten->arguments().empty() 1494 ? ArgsAsWritten->getRAngleLoc() 1495 : ArgsAsWritten->arguments().front().getSourceRange().getEnd(); 1496 Sema::InstantiatingTemplate Inst( 1497 S, InstLocBegin, 1498 Sema::InstantiatingTemplate::ParameterMappingSubstitution{}, 1499 const_cast<NamedDecl *>(Atomic.ConstraintDecl), 1500 {InstLocBegin, InstLocEnd}); 1501 if (Inst.isInvalid()) 1502 return true; 1503 if (S.SubstTemplateArguments(*Atomic.ParameterMapping, MLTAL, SubstArgs)) 1504 return true; 1505 1506 TemplateArgumentLoc *TempArgs = 1507 new (S.Context) TemplateArgumentLoc[SubstArgs.size()]; 1508 std::copy(SubstArgs.arguments().begin(), SubstArgs.arguments().end(), 1509 TempArgs); 1510 Atomic.ParameterMapping.emplace(TempArgs, SubstArgs.size()); 1511 return false; 1512 } 1513 1514 static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, 1515 const ConceptSpecializationExpr *CSE) { 1516 MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( 1517 CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), 1518 /*Final=*/false, CSE->getTemplateArguments(), 1519 /*RelativeToPrimary=*/true, 1520 /*Pattern=*/nullptr, 1521 /*ForConstraintInstantiation=*/true); 1522 1523 return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, 1524 CSE->getTemplateArgsAsWritten()); 1525 } 1526 1527 NormalizedConstraint::NormalizedConstraint(ASTContext &C, 1528 NormalizedConstraint LHS, 1529 NormalizedConstraint RHS, 1530 CompoundConstraintKind Kind) 1531 : Constraint{CompoundConstraint{ 1532 new(C) NormalizedConstraintPair{std::move(LHS), std::move(RHS)}, 1533 Kind}} {} 1534 1535 NormalizedConstraint::NormalizedConstraint(ASTContext &C, 1536 const NormalizedConstraint &Other) { 1537 if (Other.isAtomic()) { 1538 Constraint = new (C) AtomicConstraint(*Other.getAtomicConstraint()); 1539 } else if (Other.isFoldExpanded()) { 1540 Constraint = new (C) FoldExpandedConstraint( 1541 Other.getFoldExpandedConstraint()->Kind, 1542 NormalizedConstraint(C, Other.getFoldExpandedConstraint()->Constraint), 1543 Other.getFoldExpandedConstraint()->Pattern); 1544 } else { 1545 Constraint = CompoundConstraint( 1546 new (C) 1547 NormalizedConstraintPair{NormalizedConstraint(C, Other.getLHS()), 1548 NormalizedConstraint(C, Other.getRHS())}, 1549 Other.getCompoundKind()); 1550 } 1551 } 1552 1553 NormalizedConstraint &NormalizedConstraint::getLHS() const { 1554 assert(isCompound() && "getLHS called on a non-compound constraint."); 1555 return cast<CompoundConstraint>(Constraint).getPointer()->LHS; 1556 } 1557 1558 NormalizedConstraint &NormalizedConstraint::getRHS() const { 1559 assert(isCompound() && "getRHS called on a non-compound constraint."); 1560 return cast<CompoundConstraint>(Constraint).getPointer()->RHS; 1561 } 1562 1563 std::optional<NormalizedConstraint> 1564 NormalizedConstraint::fromAssociatedConstraints( 1565 Sema &S, const NamedDecl *D, ArrayRef<AssociatedConstraint> ACs) { 1566 assert(ACs.size() != 0); 1567 auto Conjunction = fromConstraintExpr(S, D, ACs[0].ConstraintExpr); 1568 if (!Conjunction) 1569 return std::nullopt; 1570 for (unsigned I = 1; I < ACs.size(); ++I) { 1571 auto Next = fromConstraintExpr(S, D, ACs[I].ConstraintExpr); 1572 if (!Next) 1573 return std::nullopt; 1574 *Conjunction = NormalizedConstraint(S.Context, std::move(*Conjunction), 1575 std::move(*Next), CCK_Conjunction); 1576 } 1577 return Conjunction; 1578 } 1579 1580 std::optional<NormalizedConstraint> 1581 NormalizedConstraint::fromConstraintExpr(Sema &S, const NamedDecl *D, 1582 const Expr *E) { 1583 assert(E != nullptr); 1584 1585 // C++ [temp.constr.normal]p1.1 1586 // [...] 1587 // - The normal form of an expression (E) is the normal form of E. 1588 // [...] 1589 E = E->IgnoreParenImpCasts(); 1590 1591 // C++2a [temp.param]p4: 1592 // [...] If T is not a pack, then E is E', otherwise E is (E' && ...). 1593 // Fold expression is considered atomic constraints per current wording. 1594 // See http://cplusplus.github.io/concepts-ts/ts-active.html#28 1595 1596 if (LogicalBinOp BO = E) { 1597 auto LHS = fromConstraintExpr(S, D, BO.getLHS()); 1598 if (!LHS) 1599 return std::nullopt; 1600 auto RHS = fromConstraintExpr(S, D, BO.getRHS()); 1601 if (!RHS) 1602 return std::nullopt; 1603 1604 return NormalizedConstraint(S.Context, std::move(*LHS), std::move(*RHS), 1605 BO.isAnd() ? CCK_Conjunction : CCK_Disjunction); 1606 } else if (auto *CSE = dyn_cast<const ConceptSpecializationExpr>(E)) { 1607 const NormalizedConstraint *SubNF; 1608 { 1609 Sema::InstantiatingTemplate Inst( 1610 S, CSE->getExprLoc(), 1611 Sema::InstantiatingTemplate::ConstraintNormalization{}, 1612 // FIXME: improve const-correctness of InstantiatingTemplate 1613 const_cast<NamedDecl *>(D), CSE->getSourceRange()); 1614 if (Inst.isInvalid()) 1615 return std::nullopt; 1616 // C++ [temp.constr.normal]p1.1 1617 // [...] 1618 // The normal form of an id-expression of the form C<A1, A2, ..., AN>, 1619 // where C names a concept, is the normal form of the 1620 // constraint-expression of C, after substituting A1, A2, ..., AN for C’s 1621 // respective template parameters in the parameter mappings in each atomic 1622 // constraint. If any such substitution results in an invalid type or 1623 // expression, the program is ill-formed; no diagnostic is required. 1624 // [...] 1625 ConceptDecl *CD = CSE->getNamedConcept(); 1626 SubNF = S.getNormalizedAssociatedConstraints( 1627 CD, AssociatedConstraint(CD->getConstraintExpr())); 1628 if (!SubNF) 1629 return std::nullopt; 1630 } 1631 1632 std::optional<NormalizedConstraint> New; 1633 New.emplace(S.Context, *SubNF); 1634 1635 if (substituteParameterMappings(S, *New, CSE)) 1636 return std::nullopt; 1637 1638 return New; 1639 } else if (auto *FE = dyn_cast<const CXXFoldExpr>(E); 1640 FE && S.getLangOpts().CPlusPlus26 && 1641 (FE->getOperator() == BinaryOperatorKind::BO_LAnd || 1642 FE->getOperator() == BinaryOperatorKind::BO_LOr)) { 1643 1644 // Normalize fold expressions in C++26. 1645 1646 FoldExpandedConstraint::FoldOperatorKind Kind = 1647 FE->getOperator() == BinaryOperatorKind::BO_LAnd 1648 ? FoldExpandedConstraint::FoldOperatorKind::And 1649 : FoldExpandedConstraint::FoldOperatorKind::Or; 1650 1651 if (FE->getInit()) { 1652 auto LHS = fromConstraintExpr(S, D, FE->getLHS()); 1653 auto RHS = fromConstraintExpr(S, D, FE->getRHS()); 1654 if (!LHS || !RHS) 1655 return std::nullopt; 1656 1657 if (FE->isRightFold()) 1658 RHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 1659 Kind, std::move(*RHS), FE->getPattern()}}; 1660 else 1661 LHS = NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 1662 Kind, std::move(*LHS), FE->getPattern()}}; 1663 1664 return NormalizedConstraint( 1665 S.Context, std::move(*LHS), std::move(*RHS), 1666 FE->getOperator() == BinaryOperatorKind::BO_LAnd ? CCK_Conjunction 1667 : CCK_Disjunction); 1668 } 1669 auto Sub = fromConstraintExpr(S, D, FE->getPattern()); 1670 if (!Sub) 1671 return std::nullopt; 1672 return NormalizedConstraint{new (S.Context) FoldExpandedConstraint{ 1673 Kind, std::move(*Sub), FE->getPattern()}}; 1674 } 1675 1676 return NormalizedConstraint{new (S.Context) AtomicConstraint(E, D)}; 1677 } 1678 1679 bool FoldExpandedConstraint::AreCompatibleForSubsumption( 1680 const FoldExpandedConstraint &A, const FoldExpandedConstraint &B) { 1681 1682 // [C++26] [temp.constr.fold] 1683 // Two fold expanded constraints are compatible for subsumption 1684 // if their respective constraints both contain an equivalent unexpanded pack. 1685 1686 llvm::SmallVector<UnexpandedParameterPack> APacks, BPacks; 1687 Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(A.Pattern), APacks); 1688 Sema::collectUnexpandedParameterPacks(const_cast<Expr *>(B.Pattern), BPacks); 1689 1690 for (const UnexpandedParameterPack &APack : APacks) { 1691 std::pair<unsigned, unsigned> DepthAndIndex = getDepthAndIndex(APack); 1692 auto it = llvm::find_if(BPacks, [&](const UnexpandedParameterPack &BPack) { 1693 return getDepthAndIndex(BPack) == DepthAndIndex; 1694 }); 1695 if (it != BPacks.end()) 1696 return true; 1697 } 1698 return false; 1699 } 1700 1701 bool Sema::IsAtLeastAsConstrained(const NamedDecl *D1, 1702 MutableArrayRef<AssociatedConstraint> AC1, 1703 const NamedDecl *D2, 1704 MutableArrayRef<AssociatedConstraint> AC2, 1705 bool &Result) { 1706 #ifndef NDEBUG 1707 if (const auto *FD1 = dyn_cast<FunctionDecl>(D1)) { 1708 auto IsExpectedEntity = [](const FunctionDecl *FD) { 1709 FunctionDecl::TemplatedKind Kind = FD->getTemplatedKind(); 1710 return Kind == FunctionDecl::TK_NonTemplate || 1711 Kind == FunctionDecl::TK_FunctionTemplate; 1712 }; 1713 const auto *FD2 = dyn_cast<FunctionDecl>(D2); 1714 assert(IsExpectedEntity(FD1) && FD2 && IsExpectedEntity(FD2) && 1715 "use non-instantiated function declaration for constraints partial " 1716 "ordering"); 1717 } 1718 #endif 1719 1720 if (AC1.empty()) { 1721 Result = AC2.empty(); 1722 return false; 1723 } 1724 if (AC2.empty()) { 1725 // TD1 has associated constraints and TD2 does not. 1726 Result = true; 1727 return false; 1728 } 1729 1730 std::pair<const NamedDecl *, const NamedDecl *> Key{D1, D2}; 1731 auto CacheEntry = SubsumptionCache.find(Key); 1732 if (CacheEntry != SubsumptionCache.end()) { 1733 Result = CacheEntry->second; 1734 return false; 1735 } 1736 1737 unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); 1738 unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); 1739 1740 for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { 1741 if (Depth2 > Depth1) { 1742 AC1[I].ConstraintExpr = 1743 AdjustConstraintDepth(*this, Depth2 - Depth1) 1744 .TransformExpr(const_cast<Expr *>(AC1[I].ConstraintExpr)) 1745 .get(); 1746 } else if (Depth1 > Depth2) { 1747 AC2[I].ConstraintExpr = 1748 AdjustConstraintDepth(*this, Depth1 - Depth2) 1749 .TransformExpr(const_cast<Expr *>(AC2[I].ConstraintExpr)) 1750 .get(); 1751 } 1752 } 1753 1754 SubsumptionChecker SC(*this); 1755 std::optional<bool> Subsumes = SC.Subsumes(D1, AC1, D2, AC2); 1756 if (!Subsumes) { 1757 // Normalization failed 1758 return true; 1759 } 1760 Result = *Subsumes; 1761 SubsumptionCache.try_emplace(Key, *Subsumes); 1762 return false; 1763 } 1764 1765 bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic( 1766 const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1, 1767 const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2) { 1768 if (isSFINAEContext()) 1769 // No need to work here because our notes would be discarded. 1770 return false; 1771 1772 if (AC1.empty() || AC2.empty()) 1773 return false; 1774 1775 const Expr *AmbiguousAtomic1 = nullptr, *AmbiguousAtomic2 = nullptr; 1776 auto IdenticalExprEvaluator = [&](const AtomicConstraint &A, 1777 const AtomicConstraint &B) { 1778 if (!A.hasMatchingParameterMapping(Context, B)) 1779 return false; 1780 const Expr *EA = A.ConstraintExpr, *EB = B.ConstraintExpr; 1781 if (EA == EB) 1782 return true; 1783 1784 // Not the same source level expression - are the expressions 1785 // identical? 1786 llvm::FoldingSetNodeID IDA, IDB; 1787 EA->Profile(IDA, Context, /*Canonical=*/true); 1788 EB->Profile(IDB, Context, /*Canonical=*/true); 1789 if (IDA != IDB) 1790 return false; 1791 1792 AmbiguousAtomic1 = EA; 1793 AmbiguousAtomic2 = EB; 1794 return true; 1795 }; 1796 1797 { 1798 // The subsumption checks might cause diagnostics 1799 SFINAETrap Trap(*this); 1800 auto *Normalized1 = getNormalizedAssociatedConstraints(D1, AC1); 1801 if (!Normalized1) 1802 return false; 1803 1804 auto *Normalized2 = getNormalizedAssociatedConstraints(D2, AC2); 1805 if (!Normalized2) 1806 return false; 1807 1808 SubsumptionChecker SC(*this); 1809 1810 bool Is1AtLeastAs2Normally = SC.Subsumes(Normalized1, Normalized2); 1811 bool Is2AtLeastAs1Normally = SC.Subsumes(Normalized2, Normalized1); 1812 1813 SubsumptionChecker SC2(*this, IdenticalExprEvaluator); 1814 bool Is1AtLeastAs2 = SC2.Subsumes(Normalized1, Normalized2); 1815 bool Is2AtLeastAs1 = SC2.Subsumes(Normalized2, Normalized1); 1816 1817 if (Is1AtLeastAs2 == Is1AtLeastAs2Normally && 1818 Is2AtLeastAs1 == Is2AtLeastAs1Normally) 1819 // Same result - no ambiguity was caused by identical atomic expressions. 1820 return false; 1821 } 1822 // A different result! Some ambiguous atomic constraint(s) caused a difference 1823 assert(AmbiguousAtomic1 && AmbiguousAtomic2); 1824 1825 Diag(AmbiguousAtomic1->getBeginLoc(), diag::note_ambiguous_atomic_constraints) 1826 << AmbiguousAtomic1->getSourceRange(); 1827 Diag(AmbiguousAtomic2->getBeginLoc(), 1828 diag::note_ambiguous_atomic_constraints_similar_expression) 1829 << AmbiguousAtomic2->getSourceRange(); 1830 return true; 1831 } 1832 1833 NormalizedConstraint::CompoundConstraintKind 1834 NormalizedConstraint::getCompoundKind() const { 1835 assert(isCompound() && "getCompoundKind on a non-compound constraint.."); 1836 return cast<CompoundConstraint>(Constraint).getInt(); 1837 } 1838 1839 AtomicConstraint *NormalizedConstraint::getAtomicConstraint() const { 1840 assert(isAtomic() && "getAtomicConstraint called on non-atomic constraint."); 1841 return cast<AtomicConstraint *>(Constraint); 1842 } 1843 1844 FoldExpandedConstraint * 1845 NormalizedConstraint::getFoldExpandedConstraint() const { 1846 assert(isFoldExpanded() && 1847 "getFoldExpandedConstraint called on non-fold-expanded constraint."); 1848 return cast<FoldExpandedConstraint *>(Constraint); 1849 } 1850 1851 // 1852 // 1853 // ------------------------ Subsumption ----------------------------------- 1854 // 1855 // 1856 1857 template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> { 1858 1859 static FoldingSetNodeID getEmptyKey() { 1860 FoldingSetNodeID ID; 1861 ID.AddInteger(std::numeric_limits<unsigned>::max()); 1862 return ID; 1863 } 1864 1865 static FoldingSetNodeID getTombstoneKey() { 1866 FoldingSetNodeID ID; 1867 for (unsigned I = 0; I < sizeof(ID) / sizeof(unsigned); ++I) { 1868 ID.AddInteger(std::numeric_limits<unsigned>::max()); 1869 } 1870 return ID; 1871 } 1872 1873 static unsigned getHashValue(const FoldingSetNodeID &Val) { 1874 return Val.ComputeHash(); 1875 } 1876 1877 static bool isEqual(const FoldingSetNodeID &LHS, 1878 const FoldingSetNodeID &RHS) { 1879 return LHS == RHS; 1880 } 1881 }; 1882 1883 SubsumptionChecker::SubsumptionChecker(Sema &SemaRef, 1884 SubsumptionCallable Callable) 1885 : SemaRef(SemaRef), Callable(Callable), NextID(1) {} 1886 1887 uint16_t SubsumptionChecker::getNewLiteralId() { 1888 assert((unsigned(NextID) + 1 < std::numeric_limits<uint16_t>::max()) && 1889 "too many constraints!"); 1890 return NextID++; 1891 } 1892 1893 auto SubsumptionChecker::find(AtomicConstraint *Ori) -> Literal { 1894 auto &Elems = AtomicMap[Ori->ConstraintExpr]; 1895 // C++ [temp.constr.order] p2 1896 // - an atomic constraint A subsumes another atomic constraint B 1897 // if and only if the A and B are identical [...] 1898 // 1899 // C++ [temp.constr.atomic] p2 1900 // Two atomic constraints are identical if they are formed from the 1901 // same expression and the targets of the parameter mappings are 1902 // equivalent according to the rules for expressions [...] 1903 1904 // Because subsumption of atomic constraints is an identity 1905 // relationship that does not require further analysis 1906 // We cache the results such that if an atomic constraint literal 1907 // subsumes another, their literal will be the same 1908 1909 llvm::FoldingSetNodeID ID; 1910 const auto &Mapping = Ori->ParameterMapping; 1911 ID.AddBoolean(Mapping.has_value()); 1912 if (Mapping) { 1913 for (const TemplateArgumentLoc &TAL : *Mapping) { 1914 SemaRef.getASTContext() 1915 .getCanonicalTemplateArgument(TAL.getArgument()) 1916 .Profile(ID, SemaRef.getASTContext()); 1917 } 1918 } 1919 auto It = Elems.find(ID); 1920 if (It == Elems.end()) { 1921 It = Elems 1922 .insert({ID, 1923 MappedAtomicConstraint{ 1924 Ori, {getNewLiteralId(), Literal::Atomic}}}) 1925 .first; 1926 ReverseMap[It->second.ID.Value] = Ori; 1927 } 1928 return It->getSecond().ID; 1929 } 1930 1931 auto SubsumptionChecker::find(FoldExpandedConstraint *Ori) -> Literal { 1932 auto &Elems = FoldMap[Ori->Pattern]; 1933 1934 FoldExpendedConstraintKey K; 1935 K.Kind = Ori->Kind; 1936 1937 auto It = llvm::find_if(Elems, [&K](const FoldExpendedConstraintKey &Other) { 1938 return K.Kind == Other.Kind; 1939 }); 1940 if (It == Elems.end()) { 1941 K.ID = {getNewLiteralId(), Literal::FoldExpanded}; 1942 It = Elems.insert(Elems.end(), std::move(K)); 1943 ReverseMap[It->ID.Value] = Ori; 1944 } 1945 return It->ID; 1946 } 1947 1948 auto SubsumptionChecker::CNF(const NormalizedConstraint &C) -> CNFFormula { 1949 return SubsumptionChecker::Normalize<CNFFormula>(C); 1950 } 1951 auto SubsumptionChecker::DNF(const NormalizedConstraint &C) -> DNFFormula { 1952 return SubsumptionChecker::Normalize<DNFFormula>(C); 1953 } 1954 1955 /// 1956 /// \brief SubsumptionChecker::Normalize 1957 /// 1958 /// Normalize a formula to Conjunctive Normal Form or 1959 /// Disjunctive normal form. 1960 /// 1961 /// Each Atomic (and Fold Expanded) constraint gets represented by 1962 /// a single id to reduce space. 1963 /// 1964 /// To minimize risks of exponential blow up, if two atomic 1965 /// constraints subsumes each other (same constraint and mapping), 1966 /// they are represented by the same literal. 1967 /// 1968 template <typename FormulaType> 1969 FormulaType SubsumptionChecker::Normalize(const NormalizedConstraint &NC) { 1970 FormulaType Res; 1971 1972 auto Add = [&, this](Clause C) { 1973 // Sort each clause and remove duplicates for faster comparisons. 1974 llvm::sort(C); 1975 C.erase(llvm::unique(C), C.end()); 1976 AddUniqueClauseToFormula(Res, std::move(C)); 1977 }; 1978 1979 if (NC.isAtomic()) 1980 return {{find(NC.getAtomicConstraint())}}; 1981 1982 if (NC.isFoldExpanded()) 1983 return {{find(NC.getFoldExpandedConstraint())}}; 1984 1985 FormulaType Left, Right; 1986 SemaRef.runWithSufficientStackSpace(SourceLocation(), [&] { 1987 Left = Normalize<FormulaType>(NC.getLHS()); 1988 Right = Normalize<FormulaType>(NC.getRHS()); 1989 }); 1990 1991 if (NC.getCompoundKind() == FormulaType::Kind) { 1992 auto SizeLeft = Left.size(); 1993 Res = std::move(Left); 1994 Res.reserve(SizeLeft + Right.size()); 1995 std::for_each(std::make_move_iterator(Right.begin()), 1996 std::make_move_iterator(Right.end()), Add); 1997 return Res; 1998 } 1999 2000 Res.reserve(Left.size() * Right.size()); 2001 for (const auto <ransform : Left) { 2002 for (const auto &RTransform : Right) { 2003 Clause Combined; 2004 Combined.reserve(LTransform.size() + RTransform.size()); 2005 llvm::append_range(Combined, LTransform); 2006 llvm::append_range(Combined, RTransform); 2007 Add(std::move(Combined)); 2008 } 2009 } 2010 return Res; 2011 } 2012 2013 void SubsumptionChecker::AddUniqueClauseToFormula(Formula &F, Clause C) { 2014 for (auto &Other : F) { 2015 if (llvm::equal(C, Other)) 2016 return; 2017 } 2018 F.push_back(C); 2019 } 2020 2021 std::optional<bool> SubsumptionChecker::Subsumes( 2022 const NamedDecl *DP, ArrayRef<AssociatedConstraint> P, const NamedDecl *DQ, 2023 ArrayRef<AssociatedConstraint> Q) { 2024 const NormalizedConstraint *PNormalized = 2025 getNormalizedAssociatedConstraints(SemaRef, DP, P); 2026 if (!PNormalized) 2027 return std::nullopt; 2028 2029 const NormalizedConstraint *QNormalized = 2030 getNormalizedAssociatedConstraints(SemaRef, DQ, Q); 2031 if (!QNormalized) 2032 return std::nullopt; 2033 2034 return Subsumes(PNormalized, QNormalized); 2035 } 2036 2037 bool SubsumptionChecker::Subsumes(const NormalizedConstraint *P, 2038 const NormalizedConstraint *Q) { 2039 2040 DNFFormula DNFP = DNF(*P); 2041 CNFFormula CNFQ = CNF(*Q); 2042 return Subsumes(DNFP, CNFQ); 2043 } 2044 2045 bool SubsumptionChecker::Subsumes(const DNFFormula &PDNF, 2046 const CNFFormula &QCNF) { 2047 for (const auto &Pi : PDNF) { 2048 for (const auto &Qj : QCNF) { 2049 // C++ [temp.constr.order] p2 2050 // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if 2051 // and only if there exists an atomic constraint Pia in Pi for which 2052 // there exists an atomic constraint, Qjb, in Qj such that Pia 2053 // subsumes Qjb. 2054 if (!DNFSubsumes(Pi, Qj)) 2055 return false; 2056 } 2057 } 2058 return true; 2059 } 2060 2061 bool SubsumptionChecker::DNFSubsumes(const Clause &P, const Clause &Q) { 2062 2063 return llvm::any_of(P, [&](Literal LP) { 2064 return llvm::any_of(Q, [this, LP](Literal LQ) { return Subsumes(LP, LQ); }); 2065 }); 2066 } 2067 2068 bool SubsumptionChecker::Subsumes(const FoldExpandedConstraint *A, 2069 const FoldExpandedConstraint *B) { 2070 std::pair<const FoldExpandedConstraint *, const FoldExpandedConstraint *> Key{ 2071 A, B}; 2072 2073 auto It = FoldSubsumptionCache.find(Key); 2074 if (It == FoldSubsumptionCache.end()) { 2075 // C++ [temp.constr.order] 2076 // a fold expanded constraint A subsumes another fold expanded 2077 // constraint B if they are compatible for subsumption, have the same 2078 // fold-operator, and the constraint of A subsumes that of B. 2079 bool DoesSubsume = 2080 A->Kind == B->Kind && 2081 FoldExpandedConstraint::AreCompatibleForSubsumption(*A, *B) && 2082 Subsumes(&A->Constraint, &B->Constraint); 2083 It = FoldSubsumptionCache.try_emplace(std::move(Key), DoesSubsume).first; 2084 } 2085 return It->second; 2086 } 2087 2088 bool SubsumptionChecker::Subsumes(Literal A, Literal B) { 2089 if (A.Kind != B.Kind) 2090 return false; 2091 switch (A.Kind) { 2092 case Literal::Atomic: 2093 if (!Callable) 2094 return A.Value == B.Value; 2095 return Callable( 2096 *static_cast<const AtomicConstraint *>(ReverseMap[A.Value]), 2097 *static_cast<const AtomicConstraint *>(ReverseMap[B.Value])); 2098 case Literal::FoldExpanded: 2099 return Subsumes( 2100 static_cast<const FoldExpandedConstraint *>(ReverseMap[A.Value]), 2101 static_cast<const FoldExpandedConstraint *>(ReverseMap[B.Value])); 2102 } 2103 llvm_unreachable("unknown literal kind"); 2104 } 2105