Coverage Report

Created: 2020-10-24 06:27

/Users/buildslave/jenkins/workspace/coverage/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, NestedNameSpecifierLoc NNS,
35
    SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
36
    NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
37
    const ASTTemplateArgumentListInfo *ArgsAsWritten,
38
    ArrayRef<TemplateArgument> ConvertedArgs,
39
    const ConstraintSatisfaction *Satisfaction)
40
    : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
41
      ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
42
                       NamedConcept, ArgsAsWritten),
43
      NumTemplateArgs(ConvertedArgs.size()),
44
      Satisfaction(Satisfaction
45
                       ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
46
812
                       : nullptr) {
47
812
  setTemplateArguments(ConvertedArgs);
48
812
  setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
49
50
  // Currently guaranteed by the fact concepts can only be at namespace-scope.
51
812
  assert(!NestedNameSpec ||
52
812
         (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
53
812
          !NestedNameSpec.getNestedNameSpecifier()
54
812
              ->containsUnexpandedParameterPack()));
55
812
  assert((!isValueDependent() || isInstantiationDependent()) &&
56
812
         "should not be value-dependent");
57
812
}
58
59
ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
60
    unsigned NumTemplateArgs)
61
    : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
62
30
      NumTemplateArgs(NumTemplateArgs) { }
63
64
void ConceptSpecializationExpr::setTemplateArguments(
65
843
    ArrayRef<TemplateArgument> Converted) {
66
843
  assert(Converted.size() == NumTemplateArgs);
67
843
  std::uninitialized_copy(Converted.begin(), Converted.end(),
68
843
                          getTrailingObjects<TemplateArgument>());
69
843
}
70
71
ConceptSpecializationExpr *
72
ConceptSpecializationExpr::Create(const ASTContext &C,
73
                                  NestedNameSpecifierLoc NNS,
74
                                  SourceLocation TemplateKWLoc,
75
                                  DeclarationNameInfo ConceptNameInfo,
76
                                  NamedDecl *FoundDecl,
77
                                  ConceptDecl *NamedConcept,
78
                               const ASTTemplateArgumentListInfo *ArgsAsWritten,
79
                                  ArrayRef<TemplateArgument> ConvertedArgs,
80
812
                                  const ConstraintSatisfaction *Satisfaction) {
81
812
  void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
82
812
                                ConvertedArgs.size()));
83
812
  return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
84
812
                                                ConceptNameInfo, FoundDecl,
85
812
                                                NamedConcept, ArgsAsWritten,
86
812
                                                ConvertedArgs, Satisfaction);
87
812
}
88
89
ConceptSpecializationExpr::ConceptSpecializationExpr(
90
    const ASTContext &C, ConceptDecl *NamedConcept,
91
    ArrayRef<TemplateArgument> ConvertedArgs,
92
    const ConstraintSatisfaction *Satisfaction, bool Dependent,
93
    bool ContainsUnexpandedParameterPack)
94
    : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
95
      ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
96
                       DeclarationNameInfo(), NamedConcept, NamedConcept,
97
                       nullptr),
98
      NumTemplateArgs(ConvertedArgs.size()),
99
      Satisfaction(Satisfaction
100
                       ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
101
1
                       : nullptr) {
102
1
  setTemplateArguments(ConvertedArgs);
103
1
  ExprDependence D = ExprDependence::None;
104
1
  if (!Satisfaction)
105
1
    D |= ExprDependence::Value;
106
1
  if (Dependent)
107
1
    D |= ExprDependence::Instantiation;
108
1
  if (ContainsUnexpandedParameterPack)
109
0
    D |= ExprDependence::UnexpandedPack;
110
1
  setDependence(D);
111
1
}
112
113
ConceptSpecializationExpr *
114
ConceptSpecializationExpr::Create(const ASTContext &C,
115
                                  ConceptDecl *NamedConcept,
116
                                  ArrayRef<TemplateArgument> ConvertedArgs,
117
                                  const ConstraintSatisfaction *Satisfaction,
118
                                  bool Dependent,
119
1
                                  bool ContainsUnexpandedParameterPack) {
120
1
  void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
121
1
                                ConvertedArgs.size()));
