blob: 76d57ed5d5b1f9e1d35464cd47b4951e0477af05 [file] [log] [blame]
Saar Raza0f50d72020-01-18 09:11:43 +02001//===- 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/ASTContext.h"
15#include "clang/AST/ASTConcept.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclarationName.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/Expr.h"
20#include "clang/AST/NestedNameSpecifier.h"
21#include "clang/AST/TemplateBase.h"
22#include "clang/AST/Type.h"
23#include "clang/Basic/SourceLocation.h"
24#include "llvm/Support/TrailingObjects.h"
25#include <algorithm>
26#include <utility>
27#include <string>
28
29using namespace clang;
30
31ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C,
32 NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
33 DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
34 ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten,
35 ArrayRef<TemplateArgument> ConvertedArgs,
36 const ConstraintSatisfaction *Satisfaction)
37 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
38 /*TypeDependent=*/false,
39 // All the flags below are set in setTemplateArguments.
40 /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false,
41 /*ContainsUnexpandedParameterPacks=*/false),
42 ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
43 NamedConcept, ArgsAsWritten),
44 NumTemplateArgs(ConvertedArgs.size()),
45 Satisfaction(Satisfaction ?
46 ASTConstraintSatisfaction::Create(C, *Satisfaction) :
47 nullptr) {
48 setTemplateArguments(ConvertedArgs);
49}
50
51ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
52 unsigned NumTemplateArgs)
53 : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
54 NumTemplateArgs(NumTemplateArgs) { }
55
56void ConceptSpecializationExpr::setTemplateArguments(
57 ArrayRef<TemplateArgument> Converted) {
58 assert(Converted.size() == NumTemplateArgs);
59 std::uninitialized_copy(Converted.begin(), Converted.end(),
60 getTrailingObjects<TemplateArgument>());
61 bool IsInstantiationDependent = false;
62 bool ContainsUnexpandedParameterPack = false;
63 for (const TemplateArgument& Arg : Converted) {
64 if (Arg.isInstantiationDependent())
65 IsInstantiationDependent = true;
66 if (Arg.containsUnexpandedParameterPack())
67 ContainsUnexpandedParameterPack = true;
68 if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
69 break;
70 }
71
72 // Currently guaranteed by the fact concepts can only be at namespace-scope.
73 assert(!NestedNameSpec ||
74 (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
75 !NestedNameSpec.getNestedNameSpecifier()
76 ->containsUnexpandedParameterPack()));
77 setInstantiationDependent(IsInstantiationDependent);
78 setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
79 assert((!isValueDependent() || isInstantiationDependent()) &&
80 "should not be value-dependent");
81}
82
83ConceptSpecializationExpr *
84ConceptSpecializationExpr::Create(const ASTContext &C,
85 NestedNameSpecifierLoc NNS,
86 SourceLocation TemplateKWLoc,
87 DeclarationNameInfo ConceptNameInfo,
88 NamedDecl *FoundDecl,
89 ConceptDecl *NamedConcept,
90 const ASTTemplateArgumentListInfo *ArgsAsWritten,
91 ArrayRef<TemplateArgument> ConvertedArgs,
92 const ConstraintSatisfaction *Satisfaction) {
93 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
94 ConvertedArgs.size()));
95 return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
96 ConceptNameInfo, FoundDecl,
97 NamedConcept, ArgsAsWritten,
98 ConvertedArgs, Satisfaction);
99}
100
101ConceptSpecializationExpr *
102ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
103 unsigned NumTemplateArgs) {
104 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
105 NumTemplateArgs));
106 return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
107}
108
109const TypeConstraint *
110concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
111 assert(isTypeConstraint());
112 auto TPL =
113 TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
114 return cast<TemplateTypeParmDecl>(TPL->getParam(0))
115 ->getTypeConstraint();
116}
117
118RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
119 RequiresExprBodyDecl *Body,
120 ArrayRef<ParmVarDecl *> LocalParameters,
121 ArrayRef<concepts::Requirement *> Requirements,
122 SourceLocation RBraceLoc)
123 : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
124 /*TD=*/false, /*VD=*/false, /*ID=*/false,
125 /*ContainsUnexpandedParameterPack=*/false),
126 NumLocalParameters(LocalParameters.size()),
127 NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
128 RequiresExprBits.IsSatisfied = false;
129 RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
130 bool Dependent = false;
131 bool ContainsUnexpandedParameterPack = false;
132 for (ParmVarDecl *P : LocalParameters) {
133 Dependent |= P->getType()->isInstantiationDependentType();
134 ContainsUnexpandedParameterPack |=
135 P->getType()->containsUnexpandedParameterPack();
136 }
137 RequiresExprBits.IsSatisfied = true;
138 for (concepts::Requirement *R : Requirements) {
139 Dependent |= R->isDependent();
140 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
141 if (!Dependent) {
142 RequiresExprBits.IsSatisfied = R->isSatisfied();
143 if (!RequiresExprBits.IsSatisfied)
144 break;
145 }
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 setValueDependent(Dependent);
153 setInstantiationDependent(Dependent);
154 setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
155}
156
157RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
158 unsigned NumLocalParameters,
159 unsigned NumRequirements)
160 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
161 NumRequirements(NumRequirements) { }
162
163RequiresExpr *
164RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
165 RequiresExprBodyDecl *Body,
166 ArrayRef<ParmVarDecl *> LocalParameters,
167 ArrayRef<concepts::Requirement *> Requirements,
168 SourceLocation RBraceLoc) {
169 void *Mem =
170 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
171 LocalParameters.size(), Requirements.size()),
172 alignof(RequiresExpr));
173 return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
174 Requirements, RBraceLoc);
175}
176
177RequiresExpr *
178RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
179 unsigned NumLocalParameters, unsigned NumRequirements) {
180 void *Mem =
181 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
182 NumLocalParameters, NumRequirements),
183 alignof(RequiresExpr));
184 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
185}