clang 17.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#include "llvm/Support/TrailingObjects.h"
27#include <algorithm>
28#include <string>
29#include <utility>
30
31using namespace clang;
32
35 SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
36 NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
37 const ASTTemplateArgumentListInfo *ArgsAsWritten,
39 const ConstraintSatisfaction *Satisfaction)
40 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
41 ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
42 NamedConcept, ArgsAsWritten),
43 SpecDecl(SpecDecl),
44 Satisfaction(Satisfaction
45 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
46 : nullptr) {
47 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
48
49 // Currently guaranteed by the fact concepts can only be at namespace-scope.
50 assert(!NestedNameSpec ||
55 "should not be value-dependent");
56}
57
59 : Expr(ConceptSpecializationExprClass, Empty) {}
60
63 SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
64 NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
65 const ASTTemplateArgumentListInfo *ArgsAsWritten,
67 const ConstraintSatisfaction *Satisfaction) {
68 return new (C) ConceptSpecializationExpr(
69 C, NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
71}
72
74 const ASTContext &C, ConceptDecl *NamedConcept,
75 const ASTTemplateArgumentListInfo *ArgsAsWritten,
77 const ConstraintSatisfaction *Satisfaction, bool Dependent,
78 bool ContainsUnexpandedParameterPack)
79 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
81 DeclarationNameInfo(), NamedConcept, NamedConcept,
82 ArgsAsWritten),
83 SpecDecl(SpecDecl),
84 Satisfaction(Satisfaction
85 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
86 : nullptr) {
87 ExprDependence D = ExprDependence::None;
88 if (!Satisfaction)
89 D |= ExprDependence::Value;
90 if (Dependent)
91 D |= ExprDependence::Instantiation;
92 if (ContainsUnexpandedParameterPack)
93 D |= ExprDependence::UnexpandedPack;
95}
96
98 const ASTContext &C, ConceptDecl *NamedConcept,
99 const ASTTemplateArgumentListInfo *ArgsAsWritten,
101 const ConstraintSatisfaction *Satisfaction, bool Dependent,
102 bool ContainsUnexpandedParameterPack) {
104 SpecDecl, Satisfaction, Dependent,
105 ContainsUnexpandedParameterPack);
106}
107
108const TypeConstraint *
110 assert(isTypeConstraint());
111 auto TPL =
112 TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
113 return cast<TemplateTypeParmDecl>(TPL->getParam(0))
114 ->getTypeConstraint();
115}
116
117// Search through the requirements, and see if any have a RecoveryExpr in it,
118// which means this RequiresExpr ALSO needs to be invalid.
120 if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))
121 return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();
122
123 if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))
124 return !NestedReq->hasInvalidConstraint() &&
125 NestedReq->getConstraintExpr() &&
126 NestedReq->getConstraintExpr()->containsErrors();
127 return false;
128}
129
130RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
132 ArrayRef<ParmVarDecl *> LocalParameters,
134 SourceLocation RBraceLoc)
135 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
136 NumLocalParameters(LocalParameters.size()),
137 NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
138 RequiresExprBits.IsSatisfied = false;
139 RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
140 bool Dependent = false;
141 bool ContainsUnexpandedParameterPack = false;
142 for (ParmVarDecl *P : LocalParameters) {
143 Dependent |= P->getType()->isInstantiationDependentType();
144 ContainsUnexpandedParameterPack |=
145 P->getType()->containsUnexpandedParameterPack();
146 }
147 RequiresExprBits.IsSatisfied = true;
148 for (concepts::Requirement *R : Requirements) {
149 Dependent |= R->isDependent();
150 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
151 if (!Dependent) {
152 RequiresExprBits.IsSatisfied = R->isSatisfied();
153 if (!RequiresExprBits.IsSatisfied)
154 break;
155 }
156
158 setDependence(getDependence() | ExprDependence::Error);
159 }
160 std::copy(LocalParameters.begin(), LocalParameters.end(),
161 getTrailingObjects<ParmVarDecl *>());
162 std::copy(Requirements.begin(), Requirements.end(),
163 getTrailingObjects<concepts::Requirement *>());
164 RequiresExprBits.IsSatisfied |= Dependent;
165 // FIXME: move the computing dependency logic to ComputeDependence.h
166 if (ContainsUnexpandedParameterPack)
167 setDependence(getDependence() | ExprDependence::UnexpandedPack);
168 // FIXME: this is incorrect for cases where we have a non-dependent
169 // requirement, but its parameters are instantiation-dependent. RequiresExpr
170 // should be instantiation-dependent if it has instantiation-dependent
171 // parameters.
172 if (Dependent)
173 setDependence(getDependence() | ExprDependence::ValueInstantiation);
174}
175
176RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
177 unsigned NumLocalParameters,
178 unsigned NumRequirements)
179 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
180 NumRequirements(NumRequirements) { }
181
185 ArrayRef<ParmVarDecl *> LocalParameters,
187 SourceLocation RBraceLoc) {
188 void *Mem =
189 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
190 LocalParameters.size(), Requirements.size()),
191 alignof(RequiresExpr));
192 return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
193 Requirements, RBraceLoc);
194}
195
198 unsigned NumLocalParameters, unsigned NumRequirements) {
199 void *Mem =
200 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
201 NumLocalParameters, NumRequirements),
202 alignof(RequiresExpr));
203 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
204}
This file provides AST data structures related to concepts.
Defines the clang::ASTContext interface.
StringRef P
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:182
Declaration of a C++20 concept.
Common data class for constructs that reference concepts with template arguments.
Definition: ASTConcept.h:112
NestedNameSpecifierLoc NestedNameSpec
Definition: ASTConcept.h:115
ConceptDecl * NamedConcept
The concept named.
Definition: ASTConcept.h:131
SourceLocation TemplateKWLoc
The location of the template keyword, if specified when naming the concept.
Definition: ASTConcept.h:119
const ASTTemplateArgumentListInfo * ArgsAsWritten
The template argument list source info used to specialize the concept.
Definition: ASTConcept.h:135
NamedDecl * FoundDecl
The declaration found by name lookup when the expression was created.
Definition: ASTConcept.h:128
Represents the specialization of a concept - evaluates to a prvalue of type bool.
Definition: ExprConcepts.h:41
ASTConstraintSatisfaction * Satisfaction
Information about the satisfaction of the named concept with the given arguments.
Definition: ExprConcepts.h:56
static ConceptSpecializationExpr * Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction)
ImplicitConceptSpecializationDecl * SpecDecl
The Implicit Concept Specialization Decl, which holds the template arguments for this specialization.
Definition: ExprConcepts.h:51
ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction)
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:28
This represents one expression.
Definition: Expr.h:110
bool isValueDependent() const
Determines whether the value of this expression depends on.
Definition: Expr.h:169
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:215
void setDependence(ExprDependence Deps)
Each concrete expr subclass is expected to compute its dependence and call this in the constructor.
Definition: Expr.h:135
This represents a decl that may have a name.
Definition: Decl.h:247
A C++ nested-name-specifier augmented with source location information.
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:1722
Represents the body of a requires-expression.
Definition: DeclCXX.h:2013
C++2a [expr.prim.req]: A requires-expression provides a concise way to express requirements on templa...
Definition: ExprConcepts.h:480
static RequiresExpr * Create(ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, ArrayRef< ParmVarDecl * > LocalParameters, ArrayRef< concepts::Requirement * > Requirements, SourceLocation RBraceLoc)
Encodes a location in the source.
Stores a list of template parameters for a TemplateDecl and its derived classes.
Definition: DeclTemplate.h:73
A static requirement that can be used in a requires-expression to check properties of types and expre...
Definition: ExprConcepts.h:148
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:142
ExprDependence computeDependence(FullExpr *E)
@ C
Languages that the frontend can parse and compile.
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition: Specifiers.h:126
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:86
Represents an explicit template argument list in C++, e.g., the "<int>" in "sort<int>".
Definition: TemplateBase.h:641
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
A placeholder type used to construct an empty shell of a type, that will be filled in later (e....
Definition: Stmt.h:1121