xref: /freebsd/contrib/llvm-project/clang/lib/AST/ASTConcept.cpp (revision 357378bbdedf24ce2b90e9bd831af4a9db3ec70a)
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/PrettyPrinter.h"
17 #include "llvm/ADT/ArrayRef.h"
18 
19 using namespace clang;
20 
21 namespace {
22 void CreatUnsatisfiedConstraintRecord(
23     const ASTContext &C, const UnsatisfiedConstraintRecord &Detail,
24     UnsatisfiedConstraintRecord *TrailingObject) {
25   if (Detail.second.is<Expr *>())
26     new (TrailingObject) UnsatisfiedConstraintRecord{
27         Detail.first,
28         UnsatisfiedConstraintRecord::second_type(Detail.second.get<Expr *>())};
29   else {
30     auto &SubstitutionDiagnostic =
31         *Detail.second.get<std::pair<SourceLocation, StringRef> *>();
32     unsigned MessageSize = SubstitutionDiagnostic.second.size();
33     char *Mem = new (C) char[MessageSize];
34     memcpy(Mem, SubstitutionDiagnostic.second.data(), MessageSize);
35     auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>(
36         SubstitutionDiagnostic.first, StringRef(Mem, MessageSize));
37     new (TrailingObject) UnsatisfiedConstraintRecord{
38         Detail.first, UnsatisfiedConstraintRecord::second_type(NewSubstDiag)};
39   }
40 }
41 } // namespace
42 
43 ASTConstraintSatisfaction::ASTConstraintSatisfaction(
44     const ASTContext &C, const ConstraintSatisfaction &Satisfaction)
45     : NumRecords{Satisfaction.Details.size()},
46       IsSatisfied{Satisfaction.IsSatisfied}, ContainsErrors{
47                                                  Satisfaction.ContainsErrors} {
48   for (unsigned I = 0; I < NumRecords; ++I)
49     CreatUnsatisfiedConstraintRecord(
50         C, Satisfaction.Details[I],
51         getTrailingObjects<UnsatisfiedConstraintRecord>() + I);
52 }
53 
54 ASTConstraintSatisfaction::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     CreatUnsatisfiedConstraintRecord(
61         C, *(Satisfaction.begin() + I),
62         getTrailingObjects<UnsatisfiedConstraintRecord>() + I);
63 }
64 
65 ASTConstraintSatisfaction *
66 ASTConstraintSatisfaction::Create(const ASTContext &C,
67                                   const ConstraintSatisfaction &Satisfaction) {
68   std::size_t size =
69       totalSizeToAlloc<UnsatisfiedConstraintRecord>(
70           Satisfaction.Details.size());
71   void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));
72   return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
73 }
74 
75 ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild(
76     const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) {
77   std::size_t size =
78       totalSizeToAlloc<UnsatisfiedConstraintRecord>(Satisfaction.NumRecords);
79   void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));
80   return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
81 }
82 
83 void ConstraintSatisfaction::Profile(
84     llvm::FoldingSetNodeID &ID, const ASTContext &C,
85     const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
86   ID.AddPointer(ConstraintOwner);
87   ID.AddInteger(TemplateArgs.size());
88   for (auto &Arg : TemplateArgs)
89     Arg.Profile(ID, C);
90 }
91 
92 ConceptReference *
93 ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
94                          SourceLocation TemplateKWLoc,
95                          DeclarationNameInfo ConceptNameInfo,
96                          NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
97                          const ASTTemplateArgumentListInfo *ArgsAsWritten) {
98   return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo,
99                                   FoundDecl, NamedConcept, ArgsAsWritten);
100 }
101 
102 void ConceptReference::print(llvm::raw_ostream &OS,
103                              const PrintingPolicy &Policy) const {
104   if (NestedNameSpec)
105     NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy);
106   ConceptName.printName(OS, Policy);
107   if (hasExplicitTemplateArgs()) {
108     OS << "<";
109     // FIXME: Find corresponding parameter for argument
110     for (auto &ArgLoc : ArgsAsWritten->arguments())
111       ArgLoc.getArgument().print(Policy, OS, /*IncludeType*/ false);
112     OS << ">";
113   }
114 }
115