xref: /freebsd/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp (revision 0b37c1590418417c894529d371800dfac71ef887)
1 //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
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 // This file implements the subclesses of Expr class declared in ExprCXX.h
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/ExprConcepts.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/AST/ASTConcept.h"
16 #include "clang/AST/Decl.h"
17 #include "clang/AST/DeclarationName.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/Expr.h"
20 #include "clang/AST/NestedNameSpecifier.h"
21 #include "clang/AST/TemplateBase.h"
22 #include "clang/AST/Type.h"
23 #include "clang/Basic/SourceLocation.h"
24 #include "llvm/Support/TrailingObjects.h"
25 #include <algorithm>
26 #include <utility>
27 #include <string>
28 
29 using namespace clang;
30 
31 ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C,
32     NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
33     DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
34     ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,
35     ArrayRef<TemplateArgument> ConvertedArgs,
36     const ConstraintSatisfaction *Satisfaction)
37     : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
38            /*TypeDependent=*/false,
39            // All the flags below are set in setTemplateArguments.
40            /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false,
41            /*ContainsUnexpandedParameterPacks=*/false),
42       ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
43                        NamedConcept, ArgsAsWritten),
44       NumTemplateArgs(ConvertedArgs.size()),
45       Satisfaction(Satisfaction ?
46                    ASTConstraintSatisfaction::Create(C, *Satisfaction) :
47                    nullptr) {
48   setTemplateArguments(ConvertedArgs);
49 }
50 
51 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
52     unsigned NumTemplateArgs)
53     : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
54       NumTemplateArgs(NumTemplateArgs) { }
55 
56 void ConceptSpecializationExpr::setTemplateArguments(
57     ArrayRef<TemplateArgument> Converted) {
58   assert(Converted.size() == NumTemplateArgs);
59   std::uninitialized_copy(Converted.begin(), Converted.end(),
60                           getTrailingObjects<TemplateArgument>());
61   bool IsInstantiationDependent = false;
62   bool ContainsUnexpandedParameterPack = false;
63   for (const TemplateArgument& Arg : Converted) {
64     if (Arg.isInstantiationDependent())
65       IsInstantiationDependent = true;
66     if (Arg.containsUnexpandedParameterPack())
67       ContainsUnexpandedParameterPack = true;
68     if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
69       break;
70   }
71 
72   // Currently guaranteed by the fact concepts can only be at namespace-scope.
73   assert(!NestedNameSpec ||
74          (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
75           !NestedNameSpec.getNestedNameSpecifier()
76               ->containsUnexpandedParameterPack()));
77   setInstantiationDependent(IsInstantiationDependent);
78   setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
79   assert((!isValueDependent() || isInstantiationDependent()) &&
80          "should not be value-dependent");
81 }
82 
83 ConceptSpecializationExpr *
84 ConceptSpecializationExpr::Create(const ASTContext &C,
85                                   NestedNameSpecifierLoc NNS,
86                                   SourceLocation TemplateKWLoc,
87                                   DeclarationNameInfo ConceptNameInfo,
88                                   NamedDecl *FoundDecl,
89                                   ConceptDecl *NamedConcept,
90                                const ASTTemplateArgumentListInfo *ArgsAsWritten,
91                                   ArrayRef<TemplateArgument> ConvertedArgs,
92                                   const ConstraintSatisfaction *Satisfaction) {
93   void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
94                                 ConvertedArgs.size()));
95   return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
96                                                 ConceptNameInfo, FoundDecl,
97                                                 NamedConcept, ArgsAsWritten,
98                                                 ConvertedArgs, Satisfaction);
99 }
100 
101 ConceptSpecializationExpr *
102 ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
103                                   unsigned NumTemplateArgs) {
104   void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
105                                 NumTemplateArgs));
106   return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
107 }
108 
109 const TypeConstraint *
110 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
111   assert(isTypeConstraint());
112   auto TPL =
113       TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
114   return cast<TemplateTypeParmDecl>(TPL->getParam(0))
115       ->getTypeConstraint();
116 }
117 
118 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
119                            RequiresExprBodyDecl *Body,
120                            ArrayRef<ParmVarDecl *> LocalParameters,
121                            ArrayRef<concepts::Requirement *> Requirements,
122                            SourceLocation RBraceLoc)
123   : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
124          /*TD=*/false, /*VD=*/false, /*ID=*/false,
125          /*ContainsUnexpandedParameterPack=*/false),
126     NumLocalParameters(LocalParameters.size()),
127     NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
128   RequiresExprBits.IsSatisfied = false;
129   RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
130   bool Dependent = false;
131   bool ContainsUnexpandedParameterPack = false;
132   for (ParmVarDecl *P : LocalParameters) {
133     Dependent |= P->getType()->isInstantiationDependentType();
134     ContainsUnexpandedParameterPack |=
135         P->getType()->containsUnexpandedParameterPack();
136   }
137   RequiresExprBits.IsSatisfied = true;
138   for (concepts::Requirement *R : Requirements) {
139     Dependent |= R->isDependent();
140     ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
141     if (!Dependent) {
142       RequiresExprBits.IsSatisfied = R->isSatisfied();
143       if (!RequiresExprBits.IsSatisfied)
144         break;
145     }
146   }
147   std::copy(LocalParameters.begin(), LocalParameters.end(),
148             getTrailingObjects<ParmVarDecl *>());
149   std::copy(Requirements.begin(), Requirements.end(),
150             getTrailingObjects<concepts::Requirement *>());
151   RequiresExprBits.IsSatisfied |= Dependent;
152   setValueDependent(Dependent);
153   setInstantiationDependent(Dependent);
154   setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
155 }
156 
157 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
158                            unsigned NumLocalParameters,
159                            unsigned NumRequirements)
160   : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
161     NumRequirements(NumRequirements) { }
162 
163 RequiresExpr *
164 RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
165                      RequiresExprBodyDecl *Body,
166                      ArrayRef<ParmVarDecl *> LocalParameters,
167                      ArrayRef<concepts::Requirement *> Requirements,
168                      SourceLocation RBraceLoc) {
169   void *Mem =
170       C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
171                      LocalParameters.size(), Requirements.size()),
172                  alignof(RequiresExpr));
173   return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
174                                 Requirements, RBraceLoc);
175 }
176 
177 RequiresExpr *
178 RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
179                      unsigned NumLocalParameters, unsigned NumRequirements) {
180   void *Mem =
181       C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
182                      NumLocalParameters, NumRequirements),
183                  alignof(RequiresExpr));
184   return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
185 }
186