xref: /openbsd-src/gnu/llvm/clang/lib/AST/ExprConcepts.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the subclesses of Expr class declared in ExprCXX.h
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick 
13e5dd7070Spatrick #include "clang/AST/ExprConcepts.h"
14e5dd7070Spatrick #include "clang/AST/ASTConcept.h"
15ec727ea7Spatrick #include "clang/AST/ASTContext.h"
16ec727ea7Spatrick #include "clang/AST/ComputeDependence.h"
17e5dd7070Spatrick #include "clang/AST/Decl.h"
18e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
19ec727ea7Spatrick #include "clang/AST/DeclarationName.h"
20ec727ea7Spatrick #include "clang/AST/DependenceFlags.h"
21e5dd7070Spatrick #include "clang/AST/Expr.h"
22e5dd7070Spatrick #include "clang/AST/NestedNameSpecifier.h"
23e5dd7070Spatrick #include "clang/AST/TemplateBase.h"
24e5dd7070Spatrick #include "clang/AST/Type.h"
25e5dd7070Spatrick #include "clang/Basic/SourceLocation.h"
26e5dd7070Spatrick #include "llvm/Support/TrailingObjects.h"
27e5dd7070Spatrick #include <algorithm>
28e5dd7070Spatrick #include <string>
29ec727ea7Spatrick #include <utility>
30e5dd7070Spatrick 
31e5dd7070Spatrick using namespace clang;
32e5dd7070Spatrick 
ConceptSpecializationExpr(const ASTContext & C,NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction)33ec727ea7Spatrick ConceptSpecializationExpr::ConceptSpecializationExpr(
34ec727ea7Spatrick     const ASTContext &C, NestedNameSpecifierLoc NNS,
35ec727ea7Spatrick     SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
36ec727ea7Spatrick     NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
37ec727ea7Spatrick     const ASTTemplateArgumentListInfo *ArgsAsWritten,
38*12c85518Srobert     ImplicitConceptSpecializationDecl *SpecDecl,
39e5dd7070Spatrick     const ConstraintSatisfaction *Satisfaction)
40a9ac8606Spatrick     : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
41e5dd7070Spatrick       ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
42e5dd7070Spatrick                        NamedConcept, ArgsAsWritten),
43*12c85518Srobert       SpecDecl(SpecDecl),
44ec727ea7Spatrick       Satisfaction(Satisfaction
45ec727ea7Spatrick                        ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
46ec727ea7Spatrick                        : nullptr) {
47ec727ea7Spatrick   setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
48e5dd7070Spatrick 
49e5dd7070Spatrick   // Currently guaranteed by the fact concepts can only be at namespace-scope.
50e5dd7070Spatrick   assert(!NestedNameSpec ||
51e5dd7070Spatrick          (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
52e5dd7070Spatrick           !NestedNameSpec.getNestedNameSpecifier()
53e5dd7070Spatrick               ->containsUnexpandedParameterPack()));
54e5dd7070Spatrick   assert((!isValueDependent() || isInstantiationDependent()) &&
55e5dd7070Spatrick          "should not be value-dependent");
56e5dd7070Spatrick }
57e5dd7070Spatrick 
ConceptSpecializationExpr(EmptyShell Empty)58*12c85518Srobert ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
59*12c85518Srobert     : Expr(ConceptSpecializationExprClass, Empty) {}
60e5dd7070Spatrick 
Create(const ASTContext & C,ConceptDecl * NamedConcept,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)61*12c85518Srobert ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
62*12c85518Srobert     const ASTContext &C, ConceptDecl *NamedConcept,
63*12c85518Srobert     ImplicitConceptSpecializationDecl *SpecDecl,
64*12c85518Srobert     const ConstraintSatisfaction *Satisfaction, bool Dependent,
65*12c85518Srobert     bool ContainsUnexpandedParameterPack) {
66*12c85518Srobert   return Create(C, NamedConcept, /*ArgsAsWritten*/ nullptr, SpecDecl, Satisfaction,
67*12c85518Srobert                 Dependent, ContainsUnexpandedParameterPack);
68e5dd7070Spatrick }
69e5dd7070Spatrick 
Create(const ASTContext & C,NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction)70*12c85518Srobert ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
71*12c85518Srobert     const ASTContext &C, NestedNameSpecifierLoc NNS,
72*12c85518Srobert     SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
73*12c85518Srobert     NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
74e5dd7070Spatrick     const ASTTemplateArgumentListInfo *ArgsAsWritten,
75*12c85518Srobert     ImplicitConceptSpecializationDecl *SpecDecl,
76e5dd7070Spatrick     const ConstraintSatisfaction *Satisfaction) {
77*12c85518Srobert   return new (C) ConceptSpecializationExpr(
78*12c85518Srobert       C, NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
79*12c85518Srobert       ArgsAsWritten, SpecDecl, Satisfaction);
80e5dd7070Spatrick }
81e5dd7070Spatrick 
ConceptSpecializationExpr(const ASTContext & C,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)82e5dd7070Spatrick ConceptSpecializationExpr::ConceptSpecializationExpr(
83e5dd7070Spatrick     const ASTContext &C, ConceptDecl *NamedConcept,
84*12c85518Srobert     const ASTTemplateArgumentListInfo *ArgsAsWritten,
85*12c85518Srobert     ImplicitConceptSpecializationDecl *SpecDecl,
86e5dd7070Spatrick     const ConstraintSatisfaction *Satisfaction, bool Dependent,
87e5dd7070Spatrick     bool ContainsUnexpandedParameterPack)
88a9ac8606Spatrick     : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
89e5dd7070Spatrick       ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
90ec727ea7Spatrick                        DeclarationNameInfo(), NamedConcept, NamedConcept,
91*12c85518Srobert                        ArgsAsWritten),
92*12c85518Srobert       SpecDecl(SpecDecl),
93ec727ea7Spatrick       Satisfaction(Satisfaction
94ec727ea7Spatrick                        ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
95ec727ea7Spatrick                        : nullptr) {
96ec727ea7Spatrick   ExprDependence D = ExprDependence::None;
97ec727ea7Spatrick   if (!Satisfaction)
98ec727ea7Spatrick     D |= ExprDependence::Value;
99ec727ea7Spatrick   if (Dependent)
100ec727ea7Spatrick     D |= ExprDependence::Instantiation;
101ec727ea7Spatrick   if (ContainsUnexpandedParameterPack)
102ec727ea7Spatrick     D |= ExprDependence::UnexpandedPack;
103ec727ea7Spatrick   setDependence(D);
104e5dd7070Spatrick }
105e5dd7070Spatrick 
Create(const ASTContext & C,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)106*12c85518Srobert ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
107*12c85518Srobert     const ASTContext &C, ConceptDecl *NamedConcept,
108*12c85518Srobert     const ASTTemplateArgumentListInfo *ArgsAsWritten,
109*12c85518Srobert     ImplicitConceptSpecializationDecl *SpecDecl,
110*12c85518Srobert     const ConstraintSatisfaction *Satisfaction, bool Dependent,
111e5dd7070Spatrick     bool ContainsUnexpandedParameterPack) {
112*12c85518Srobert   return new (C) ConceptSpecializationExpr(C, NamedConcept, ArgsAsWritten,
113*12c85518Srobert                                            SpecDecl, Satisfaction, Dependent,
114e5dd7070Spatrick                                            ContainsUnexpandedParameterPack);
115e5dd7070Spatrick }
116e5dd7070Spatrick 
117e5dd7070Spatrick const TypeConstraint *
getTypeConstraint() const118e5dd7070Spatrick concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
119e5dd7070Spatrick   assert(isTypeConstraint());
120e5dd7070Spatrick   auto TPL =
121e5dd7070Spatrick       TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
122e5dd7070Spatrick   return cast<TemplateTypeParmDecl>(TPL->getParam(0))
123e5dd7070Spatrick       ->getTypeConstraint();
124e5dd7070Spatrick }
125e5dd7070Spatrick 
RequiresExpr(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,ArrayRef<ParmVarDecl * > LocalParameters,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)126e5dd7070Spatrick RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
127e5dd7070Spatrick                            RequiresExprBodyDecl *Body,
128e5dd7070Spatrick                            ArrayRef<ParmVarDecl *> LocalParameters,
129e5dd7070Spatrick                            ArrayRef<concepts::Requirement *> Requirements,
130e5dd7070Spatrick                            SourceLocation RBraceLoc)
131a9ac8606Spatrick     : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
132e5dd7070Spatrick       NumLocalParameters(LocalParameters.size()),
133e5dd7070Spatrick       NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
134e5dd7070Spatrick   RequiresExprBits.IsSatisfied = false;
135e5dd7070Spatrick   RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
136e5dd7070Spatrick   bool Dependent = false;
137e5dd7070Spatrick   bool ContainsUnexpandedParameterPack = false;
138e5dd7070Spatrick   for (ParmVarDecl *P : LocalParameters) {
139e5dd7070Spatrick     Dependent |= P->getType()->isInstantiationDependentType();
140e5dd7070Spatrick     ContainsUnexpandedParameterPack |=
141e5dd7070Spatrick         P->getType()->containsUnexpandedParameterPack();
142e5dd7070Spatrick   }
143e5dd7070Spatrick   RequiresExprBits.IsSatisfied = true;
144e5dd7070Spatrick   for (concepts::Requirement *R : Requirements) {
145e5dd7070Spatrick     Dependent |= R->isDependent();
146e5dd7070Spatrick     ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
147e5dd7070Spatrick     if (!Dependent) {
148e5dd7070Spatrick       RequiresExprBits.IsSatisfied = R->isSatisfied();
149e5dd7070Spatrick       if (!RequiresExprBits.IsSatisfied)
150e5dd7070Spatrick         break;
151e5dd7070Spatrick     }
152e5dd7070Spatrick   }
153e5dd7070Spatrick   std::copy(LocalParameters.begin(), LocalParameters.end(),
154e5dd7070Spatrick             getTrailingObjects<ParmVarDecl *>());
155e5dd7070Spatrick   std::copy(Requirements.begin(), Requirements.end(),
156e5dd7070Spatrick             getTrailingObjects<concepts::Requirement *>());
157e5dd7070Spatrick   RequiresExprBits.IsSatisfied |= Dependent;
158ec727ea7Spatrick   // FIXME: move the computing dependency logic to ComputeDependence.h
159ec727ea7Spatrick   if (ContainsUnexpandedParameterPack)
160ec727ea7Spatrick     setDependence(getDependence() | ExprDependence::UnexpandedPack);
161ec727ea7Spatrick   // FIXME: this is incorrect for cases where we have a non-dependent
162ec727ea7Spatrick   // requirement, but its parameters are instantiation-dependent. RequiresExpr
163ec727ea7Spatrick   // should be instantiation-dependent if it has instantiation-dependent
164ec727ea7Spatrick   // parameters.
165ec727ea7Spatrick   if (Dependent)
166ec727ea7Spatrick     setDependence(getDependence() | ExprDependence::ValueInstantiation);
167e5dd7070Spatrick }
168e5dd7070Spatrick 
RequiresExpr(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)169e5dd7070Spatrick RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
170e5dd7070Spatrick                            unsigned NumLocalParameters,
171e5dd7070Spatrick                            unsigned NumRequirements)
172e5dd7070Spatrick   : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
173e5dd7070Spatrick     NumRequirements(NumRequirements) { }
174e5dd7070Spatrick 
175e5dd7070Spatrick RequiresExpr *
Create(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,ArrayRef<ParmVarDecl * > LocalParameters,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)176e5dd7070Spatrick RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
177e5dd7070Spatrick                      RequiresExprBodyDecl *Body,
178e5dd7070Spatrick                      ArrayRef<ParmVarDecl *> LocalParameters,
179e5dd7070Spatrick                      ArrayRef<concepts::Requirement *> Requirements,
180e5dd7070Spatrick                      SourceLocation RBraceLoc) {
181e5dd7070Spatrick   void *Mem =
182e5dd7070Spatrick       C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
183e5dd7070Spatrick                      LocalParameters.size(), Requirements.size()),
184e5dd7070Spatrick                  alignof(RequiresExpr));
185e5dd7070Spatrick   return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
186e5dd7070Spatrick                                 Requirements, RBraceLoc);
187e5dd7070Spatrick }
188e5dd7070Spatrick 
189e5dd7070Spatrick RequiresExpr *
Create(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)190e5dd7070Spatrick RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
191e5dd7070Spatrick                      unsigned NumLocalParameters, unsigned NumRequirements) {
192e5dd7070Spatrick   void *Mem =
193e5dd7070Spatrick       C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
194e5dd7070Spatrick                      NumLocalParameters, NumRequirements),
195e5dd7070Spatrick                  alignof(RequiresExpr));
196e5dd7070Spatrick   return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
197e5dd7070Spatrick }
198