122
1
  return new (Buffer) ConceptSpecializationExpr(
123
1
      C, NamedConcept, ConvertedArgs, Satisfaction, Dependent,
124
1
      ContainsUnexpandedParameterPack);
125
1
}
126
127
ConceptSpecializationExpr *
128
ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
129
30
                                  unsigned NumTemplateArgs) {
130
30
  void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
131
30
                                NumTemplateArgs));
132
30
  return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
133
30
}
134
135
const TypeConstraint *
136
41
concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
137
41
  assert(isTypeConstraint());
138
41
  auto TPL =
139
41
      TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
140
41
  return cast<TemplateTypeParmDecl>(TPL->getParam(0))
141
41
      ->getTypeConstraint();
142
41
}
143
144
RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
145
                           RequiresExprBodyDecl *Body,
146
                           ArrayRef<ParmVarDecl *> LocalParameters,
147
                           ArrayRef<concepts::Requirement *> Requirements,
148
                           SourceLocation RBraceLoc)
149
    : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
150
      NumLocalParameters(LocalParameters.size()),
151
355
      NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
152
355
  RequiresExprBits.IsSatisfied = false;
153
355
  RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
154
355
  bool Dependent = false;
155
355
  bool ContainsUnexpandedParameterPack = false;
156
192
  for (ParmVarDecl *P : LocalParameters) {
157
192
    Dependent |= P->getType()->isInstantiationDependentType();
158
192
    ContainsUnexpandedParameterPack |=
159
192
        P->getType()->containsUnexpandedParameterPack();
160
192
  }
161
355
  RequiresExprBits.IsSatisfied = true;
162
422
  for (concepts::Requirement *R : Requirements) {
163
422
    Dependent |= R->isDependent();
164
422
    ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
165
422
    if (!Dependent) {
166
257
      RequiresExprBits.IsSatisfied = R->isSatisfied();
167
257
      if (!RequiresExprBits.IsSatisfied)
168
93
        break;
169
257
    }
170
422
  }
171
355
  std::copy(LocalParameters.begin(), LocalParameters.end(),
172
355
            getTrailingObjects<ParmVarDecl *>());
173
355
  std::copy(Requirements.begin(), Requirements.end(),
174
355
            getTrailingObjects<concepts::Requirement *>());
175
355
  RequiresExprBits.IsSatisfied |= Dependent;
176
  // FIXME: move the computing dependency logic to ComputeDependence.h
177
355
  if (ContainsUnexpandedParameterPack)
178
13
    setDependence(getDependence() | ExprDependence::UnexpandedPack);
179
  // FIXME: this is incorrect for cases where we have a non-dependent
180
  // requirement, but its parameters are instantiation-dependent. RequiresExpr
181
  // should be instantiation-dependent if it has instantiation-dependent
182
  // parameters.
183
355
  if (Dependent)
184
131
    setDependence(getDependence() | ExprDependence::ValueInstantiation);
185
355
}
186
187
RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
188
                           unsigned NumLocalParameters,
189
                           unsigned NumRequirements)
190
  : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
191
2
    NumRequirements(NumRequirements) { }
192
193
RequiresExpr *
194
RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
195
                     RequiresExprBodyDecl *Body,
196
                     ArrayRef<ParmVarDecl *> LocalParameters,
197
                     ArrayRef<concepts::Requirement *> Requirements,
198
355
                     SourceLocation RBraceLoc) {
199
355
  void *Mem =
200
355
      C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
201
355
                     LocalParameters.size(), Requirements.size()),
202
355
                 alignof(RequiresExpr));
203
355
  return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
204
355
                                Requirements, RBraceLoc);
205
355
}
206
207
RequiresExpr *
208
RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
209
2
                     unsigned NumLocalParameters, unsigned NumRequirements) {
210
2
  void *Mem =
211
2
      C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
212
2
                     NumLocalParameters, NumRequirements),
213
2
                 alignof(RequiresExpr));
214
2
  return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
215
2
}