ExprConcepts.cpp 9.5 KB

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