Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/AST/ExprConcepts.cpp
Line
Count
Source (jump to first uncovered line)
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 "llvm/Support/TrailingObjects.h"
27
#include <algorithm>
28
#include <string>
29
#include <utility>
30
31
using namespace clang;
32
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
0
                       : nullptr) {
42
0
  setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
43
44
  // Currently guaranteed by the fact concepts can only be at namespace-scope.
45
0
  assert(!Loc->getNestedNameSpecifierLoc() ||
46
0
         (!Loc->getNestedNameSpecifierLoc()
47
0
               .getNestedNameSpecifier()
48
0
               ->isInstantiationDependent() &&
49
0
          !Loc->getNestedNameSpecifierLoc()
50
0
               .getNestedNameSpecifier()
51
0
               ->containsUnexpandedParameterPack()));
52
0
  assert((!isValueDependent() || isInstantiationDependent()) &&
53
0
         "should not be value-dependent");
54
0
}
55
56
ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
57
0
    : Expr(ConceptSpecializationExprClass, Empty) {}
58
59
ConceptSpecializationExpr *
60
ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
61
                                  ImplicitConceptSpecializationDecl *SpecDecl,
62
0
                                  const ConstraintSatisfaction *Satisfaction) {
63
0
  return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);
64
0
}
65
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
0
                       : nullptr) {
76
0
  ExprDependence D = ExprDependence::None;
77
0
  if (!Satisfaction)
78
0
    D |= ExprDependence::Value;
79
0
  if (Dependent)
80
0
    D |= ExprDependence::Instantiation;
81
0
  if (ContainsUnexpandedParameterPack)
82
0
    D |= ExprDependence::UnexpandedPack;
83
0
  setDependence(D);
84
0
}
85
86
ConceptSpecializationExpr *
87
ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
88
                                  ImplicitConceptSpecializationDecl *SpecDecl,
89
                                  const ConstraintSatisfaction *Satisfaction,
90
                                  bool Dependent,
91
0
                                  bool ContainsUnexpandedParameterPack) {
92
0
  return new (C)
93
0
      ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,
94
0
                                ContainsUnexpandedParameterPack);
95
0
}
96
97
const TypeConstraint *
98
0
concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
99
0
  assert(isTypeConstraint());
100
0
  auto TPL =
101
0
      TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
102
0
  return cast<TemplateTypeParmDecl>(TPL->getParam(0))
103
0
      ->getTypeConstraint();
104
0
}
105
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
0
static bool RequirementContainsError(concepts::Requirement *R) {
109
0
  if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))
110
0
    return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();
111
112
0
  if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))
113
0
    return !NestedReq->hasInvalidConstraint() &&
114
0
           NestedReq->getConstraintExpr() &&
115
0
           NestedReq->getConstraintExpr()->containsErrors();
116
0
  return false;
117
0
}
118
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
0
      RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {
129
0
  RequiresExprBits.IsSatisfied = false;
130
0
  RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
131
0
  bool Dependent = false;
132
0
  bool ContainsUnexpandedParameterPack = false;
133
0
  for (ParmVarDecl *P : LocalParameters) {
134
0
    Dependent |= P->getType()->isInstantiationDependentType();
135
0
    ContainsUnexpandedParameterPack |=
136
0
        P->getType()->containsUnexpandedParameterPack();
137
0
  }
138
0
  RequiresExprBits.IsSatisfied = true;
139
0
  for (concepts::Requirement *R : Requirements) {
140
0
    Dependent |= R->isDependent();
141
0
    ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
142
0
    if (!Dependent) {
143
0
      RequiresExprBits.IsSatisfied = R->isSatisfied();
144
0
      if (!RequiresExprBits.IsSatisfied)
145
0
        break;
146
0
    }
147
148
0
    if (RequirementContainsError(R))
149
0
      setDependence(getDependence() | ExprDependence::Error);
150
0
  }
151
0
  std::copy(LocalParameters.begin(), LocalParameters.end(),
152
0
            getTrailingObjects<ParmVarDecl *>());
153
0
  std::copy(Requirements.begin(), Requirements.end(),
154
0
            getTrailingObjects<concepts::Requirement *>());
155
0
  RequiresExprBits.IsSatisfied |= Dependent;
156
  // FIXME: move the computing dependency logic to ComputeDependence.h
157
0
  if (ContainsUnexpandedParameterPack)
158
0
    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
0
  if (Dependent)
164
0
    setDependence(getDependence() | ExprDependence::ValueInstantiation);
165
0
}
166
167
RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
168
                           unsigned NumLocalParameters,
169
                           unsigned NumRequirements)
170
  : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
171
0
    NumRequirements(NumRequirements) { }
172
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
0
    SourceLocation RBraceLoc) {
178
0
  void *Mem =
179
0
      C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
180
0
                     LocalParameters.size(), Requirements.size()),
181
0
                 alignof(RequiresExpr));
182
0
  return new (Mem)
183
0
      RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,
184
0
                   RParenLoc, Requirements, RBraceLoc);
185
0
}
186
187
RequiresExpr *
188
RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
189
0
                     unsigned NumLocalParameters, unsigned NumRequirements) {
190
0
  void *Mem =
191
0
      C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
192
0
                     NumLocalParameters, NumRequirements),
193
0
                 alignof(RequiresExpr));
194
0
  return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
195
0
}