| Saar Raz | a0f50d7 | 2020-01-18 09:11:43 +0200 | [diff] [blame] | 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 | |
| 29 | using namespace clang; |
| 30 | |
| 31 | ConceptSpecializationExpr::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 | |
| 51 | ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, |
| 52 | unsigned NumTemplateArgs) |
| 53 | : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(), |
| 54 | NumTemplateArgs(NumTemplateArgs) { } |
| 55 | |
| 56 | void 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 | |
| 83 | ConceptSpecializationExpr * |
| 84 | ConceptSpecializationExpr::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 | |
| 101 | ConceptSpecializationExpr * |
| 102 | ConceptSpecializationExpr::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 | |
| 109 | const TypeConstraint * |
| 110 | concepts::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 | |
| 118 | RequiresExpr::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 | |
| 157 | RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, |
| 158 | unsigned NumLocalParameters, |
| 159 | unsigned NumRequirements) |
| 160 | : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), |
| 161 | NumRequirements(NumRequirements) { } |
| 162 | |
| 163 | RequiresExpr * |
| 164 | RequiresExpr::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 | |
| 177 | RequiresExpr * |
| 178 | RequiresExpr::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 | } |