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 | #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 (Detail.is<Expr *>()) |
27 | new (TrailingObject) UnsatisfiedConstraintRecord(Detail.get<Expr *>()); |
28 | else { |
29 | auto &SubstitutionDiagnostic = |
30 | *Detail.get<std::pair<SourceLocation, StringRef> *>(); |
31 | StringRef Message = C.backupStr(S: 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( |
45 | C, Detail: Satisfaction.Details[I], |
46 | TrailingObject: getTrailingObjects<UnsatisfiedConstraintRecord>() + I); |
47 | } |
48 | |
49 | ASTConstraintSatisfaction::ASTConstraintSatisfaction( |
50 | const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) |
51 | : NumRecords{Satisfaction.NumRecords}, |
52 | IsSatisfied{Satisfaction.IsSatisfied}, |
53 | ContainsErrors{Satisfaction.ContainsErrors} { |
54 | for (unsigned I = 0; I < NumRecords; ++I) |
55 | CreateUnsatisfiedConstraintRecord( |
56 | C, Detail: *(Satisfaction.begin() + I), |
57 | TrailingObject: getTrailingObjects<UnsatisfiedConstraintRecord>() + I); |
58 | } |
59 | |
60 | ASTConstraintSatisfaction * |
61 | ASTConstraintSatisfaction::Create(const ASTContext &C, |
62 | const ConstraintSatisfaction &Satisfaction) { |
63 | std::size_t size = |
64 | totalSizeToAlloc<UnsatisfiedConstraintRecord>( |
65 | Counts: Satisfaction.Details.size()); |
66 | void *Mem = C.Allocate(Size: size, Align: alignof(ASTConstraintSatisfaction)); |
67 | return new (Mem) ASTConstraintSatisfaction(C, Satisfaction); |
68 | } |
69 | |
70 | ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild( |
71 | const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) { |
72 | std::size_t size = |
73 | totalSizeToAlloc<UnsatisfiedConstraintRecord>(Counts: Satisfaction.NumRecords); |
74 | void *Mem = C.Allocate(Size: size, Align: alignof(ASTConstraintSatisfaction)); |
75 | return new (Mem) ASTConstraintSatisfaction(C, Satisfaction); |
76 | } |
77 | |
78 | void ConstraintSatisfaction::Profile( |
79 | llvm::FoldingSetNodeID &ID, const ASTContext &C, |
80 | const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) { |
81 | ID.AddPointer(Ptr: ConstraintOwner); |
82 | ID.AddInteger(I: TemplateArgs.size()); |
83 | for (auto &Arg : TemplateArgs) |
84 | Arg.Profile(ID, Context: C); |
85 | } |
86 | |
87 | ConceptReference * |
88 | ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS, |
89 | SourceLocation TemplateKWLoc, |
90 | DeclarationNameInfo ConceptNameInfo, |
91 | NamedDecl *FoundDecl, ConceptDecl *NamedConcept, |
92 | const ASTTemplateArgumentListInfo *ArgsAsWritten) { |
93 | return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, |
94 | FoundDecl, NamedConcept, ArgsAsWritten); |
95 | } |
96 | |
97 | void ConceptReference::print(llvm::raw_ostream &OS, |
98 | const PrintingPolicy &Policy) const { |
99 | if (NestedNameSpec) |
100 | NestedNameSpec.getNestedNameSpecifier()->print(OS, Policy); |
101 | ConceptName.printName(OS, Policy); |
102 | if (hasExplicitTemplateArgs()) { |
103 | OS << "<" ; |
104 | llvm::ListSeparator Sep(", " ); |
105 | // FIXME: Find corresponding parameter for argument |
106 | for (auto &ArgLoc : ArgsAsWritten->arguments()) { |
107 | OS << Sep; |
108 | ArgLoc.getArgument().print(Policy, Out&: OS, /*IncludeType*/ false); |
109 | } |
110 | OS << ">" ; |
111 | } |
112 | } |
113 | |