1 //===--- ASTConcept.cpp - Concepts Related AST Data Structures --*- C++ -*-===// 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 /// \file 10 /// \brief This file defines AST data structures related to concepts. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ASTConcept.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/ExprConcepts.h" 17 #include "clang/AST/PrettyPrinter.h" 18 #include "llvm/ADT/StringExtras.h" 19 20 using namespace clang; 21 22 static void 23 CreateUnsatisfiedConstraintRecord(const ASTContext &C, 24 const UnsatisfiedConstraintRecord &Detail, 25 UnsatisfiedConstraintRecord *TrailingObject) { 26 if (auto *E = dyn_cast<Expr *>(Detail)) 27 new (TrailingObject) UnsatisfiedConstraintRecord(E); 28 else { 29 auto &SubstitutionDiagnostic = 30 *cast<std::pair<SourceLocation, StringRef> *>(Detail); 31 StringRef Message = C.backupStr(SubstitutionDiagnostic.second); 32 auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>( 33 SubstitutionDiagnostic.first, Message); 34 new (TrailingObject) UnsatisfiedConstraintRecord(NewSubstDiag); 35 } 36 } 37 38 ASTConstraintSatisfaction::ASTConstraintSatisfaction( 39 const ASTContext &C, const ConstraintSatisfaction &Satisfaction) 40 : NumRecords{Satisfaction.Details.size()}, 41 IsSatisfied{Satisfaction.IsSatisfied}, ContainsErrors{ 42 Satisfaction.ContainsErrors} { 43 for (unsigned I = 0; I < NumRecords; ++I) 44 CreateUnsatisfiedConstraintRecord(C, Satisfaction.Details[I], 45 getTrailingObjects() + I); 46 } 47 48 ASTConstraintSatisfaction::ASTConstraintSatisfaction( 49 const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) 50 : NumRecords{Satisfaction.NumRecords}, 51 IsSatisfied{Satisfaction.IsSatisfied}, 52 ContainsErrors{Satisfaction.ContainsErrors} { 53 for (unsigned I = 0; I < NumRecords; ++I) 54 CreateUnsatisfiedConstraintRecord(C, *(Satisfaction.begin() + I), 55 getTrailingObjects() + I); 56 } 57 58 ASTConstraintSatisfaction * 59 ASTConstraintSatisfaction::Create(const ASTContext &C, 60 const ConstraintSatisfaction &Satisfaction) { 61 std::size_t size = 62 totalSizeToAlloc<UnsatisfiedConstraintRecord>( 63 Satisfaction.Details.size()); 64 void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction)); 65 return new (Mem) ASTConstraintSatisfaction(C, Satisfaction); 66 } 67 68 ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild( 69 const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) { 70 std::size_t size = 71 totalSizeToAlloc<UnsatisfiedConstraintRecord>(Satisfaction.NumRecords); 72 void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction)); 73 return new (Mem) ASTConstraintSatisfaction(C, Satisfaction); 74 } 75 76 void ConstraintSatisfaction::Profile( 77 llvm::FoldingSetNodeID &ID, const ASTContext &C, 78 const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) { 79 ID.AddPointer(ConstraintOwner); 80 ID.AddInteger(TemplateArgs.size()); 81 for (auto &Arg : TemplateArgs) 82 Arg.Profile(ID, C); 83 } 84 85 ConceptReference * 86 ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS, 87 SourceLocation TemplateKWLoc, 88 DeclarationNameInfo ConceptNameInfo, 89 NamedDecl *FoundDecl, ConceptDecl *NamedConcept, 90 const ASTTemplateArgumentListInfo *ArgsAsWritten) { 91 return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, 92 FoundDecl, NamedConcept, ArgsAsWritten); 93 } 94 95 void ConceptReference::print(llvm::raw_ostream &OS, 96 const PrintingPolicy &Policy) const { 97 if (NestedNameSpec) 98 NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); 99 ConceptName.printName(OS, Policy); 100 if (hasExplicitTemplateArgs()) { 101 OS << "<"; 102 llvm::ListSeparator Sep(", "); 103 // FIXME: Find corresponding parameter for argument 104 for (auto &ArgLoc : ArgsAsWritten->arguments()) { 105 OS << Sep; 106 ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false); 107 } 108 OS << ">"; 109 } 110 } 111 112 concepts::ExprRequirement::ExprRequirement( 113 Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 114 ReturnTypeRequirement Req, SatisfactionStatus Status, 115 ConceptSpecializationExpr *SubstitutedConstraintExpr) 116 : Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, 117 Status == SS_Dependent && 118 (E->containsUnexpandedParameterPack() || 119 Req.containsUnexpandedParameterPack()), 120 Status == SS_Satisfied), 121 Value(E), NoexceptLoc(NoexceptLoc), TypeReq(Req), 122 SubstitutedConstraintExpr(SubstitutedConstraintExpr), Status(Status) { 123 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 124 "Simple requirement must not have a return type requirement or a " 125 "noexcept specification"); 126 assert((Status > SS_TypeRequirementSubstitutionFailure && 127 Req.isTypeConstraint()) == (SubstitutedConstraintExpr != nullptr)); 128 } 129 130 concepts::ExprRequirement::ExprRequirement( 131 SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, 132 SourceLocation NoexceptLoc, ReturnTypeRequirement Req) 133 : Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), 134 Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), 135 Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), 136 Status(SS_ExprSubstitutionFailure) { 137 assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && 138 "Simple requirement must not have a return type requirement or a " 139 "noexcept specification"); 140 } 141 142 concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement( 143 TemplateParameterList *TPL) 144 : TypeConstraintInfo(TPL, false) { 145 assert(TPL->size() == 1); 146 const TypeConstraint *TC = 147 cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint(); 148 assert(TC && 149 "TPL must have a template type parameter with a type constraint"); 150 auto *Constraint = 151 cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint()); 152 bool Dependent = 153 Constraint->getTemplateArgsAsWritten() && 154 TemplateSpecializationType::anyInstantiationDependentTemplateArguments( 155 Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)); 156 TypeConstraintInfo.setInt(Dependent ? true : false); 157 } 158 159 concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement( 160 TemplateParameterList *TPL, bool IsDependent) 161 : TypeConstraintInfo(TPL, IsDependent) {} 162 163 concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) 164 : Requirement(RK_Type, T->getType()->isInstantiationDependentType(), 165 T->getType()->containsUnexpandedParameterPack(), 166 // We reach this ctor with either dependent types (in which 167 // IsSatisfied doesn't matter) or with non-dependent type in 168 // which the existence of the type indicates satisfaction. 169 /*IsSatisfied=*/true), 170 Value(T), 171 Status(T->getType()->isInstantiationDependentType() ? SS_Dependent 172 : SS_Satisfied) {} 173