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/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 bool IsInstantiationDependent = false; 50 bool ContainsUnexpandedParameterPack = false; 51 for (const TemplateArgumentLoc& ArgLoc : ArgsAsWritten->arguments()) { 52 if (ArgLoc.getArgument().isInstantiationDependent()) 53 IsInstantiationDependent = true; 54 if (ArgLoc.getArgument().containsUnexpandedParameterPack()) 55 ContainsUnexpandedParameterPack = true; 56 if (ContainsUnexpandedParameterPack && IsInstantiationDependent) 57 break; 58 } 59 60 // Currently guaranteed by the fact concepts can only be at namespace-scope. 61 assert(!NestedNameSpec || 62 (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() && 63 !NestedNameSpec.getNestedNameSpecifier() 64 ->containsUnexpandedParameterPack())); 65 setInstantiationDependent(IsInstantiationDependent); 66 setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); 67 assert((!isValueDependent() || isInstantiationDependent()) && 68 "should not be value-dependent"); 69} 70 71ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, 72 unsigned NumTemplateArgs) 73 : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(), 74 NumTemplateArgs(NumTemplateArgs) { } 75 76void ConceptSpecializationExpr::setTemplateArguments( 77 ArrayRef<TemplateArgument> Converted) { 78 assert(Converted.size() == NumTemplateArgs); 79 std::uninitialized_copy(Converted.begin(), Converted.end(), 80 getTrailingObjects<TemplateArgument>()); 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::ConceptSpecializationExpr( 102 const ASTContext &C, ConceptDecl *NamedConcept, 103 ArrayRef<TemplateArgument> ConvertedArgs, 104 const ConstraintSatisfaction *Satisfaction, bool Dependent, 105 bool ContainsUnexpandedParameterPack) 106 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary, 107 /*TypeDependent=*/false, 108 /*ValueDependent=*/!Satisfaction, Dependent, 109 ContainsUnexpandedParameterPack), 110 ConceptReference(NestedNameSpecifierLoc(), SourceLocation(), 111 DeclarationNameInfo(), NamedConcept, 112 NamedConcept, nullptr), 113 NumTemplateArgs(ConvertedArgs.size()), 114 Satisfaction(Satisfaction ? 115 ASTConstraintSatisfaction::Create(C, *Satisfaction) : 116 nullptr) { 117 setTemplateArguments(ConvertedArgs); 118} 119 120ConceptSpecializationExpr * 121ConceptSpecializationExpr::Create(const ASTContext &C, 122 ConceptDecl *NamedConcept, 123 ArrayRef<TemplateArgument> ConvertedArgs, 124 const ConstraintSatisfaction *Satisfaction, 125 bool Dependent, 126 bool ContainsUnexpandedParameterPack) { 127 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( 128 ConvertedArgs.size())); 129 return new (Buffer) ConceptSpecializationExpr( 130 C, NamedConcept, ConvertedArgs, Satisfaction, Dependent, 131 ContainsUnexpandedParameterPack); 132} 133 134ConceptSpecializationExpr * 135ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty, 136 unsigned NumTemplateArgs) { 137 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( 138 NumTemplateArgs)); 139 return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); 140} 141 142const TypeConstraint * 143concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { 144 assert(isTypeConstraint()); 145 auto TPL = 146 TypeConstraintInfo.getPointer().get<TemplateParameterList *>(); 147 return cast<TemplateTypeParmDecl>(TPL->getParam(0)) 148 ->getTypeConstraint(); 149} 150 151RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, 152 RequiresExprBodyDecl *Body, 153 ArrayRef<ParmVarDecl *> LocalParameters, 154 ArrayRef<concepts::Requirement *> Requirements, 155 SourceLocation RBraceLoc) 156 : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary, 157 /*TD=*/false, /*VD=*/false, /*ID=*/false, 158 /*ContainsUnexpandedParameterPack=*/false), 159 NumLocalParameters(LocalParameters.size()), 160 NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) { 161 RequiresExprBits.IsSatisfied = false; 162 RequiresExprBits.RequiresKWLoc = RequiresKWLoc; 163 bool Dependent = false; 164 bool ContainsUnexpandedParameterPack = false; 165 for (ParmVarDecl *P : LocalParameters) { 166 Dependent |= P->getType()->isInstantiationDependentType(); 167 ContainsUnexpandedParameterPack |= 168 P->getType()->containsUnexpandedParameterPack(); 169 } 170 RequiresExprBits.IsSatisfied = true; 171 for (concepts::Requirement *R : Requirements) { 172 Dependent |= R->isDependent(); 173 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack(); 174 if (!Dependent) { 175 RequiresExprBits.IsSatisfied = R->isSatisfied(); 176 if (!RequiresExprBits.IsSatisfied) 177 break; 178 } 179 } 180 std::copy(LocalParameters.begin(), LocalParameters.end(), 181 getTrailingObjects<ParmVarDecl *>()); 182 std::copy(Requirements.begin(), Requirements.end(), 183 getTrailingObjects<concepts::Requirement *>()); 184 RequiresExprBits.IsSatisfied |= Dependent; 185 setValueDependent(Dependent); 186 setInstantiationDependent(Dependent); 187 setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); 188} 189 190RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, 191 unsigned NumLocalParameters, 192 unsigned NumRequirements) 193 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), 194 NumRequirements(NumRequirements) { } 195 196RequiresExpr * 197RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc, 198 RequiresExprBodyDecl *Body, 199 ArrayRef<ParmVarDecl *> LocalParameters, 200 ArrayRef<concepts::Requirement *> Requirements, 201 SourceLocation RBraceLoc) { 202 void *Mem = 203 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 204 LocalParameters.size(), Requirements.size()), 205 alignof(RequiresExpr)); 206 return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters, 207 Requirements, RBraceLoc); 208} 209 210RequiresExpr * 211RequiresExpr::Create(ASTContext &C, EmptyShell Empty, 212 unsigned NumLocalParameters, unsigned NumRequirements) { 213 void *Mem = 214 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 215 NumLocalParameters, NumRequirements), 216 alignof(RequiresExpr)); 217 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); 218} 219