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/Decl.h"
17 #include "clang/AST/TemplateBase.h"
18 #include "llvm/ADT/ArrayRef.h"
19 #include "llvm/ADT/FoldingSet.h"
20 using namespace clang;
21 
22 namespace {
23 void CreatUnsatisfiedConstraintRecord(
24     const ASTContext &C, const UnsatisfiedConstraintRecord &Detail,
25     UnsatisfiedConstraintRecord *TrailingObject) {
26   if (Detail.second.is<Expr *>())
27     new (TrailingObject) UnsatisfiedConstraintRecord{
28         Detail.first,
29         UnsatisfiedConstraintRecord::second_type(Detail.second.get<Expr *>())};
30   else {
31     auto &SubstitutionDiagnostic =
32         *Detail.second.get<std::pair<SourceLocation, StringRef> *>();
33     unsigned MessageSize = SubstitutionDiagnostic.second.size();
34     char *Mem = new (C) char[MessageSize];
35     memcpy(Mem, SubstitutionDiagnostic.second.data(), MessageSize);
36     auto *NewSubstDiag = new (C) std::pair<SourceLocation, StringRef>(
37         SubstitutionDiagnostic.first, StringRef(Mem, MessageSize));
38     new (TrailingObject) UnsatisfiedConstraintRecord{
39         Detail.first, UnsatisfiedConstraintRecord::second_type(NewSubstDiag)};
40   }
41 }
42 } // namespace
43 
44 ASTConstraintSatisfaction::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     CreatUnsatisfiedConstraintRecord(
51         C, Satisfaction.Details[I],
52         getTrailingObjects<UnsatisfiedConstraintRecord>() + I);
53 }
54 
55 ASTConstraintSatisfaction::ASTConstraintSatisfaction(
56     const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction)
57     : NumRecords{Satisfaction.NumRecords},
58       IsSatisfied{Satisfaction.IsSatisfied},
59       ContainsErrors{Satisfaction.ContainsErrors} {
60   for (unsigned I = 0; I < NumRecords; ++I)
61     CreatUnsatisfiedConstraintRecord(
62         C, *(Satisfaction.begin() + I),
63         getTrailingObjects<UnsatisfiedConstraintRecord>() + I);
64 }
65 
66 ASTConstraintSatisfaction *
67 ASTConstraintSatisfaction::Create(const ASTContext &C,
68                                   const ConstraintSatisfaction &Satisfaction) {
69   std::size_t size =
70       totalSizeToAlloc<UnsatisfiedConstraintRecord>(
71           Satisfaction.Details.size());
72   void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));
73   return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
74 }
75 
76 ASTConstraintSatisfaction *ASTConstraintSatisfaction::Rebuild(
77     const ASTContext &C, const ASTConstraintSatisfaction &Satisfaction) {
78   std::size_t size =
79       totalSizeToAlloc<UnsatisfiedConstraintRecord>(Satisfaction.NumRecords);
80   void *Mem = C.Allocate(size, alignof(ASTConstraintSatisfaction));
81   return new (Mem) ASTConstraintSatisfaction(C, Satisfaction);
82 }
83 
84 void ConstraintSatisfaction::Profile(
85     llvm::FoldingSetNodeID &ID, const ASTContext &C,
86     const NamedDecl *ConstraintOwner, ArrayRef<TemplateArgument> TemplateArgs) {
87   ID.AddPointer(ConstraintOwner);
88   ID.AddInteger(TemplateArgs.size());
89   for (auto &Arg : TemplateArgs)
90     Arg.Profile(ID, C);
91 }
92