ExprConcepts.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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. ImplicitConceptSpecializationDecl *SpecDecl,
  36. const ConstraintSatisfaction *Satisfaction)
  37. : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
  38. ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
  39. NamedConcept, ArgsAsWritten),
  40. SpecDecl(SpecDecl),
  41. Satisfaction(Satisfaction
  42. ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
  43. : nullptr) {
  44. setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
  45. // Currently guaranteed by the fact concepts can only be at namespace-scope.
  46. assert(!NestedNameSpec ||
  47. (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
  48. !NestedNameSpec.getNestedNameSpecifier()
  49. ->containsUnexpandedParameterPack()));
  50. assert((!isValueDependent() || isInstantiationDependent()) &&
  51. "should not be value-dependent");
  52. }
  53. ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
  54. : Expr(ConceptSpecializationExprClass, Empty) {}
  55. ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
  56. const ASTContext &C, NestedNameSpecifierLoc NNS,
  57. SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
  58. NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
  59. const ASTTemplateArgumentListInfo *ArgsAsWritten,
  60. ImplicitConceptSpecializationDecl *SpecDecl,
  61. const ConstraintSatisfaction *Satisfaction) {
  62. return new (C) ConceptSpecializationExpr(
  63. C, NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
  64. ArgsAsWritten, SpecDecl, Satisfaction);
  65. }
  66. ConceptSpecializationExpr::ConceptSpecializationExpr(
  67. const ASTContext &C, ConceptDecl *NamedConcept,
  68. ImplicitConceptSpecializationDecl *SpecDecl,
  69. const ConstraintSatisfaction *Satisfaction, bool Dependent,
  70. bool ContainsUnexpandedParameterPack)
  71. : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
  72. ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
  73. DeclarationNameInfo(), NamedConcept, NamedConcept,
  74. nullptr),
  75. SpecDecl(SpecDecl),
  76. Satisfaction(Satisfaction
  77. ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
  78. : nullptr) {
  79. ExprDependence D = ExprDependence::None;
  80. if (!Satisfaction)
  81. D |= ExprDependence::Value;
  82. if (Dependent)
  83. D |= ExprDependence::Instantiation;
  84. if (ContainsUnexpandedParameterPack)
  85. D |= ExprDependence::UnexpandedPack;
  86. setDependence(D);
  87. }
  88. ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
  89. const ASTContext &C, ConceptDecl *NamedConcept,
  90. ImplicitConceptSpecializationDecl *SpecDecl,
  91. const ConstraintSatisfaction *Satisfaction, bool Dependent,
  92. bool ContainsUnexpandedParameterPack) {
  93. return new (C)
  94. ConceptSpecializationExpr(C, NamedConcept, SpecDecl, Satisfaction,
  95. Dependent, ContainsUnexpandedParameterPack);
  96. }
  97. const TypeConstraint *
  98. concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
  99. assert(isTypeConstraint());
  100. auto TPL =
  101. TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
  102. return cast<TemplateTypeParmDecl>(TPL->getParam(0))
  103. ->getTypeConstraint();
  104. }
  105. RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
  106. RequiresExprBodyDecl *Body,
  107. ArrayRef<ParmVarDecl *> LocalParameters,
  108. ArrayRef<concepts::Requirement *> Requirements,
  109. SourceLocation RBraceLoc)
  110. : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
  111. NumLocalParameters(LocalParameters.size()),
  112. NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
  113. RequiresExprBits.IsSatisfied = false;
  114. RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
  115. bool Dependent = false;
  116. bool ContainsUnexpandedParameterPack = false;
  117. for (ParmVarDecl *P : LocalParameters) {
  118. Dependent |= P->getType()->isInstantiationDependentType();
  119. ContainsUnexpandedParameterPack |=
  120. P->getType()->containsUnexpandedParameterPack();
  121. }
  122. RequiresExprBits.IsSatisfied = true;
  123. for (concepts::Requirement *R : Requirements) {
  124. Dependent |= R->isDependent();
  125. ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
  126. if (!Dependent) {
  127. RequiresExprBits.IsSatisfied = R->isSatisfied();
  128. if (!RequiresExprBits.IsSatisfied)
  129. break;
  130. }
  131. }
  132. std::copy(LocalParameters.begin(), LocalParameters.end(),
  133. getTrailingObjects<ParmVarDecl *>());
  134. std::copy(Requirements.begin(), Requirements.end(),
  135. getTrailingObjects<concepts::Requirement *>());
  136. RequiresExprBits.IsSatisfied |= Dependent;
  137. // FIXME: move the computing dependency logic to ComputeDependence.h
  138. if (ContainsUnexpandedParameterPack)
  139. setDependence(getDependence() | ExprDependence::UnexpandedPack);
  140. // FIXME: this is incorrect for cases where we have a non-dependent
  141. // requirement, but its parameters are instantiation-dependent. RequiresExpr
  142. // should be instantiation-dependent if it has instantiation-dependent
  143. // parameters.
  144. if (Dependent)
  145. setDependence(getDependence() | ExprDependence::ValueInstantiation);
  146. }
  147. RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
  148. unsigned NumLocalParameters,
  149. unsigned NumRequirements)
  150. : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
  151. NumRequirements(NumRequirements) { }
  152. RequiresExpr *
  153. RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
  154. RequiresExprBodyDecl *Body,
  155. ArrayRef<ParmVarDecl *> LocalParameters,
  156. ArrayRef<concepts::Requirement *> Requirements,
  157. SourceLocation RBraceLoc) {
  158. void *Mem =
  159. C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
  160. LocalParameters.size(), Requirements.size()),
  161. alignof(RequiresExpr));
  162. return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
  163. Requirements, RBraceLoc);
  164. }
  165. RequiresExpr *
  166. RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
  167. unsigned NumLocalParameters, unsigned NumRequirements) {
  168. void *Mem =
  169. C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
  170. NumLocalParameters, NumRequirements),
  171. alignof(RequiresExpr));
  172. return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
  173. }