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