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(dest: Mem, src: SubstitutionDiagnostic.second.data(), n: 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, Detail: Satisfaction.Details[I], |
51 | TrailingObject: 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, Detail: *(Satisfaction.begin() + I), |
62 | TrailingObject: 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 | Counts: Satisfaction.Details.size()); |
71 | void *Mem = C.Allocate(Size: size, Align: 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>(Counts: Satisfaction.NumRecords); |
79 | void *Mem = C.Allocate(Size: size, Align: 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(Ptr: ConstraintOwner); |
87 | ID.AddInteger(I: TemplateArgs.size()); |
88 | for (auto &Arg : TemplateArgs) |
89 | Arg.Profile(ID, Context: 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, Out&: OS, /*IncludeType*/ false); |
112 | OS << ">" ; |
113 | } |
114 | } |
115 | |