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/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 <algorithm>
27
28using namespace clang;
29
30ConceptSpecializationExpr::ConceptSpecializationExpr(
31 const ASTContext &C, ConceptReference *Loc,
32 ImplicitConceptSpecializationDecl *SpecDecl,
33 const ConstraintSatisfaction *Satisfaction)
34 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
35 ConceptRef(Loc), SpecDecl(SpecDecl),
36 Satisfaction(Satisfaction
37 ? ASTConstraintSatisfaction::Create(C, Satisfaction: *Satisfaction)
38 : nullptr) {
39 setDependence(computeDependence(E: this, /*ValueDependent=*/!Satisfaction));
40
41 // Currently guaranteed by the fact concepts can only be at namespace-scope.
42 assert(!Loc->getNestedNameSpecifierLoc() ||
43 (!Loc->getNestedNameSpecifierLoc()
44 .getNestedNameSpecifier()
45 ->isInstantiationDependent() &&
46 !Loc->getNestedNameSpecifierLoc()
47 .getNestedNameSpecifier()
48 ->containsUnexpandedParameterPack()));
49 assert((!isValueDependent() || isInstantiationDependent()) &&
50 "should not be value-dependent");
51}
52
53ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
54 : Expr(ConceptSpecializationExprClass, Empty) {}
55
56ConceptSpecializationExpr *
57ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
58 ImplicitConceptSpecializationDecl *SpecDecl,
59 const ConstraintSatisfaction *Satisfaction) {
60 return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);
61}
62
63ConceptSpecializationExpr::ConceptSpecializationExpr(
64 const ASTContext &C, ConceptReference *Loc,
65 ImplicitConceptSpecializationDecl *SpecDecl,
66 const ConstraintSatisfaction *Satisfaction, bool Dependent,
67 bool ContainsUnexpandedParameterPack)
68 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
69 ConceptRef(Loc), SpecDecl(SpecDecl),
70 Satisfaction(Satisfaction
71 ? ASTConstraintSatisfaction::Create(C, Satisfaction: *Satisfaction)
72 : nullptr) {
73 ExprDependence D = ExprDependence::None;
74 if (!Satisfaction)
75 D |= ExprDependence::Value;
76 if (Dependent)
77 D |= ExprDependence::Instantiation;
78 if (ContainsUnexpandedParameterPack)
79 D |= ExprDependence::UnexpandedPack;
80 setDependence(D);
81}
82
83ConceptSpecializationExpr *
84ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
85 ImplicitConceptSpecializationDecl *SpecDecl,
86 const ConstraintSatisfaction *Satisfaction,
87 bool Dependent,
88 bool ContainsUnexpandedParameterPack) {
89 return new (C)
90 ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,
91 ContainsUnexpandedParameterPack);
92}
93
94const TypeConstraint *
95concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
96 assert(isTypeConstraint());
97 auto TPL = cast<TemplateParameterList *>(Val: TypeConstraintInfo.getPointer());
98 return cast<TemplateTypeParmDecl>(Val: TPL->getParam(Idx: 0))
99 ->getTypeConstraint();
100}
101
102// Search through the requirements, and see if any have a RecoveryExpr in it,
103// which means this RequiresExpr ALSO needs to be invalid.
104static bool RequirementContainsError(concepts::Requirement *R) {
105 if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(Val: R))
106 return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();
107
108 if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(Val: R))
109 return !NestedReq->hasInvalidConstraint() &&
110 NestedReq->getConstraintExpr() &&
111 NestedReq->getConstraintExpr()->containsErrors();
112 return false;
113}
114
115RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
116 RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
117 ArrayRef<ParmVarDecl *> LocalParameters,
118 SourceLocation RParenLoc,
119 ArrayRef<concepts::Requirement *> Requirements,
120 SourceLocation RBraceLoc)
121 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
122 NumLocalParameters(LocalParameters.size()),
123 NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),
124 RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {
125 RequiresExprBits.IsSatisfied = false;
126 RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
127 bool Dependent = false;
128 bool ContainsUnexpandedParameterPack = false;
129 for (ParmVarDecl *P : LocalParameters) {
130 Dependent |= P->getType()->isInstantiationDependentType();
131 ContainsUnexpandedParameterPack |=
132 P->getType()->containsUnexpandedParameterPack();
133 }
134 RequiresExprBits.IsSatisfied = true;
135 for (concepts::Requirement *R : Requirements) {
136 Dependent |= R->isDependent();
137 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
138 if (!Dependent) {
139 RequiresExprBits.IsSatisfied = R->isSatisfied();
140 if (!RequiresExprBits.IsSatisfied)
141 break;
142 }
143
144 if (RequirementContainsError(R))
145 setDependence(getDependence() | ExprDependence::Error);
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 // FIXME: move the computing dependency logic to ComputeDependence.h
153 if (ContainsUnexpandedParameterPack)
154 setDependence(getDependence() | ExprDependence::UnexpandedPack);
155 // FIXME: this is incorrect for cases where we have a non-dependent
156 // requirement, but its parameters are instantiation-dependent. RequiresExpr
157 // should be instantiation-dependent if it has instantiation-dependent
158 // parameters.
159 if (Dependent)
160 setDependence(getDependence() | ExprDependence::ValueInstantiation);
161}
162
163RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
164 unsigned NumLocalParameters,
165 unsigned NumRequirements)
166 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
167 NumRequirements(NumRequirements) { }
168
169RequiresExpr *RequiresExpr::Create(
170 ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
171 SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
172 SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
173 SourceLocation RBraceLoc) {
174 void *Mem =
175 C.Allocate(Size: totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
176 Counts: LocalParameters.size(), Counts: Requirements.size()),
177 Align: alignof(RequiresExpr));
178 return new (Mem)
179 RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,
180 RParenLoc, Requirements, RBraceLoc);
181}
182
183RequiresExpr *
184RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
185 unsigned NumLocalParameters, unsigned NumRequirements) {
186 void *Mem =
187 C.Allocate(Size: totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
188 Counts: NumLocalParameters, Counts: NumRequirements),
189 Align: alignof(RequiresExpr));
190 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
191}
192

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang/lib/AST/ExprConcepts.cpp