clang 23.0.0git
ExprConcepts.cpp
Go to the documentation of this file.
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
17#include "clang/AST/Decl.h"
21#include "clang/AST/Expr.h"
24#include "clang/AST/Type.h"
26
27using namespace clang;
28
29ConceptSpecializationExpr::ConceptSpecializationExpr(
30 const ASTContext &C, ConceptReference *Loc,
32 const ConstraintSatisfaction *Satisfaction)
33 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
34 ConceptRef(Loc), SpecDecl(SpecDecl),
35 Satisfaction(Satisfaction
36 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
37 : nullptr) {
38 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
39
40 // Currently guaranteed by the fact concepts can only be at namespace-scope.
41 assert(!Loc->getNestedNameSpecifierLoc() ||
48 assert((!isValueDependent() || isInstantiationDependent()) &&
49 "should not be value-dependent");
50}
51
52ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
53 : Expr(ConceptSpecializationExprClass, Empty) {}
54
58 const ConstraintSatisfaction *Satisfaction) {
59 return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);
60}
61
62ConceptSpecializationExpr::ConceptSpecializationExpr(
63 const ASTContext &C, ConceptReference *Loc,
65 const ConstraintSatisfaction *Satisfaction, bool Dependent,
66 bool ContainsUnexpandedParameterPack)
67 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
68 ConceptRef(Loc), SpecDecl(SpecDecl),
69 Satisfaction(Satisfaction
70 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
71 : nullptr) {
72 ExprDependence D = ExprDependence::None;
73 if (!Satisfaction)
74 D |= ExprDependence::Value;
75 if (Dependent)
76 D |= ExprDependence::Instantiation;
77 if (ContainsUnexpandedParameterPack)
78 D |= ExprDependence::UnexpandedPack;
80}
81
85 const ConstraintSatisfaction *Satisfaction,
86 bool Dependent,
87 bool ContainsUnexpandedParameterPack) {
88 return new (C)
89 ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,
90 ContainsUnexpandedParameterPack);
91}
92
93const TypeConstraint *
95 assert(isTypeConstraint());
96 auto TPL = cast<TemplateParameterList *>(TypeConstraintInfo.getPointer());
97 return cast<TemplateTypeParmDecl>(TPL->getParam(0))
98 ->getTypeConstraint();
99}
100
101// Search through the requirements, and see if any have a RecoveryExpr in it,
102// which means this RequiresExpr ALSO needs to be invalid.
104 if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R)) {
105 if (ExprReq->isExprSubstitutionFailure())
106 return true;
107 if (auto *E = ExprReq->getExpr())
108 return E->containsErrors();
109 return false;
110 }
111
112 if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))
113 return !NestedReq->hasInvalidConstraint() &&
114 NestedReq->getConstraintExpr() &&
115 NestedReq->getConstraintExpr()->containsErrors();
116 return false;
117}
118
119RequiresExpr::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();
137 }
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;
146 }
147
149 setDependence(getDependence() | ExprDependence::Error);
150 }
151 llvm::copy(LocalParameters, getTrailingObjects<ParmVarDecl *>());
152 llvm::copy(Requirements, getTrailingObjects<concepts::Requirement *>());
153 RequiresExprBits.IsSatisfied |= Dependent;
154 // FIXME: move the computing dependency logic to ComputeDependence.h
155 if (ContainsUnexpandedParameterPack)
156 setDependence(getDependence() | ExprDependence::UnexpandedPack);
157 // FIXME: this is incorrect for cases where we have a non-dependent
158 // requirement, but its parameters are instantiation-dependent. RequiresExpr
159 // should be instantiation-dependent if it has instantiation-dependent
160 // parameters.
161 if (Dependent)
162 setDependence(getDependence() | ExprDependence::ValueInstantiation);
163}
164
165RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
166 unsigned NumLocalParameters,
167 unsigned NumRequirements)
168 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
169 NumRequirements(NumRequirements) { }
170
172 ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
173 SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
175 SourceLocation RBraceLoc) {
176 void *Mem =
177 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
178 LocalParameters.size(), Requirements.size()),
179 alignof(RequiresExpr));
180 return new (Mem)
181 RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,
182 RParenLoc, Requirements, RBraceLoc);
183}
184
187 unsigned NumLocalParameters, unsigned NumRequirements) {
188 void *Mem =
189 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
190 NumLocalParameters, NumRequirements),
191 alignof(RequiresExpr));
192 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
193}
This file provides AST data structures related to concepts.
Defines the clang::ASTContext interface.
Defines the C++ template declaration subclasses.
static bool RequirementContainsError(concepts::Requirement *R)
Defines Expressions and AST nodes for C++2a concepts.
Defines the clang::SourceLocation class and associated facilities.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:220
A reference to a concept and its template args, as it appears in the code.
Definition ASTConcept.h:130
const NestedNameSpecifierLoc & getNestedNameSpecifierLoc() const
Definition ASTConcept.h:170
Represents the specialization of a concept - evaluates to a prvalue of type bool.
static ConceptSpecializationExpr * Create(const ASTContext &C, ConceptReference *ConceptRef, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:47
This represents one expression.
Definition Expr.h:112
void setDependence(ExprDependence Deps)
Each concrete expr subclass is expected to compute its dependence and call this in the constructor.
Definition Expr.h:137
NestedNameSpecifier getNestedNameSpecifier() const
Retrieve the nested-name-specifier to which this instance refers.
bool isInstantiationDependent() const
Whether this nested name specifier involves a template parameter.
bool containsUnexpandedParameterPack() const
Whether this nested-name-specifier contains an unexpanded parameter pack (for C++11 variadic template...
Represents a parameter to a function.
Definition Decl.h:1790
Represents the body of a requires-expression.
Definition DeclCXX.h:2098
C++2a [expr.prim.req]: A requires-expression provides a concise way to express requirements on templa...
static RequiresExpr * Create(ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, SourceLocation LParenLoc, ArrayRef< ParmVarDecl * > LocalParameters, SourceLocation RParenLoc, ArrayRef< concepts::Requirement * > Requirements, SourceLocation RBraceLoc)
Encodes a location in the source.
Models the abbreviated syntax to constrain a template type parameter: template <convertible_to<string...
Definition ASTConcept.h:227
A static requirement that can be used in a requires-expression to check properties of types and expre...
The JSON file list parser is used to communicate input to InstallAPI.
ExprDependenceScope::ExprDependence ExprDependence
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition Specifiers.h:151
ExprDependence computeDependence(FullExpr *E)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ Dependent
Parse the block as a dependent block, which may be used in some template instantiations but not other...
Definition Parser.h:142
static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation StepModifierLoc, SourceLocation EndLoc, ArrayRef< Expr * > VL, ArrayRef< Expr * > PL, ArrayRef< Expr * > IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate)
Creates clause with a list of variables VL and a linear step Step.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
U cast(CodeGen::Address addr)
Definition Address.h:327
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition ASTConcept.h:91
A placeholder type used to construct an empty shell of a type, that will be filled in later (e....
Definition Stmt.h:1425