brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · fd12bc4 Raw
199 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// \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/NestedNameSpecifier.h"18#include "clang/AST/PrettyPrinter.h"19#include "llvm/ADT/StringExtras.h"20 21using namespace clang;22 23static void24CreateUnsatisfiedConstraintRecord(const ASTContext &C,25                                  const UnsatisfiedConstraintRecord &Detail,26                                  UnsatisfiedConstraintRecord *TrailingObject) {27  if (Detail.isNull())28    new (TrailingObject) UnsatisfiedConstraintRecord(nullptr);29  else if (const auto *E = llvm::dyn_cast<const Expr *>(Detail))30    new (TrailingObject) UnsatisfiedConstraintRecord(E);31  else if (const auto *Concept =32               llvm::dyn_cast<const ConceptReference *>(Detail))33    new (TrailingObject) UnsatisfiedConstraintRecord(Concept);34  else {35    auto &SubstitutionDiagnostic =36        *cast<const clang::ConstraintSubstitutionDiagnostic *>(Detail);37    StringRef Message = C.backupStr(SubstitutionDiagnostic.second);38    auto *NewSubstDiag = new (C) clang::ConstraintSubstitutionDiagnostic(39        SubstitutionDiagnostic.first, Message);40    new (TrailingObject) UnsatisfiedConstraintRecord(NewSubstDiag);41  }42}43 44ASTConstraintSatisfaction::ASTConstraintSatisfaction(45    const ASTContext &C, const ConstraintSatisfaction &Satisfaction)46    : NumRecords{Satisfaction.Details.size()},47      IsSatisfied{Satisfaction.IsSatisfied}, ContainsErrors{48                                                 Satisfaction.ContainsErrors} {49  for (unsigned I = 0; I < NumRecords; ++I)50    CreateUnsatisfiedConstraintRecord(C, Satisfaction.Details[I],51                                      getTrailingObjects() + I);52}53 54ASTConstraintSatisfaction::ASTConstraintSatisfaction(55    const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction)56    : NumRecords{Satisfaction.NumRecords},57      IsSatisfied{Satisfaction.IsSatisfied},58      ContainsErrors{Satisfaction.ContainsErrors} {59  for (unsigned I = 0; I < NumRecords; ++I)60    CreateUnsatisfiedConstraintRecord(C, *(Satisfaction.begin() + I),61                                      getTrailingObjects() + I);62}63 64ASTConstraintSatisfaction *65ASTConstraintSatisfaction::Create(const ASTContext &C,66                                  const ConstraintSatisfaction &Satisfaction) {67  std::size_t size =68      totalSizeToAlloc<UnsatisfiedConstraintRecord>(69          Satisfaction.Details.size());70  void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));71  return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);72}73 74ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild(75    const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) {76  std::size_t size =77      totalSizeToAlloc<UnsatisfiedConstraintRecord>(Satisfaction.NumRecords);78  void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));79  return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);80}81 82void ConstraintSatisfaction::Profile(llvm::FoldingSetNodeID &ID,83                                     const ASTContext &C,84                                     const NamedDecl *ConstraintOwner,85                                     ArrayRef<TemplateArgument> TemplateArgs) {86  ID.AddPointer(ConstraintOwner);87  ID.AddInteger(TemplateArgs.size());88  for (auto &Arg : TemplateArgs)89    Arg.Profile(ID, C);90}91 92ConceptReference *93ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS,94                         SourceLocation TemplateKWLoc,95                         DeclarationNameInfo ConceptNameInfo,96                         NamedDecl *FoundDecl, TemplateDecl *NamedConcept,97                         const ASTTemplateArgumentListInfo *ArgsAsWritten) {98  return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo,99                                  FoundDecl, NamedConcept, ArgsAsWritten);100}101 102SourceLocation ConceptReference::getBeginLoc() const {103  // Note that if the qualifier is null the template KW must also be null.104  if (auto QualifierLoc = getNestedNameSpecifierLoc())105    return QualifierLoc.getBeginLoc();106  return getConceptNameInfo().getBeginLoc();107}108 109void ConceptReference::print(llvm::raw_ostream &OS,110                             const PrintingPolicy &Policy) const {111  NestedNameSpec.getNestedNameSpecifier().print(OS, Policy);112  ConceptName.printName(OS, Policy);113  if (hasExplicitTemplateArgs()) {114    OS << "<";115    llvm::ListSeparator Sep(", ");116    // FIXME: Find corresponding parameter for argument117    for (auto &ArgLoc : ArgsAsWritten->arguments()) {118      OS << Sep;119      ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false);120    }121    OS << ">";122  }123}124 125const StreamingDiagnostic &clang::operator<<(const StreamingDiagnostic &DB,126                                             const ConceptReference *C) {127  std::string NameStr;128  llvm::raw_string_ostream OS(NameStr);129  LangOptions LO;130  LO.CPlusPlus = true;131  LO.Bool = true;132  OS << '\'';133  C->print(OS, PrintingPolicy(LO));134  OS << '\'';135  return DB << NameStr;136}137 138concepts::ExprRequirement::ExprRequirement(139    Expr *E, bool IsSimple, SourceLocation NoexceptLoc,140    ReturnTypeRequirement Req, SatisfactionStatus Status,141    ConceptSpecializationExpr *SubstitutedConstraintExpr)142    : Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent,143                  Status == SS_Dependent &&144                      (E->containsUnexpandedParameterPack() ||145                       Req.containsUnexpandedParameterPack()),146                  Status == SS_Satisfied),147      Value(E), NoexceptLoc(NoexceptLoc), TypeReq(Req),148      SubstitutedConstraintExpr(SubstitutedConstraintExpr), Status(Status) {149  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&150         "Simple requirement must not have a return type requirement or a "151         "noexcept specification");152  assert((Status > SS_TypeRequirementSubstitutionFailure &&153          Req.isTypeConstraint()) == (SubstitutedConstraintExpr != nullptr));154}155 156concepts::ExprRequirement::ExprRequirement(157    SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple,158    SourceLocation NoexceptLoc, ReturnTypeRequirement Req)159    : Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(),160                  Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false),161      Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req),162      Status(SS_ExprSubstitutionFailure) {163  assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) &&164         "Simple requirement must not have a return type requirement or a "165         "noexcept specification");166}167 168concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement(169    TemplateParameterList *TPL)170    : TypeConstraintInfo(TPL, false) {171  assert(TPL->size() == 1);172  const TypeConstraint *TC =173      cast<TemplateTypeParmDecl>(TPL->getParam(0))->getTypeConstraint();174  assert(TC &&175         "TPL must have a template type parameter with a type constraint");176  auto *Constraint =177      cast<ConceptSpecializationExpr>(TC->getImmediatelyDeclaredConstraint());178  bool Dependent =179      Constraint->getTemplateArgsAsWritten() &&180      TemplateSpecializationType::anyInstantiationDependentTemplateArguments(181          Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1));182  TypeConstraintInfo.setInt(Dependent ? true : false);183}184 185concepts::ExprRequirement::ReturnTypeRequirement::ReturnTypeRequirement(186    TemplateParameterList *TPL, bool IsDependent)187    : TypeConstraintInfo(TPL, IsDependent) {}188 189concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T)190    : Requirement(RK_Type, T->getType()->isInstantiationDependentType(),191                  T->getType()->containsUnexpandedParameterPack(),192                  // We reach this ctor with either dependent types (in which193                  // IsSatisfied doesn't matter) or with non-dependent type in194                  // which the existence of the type indicates satisfaction.195                  /*IsSatisfied=*/true),196      Value(T),197      Status(T->getType()->isInstantiationDependentType() ? SS_Dependent198                                                          : SS_Satisfied) {}199