[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / clang / lib / AST / ExprConcepts.cpp
blob0704630c0fc266400e2f432db5b7eab2a06aa2f0
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
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/ExprConcepts.h"
14 #include "clang/AST/ASTConcept.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/ComputeDependence.h"
17 #include "clang/AST/Decl.h"
18 #include "clang/AST/DeclTemplate.h"
19 #include "clang/AST/DeclarationName.h"
20 #include "clang/AST/DependenceFlags.h"
21 #include "clang/AST/Expr.h"
22 #include "clang/AST/NestedNameSpecifier.h"
23 #include "clang/AST/TemplateBase.h"
24 #include "clang/AST/Type.h"
25 #include "clang/Basic/SourceLocation.h"
26 #include "llvm/Support/TrailingObjects.h"
27 #include <algorithm>
28 #include <string>
29 #include <utility>
31 using namespace clang;
33 ConceptSpecializationExpr::ConceptSpecializationExpr(
34 const ASTContext &C, ConceptReference *Loc,
35 ImplicitConceptSpecializationDecl *SpecDecl,
36 const ConstraintSatisfaction *Satisfaction)
37 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
38 ConceptRef(Loc), SpecDecl(SpecDecl),
39 Satisfaction(Satisfaction
40 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
41 : nullptr) {
42 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
44 // Currently guaranteed by the fact concepts can only be at namespace-scope.
45 assert(!Loc->getNestedNameSpecifierLoc() ||
46 (!Loc->getNestedNameSpecifierLoc()
47 .getNestedNameSpecifier()
48 ->isInstantiationDependent() &&
49 !Loc->getNestedNameSpecifierLoc()
50 .getNestedNameSpecifier()
51 ->containsUnexpandedParameterPack()));
52 assert((!isValueDependent() || isInstantiationDependent()) &&
53 "should not be value-dependent");
56 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
57 : Expr(ConceptSpecializationExprClass, Empty) {}
59 ConceptSpecializationExpr *
60 ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
61 ImplicitConceptSpecializationDecl *SpecDecl,
62 const ConstraintSatisfaction *Satisfaction) {
63 return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);
66 ConceptSpecializationExpr::ConceptSpecializationExpr(
67 const ASTContext &C, ConceptReference *Loc,
68 ImplicitConceptSpecializationDecl *SpecDecl,
69 const ConstraintSatisfaction *Satisfaction, bool Dependent,
70 bool ContainsUnexpandedParameterPack)
71 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
72 ConceptRef(Loc), SpecDecl(SpecDecl),
73 Satisfaction(Satisfaction
74 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
75 : nullptr) {
76 ExprDependence D = ExprDependence::None;
77 if (!Satisfaction)
78 D |= ExprDependence::Value;
79 if (Dependent)
80 D |= ExprDependence::Instantiation;
81 if (ContainsUnexpandedParameterPack)
82 D |= ExprDependence::UnexpandedPack;
83 setDependence(D);
86 ConceptSpecializationExpr *
87 ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
88 ImplicitConceptSpecializationDecl *SpecDecl,
89 const ConstraintSatisfaction *Satisfaction,
90 bool Dependent,
91 bool ContainsUnexpandedParameterPack) {
92 return new (C)
93 ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,
94 ContainsUnexpandedParameterPack);
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();
106 // Search through the requirements, and see if any have a RecoveryExpr in it,
107 // which means this RequiresExpr ALSO needs to be invalid.
108 static bool RequirementContainsError(concepts::Requirement *R) {
109 if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))
110 return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();
112 if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))
113 return !NestedReq->hasInvalidConstraint() &&
114 NestedReq->getConstraintExpr() &&
115 NestedReq->getConstraintExpr()->containsErrors();
116 return false;
119 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
120 RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
121 ArrayRef<ParmVarDecl *> LocalParameters,
122 SourceLocation RParenLoc,
123 ArrayRef<concepts::Requirement *> Requirements,
124 SourceLocation RBraceLoc)
125 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
126 NumLocalParameters(LocalParameters.size()),
127 NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),
128 RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {
129 RequiresExprBits.IsSatisfied = false;
130 RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
131 bool Dependent = false;
132 bool ContainsUnexpandedParameterPack = false;
133 for (ParmVarDecl *P : LocalParameters) {
134 Dependent |= P->getType()->isInstantiationDependentType();
135 ContainsUnexpandedParameterPack |=
136 P->getType()->containsUnexpandedParameterPack();
138 RequiresExprBits.IsSatisfied = true;
139 for (concepts::Requirement *R : Requirements) {
140 Dependent |= R->isDependent();
141 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
142 if (!Dependent) {
143 RequiresExprBits.IsSatisfied = R->isSatisfied();
144 if (!RequiresExprBits.IsSatisfied)
145 break;
148 if (RequirementContainsError(R))
149 setDependence(getDependence() | ExprDependence::Error);
151 std::copy(LocalParameters.begin(), LocalParameters.end(),
152 getTrailingObjects<ParmVarDecl *>());
153 std::copy(Requirements.begin(), Requirements.end(),
154 getTrailingObjects<concepts::Requirement *>());
155 RequiresExprBits.IsSatisfied |= Dependent;
156 // FIXME: move the computing dependency logic to ComputeDependence.h
157 if (ContainsUnexpandedParameterPack)
158 setDependence(getDependence() | ExprDependence::UnexpandedPack);
159 // FIXME: this is incorrect for cases where we have a non-dependent
160 // requirement, but its parameters are instantiation-dependent. RequiresExpr
161 // should be instantiation-dependent if it has instantiation-dependent
162 // parameters.
163 if (Dependent)
164 setDependence(getDependence() | ExprDependence::ValueInstantiation);
167 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
168 unsigned NumLocalParameters,
169 unsigned NumRequirements)
170 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
171 NumRequirements(NumRequirements) { }
173 RequiresExpr *RequiresExpr::Create(
174 ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
175 SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
176 SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
177 SourceLocation RBraceLoc) {
178 void *Mem =
179 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
180 LocalParameters.size(), Requirements.size()),
181 alignof(RequiresExpr));
182 return new (Mem)
183 RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,
184 RParenLoc, Requirements, RBraceLoc);
187 RequiresExpr *
188 RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
189 unsigned NumLocalParameters, unsigned NumRequirements) {
190 void *Mem =
191 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
192 NumLocalParameters, NumRequirements),
193 alignof(RequiresExpr));
194 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);