1a0f50d73SSaar Raz //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===// 2a0f50d73SSaar Raz // 3a0f50d73SSaar Raz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a0f50d73SSaar Raz // See https://llvm.org/LICENSE.txt for license information. 5a0f50d73SSaar Raz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a0f50d73SSaar Raz // 7a0f50d73SSaar Raz //===----------------------------------------------------------------------===// 8a0f50d73SSaar Raz // 9a0f50d73SSaar Raz // This file implements the subclesses of Expr class declared in ExprCXX.h 10a0f50d73SSaar Raz // 11a0f50d73SSaar Raz //===----------------------------------------------------------------------===// 12a0f50d73SSaar Raz 13a0f50d73SSaar Raz #include "clang/AST/ExprConcepts.h" 14a0f50d73SSaar Raz #include "clang/AST/ASTConcept.h" 15ec3060c7SIlya Biryukov #include "clang/AST/ASTContext.h" 16876bb86eSHaojian Wu #include "clang/AST/ComputeDependence.h" 17a0f50d73SSaar Raz #include "clang/AST/Decl.h" 18a0f50d73SSaar Raz #include "clang/AST/DeclTemplate.h" 19ec3060c7SIlya Biryukov #include "clang/AST/DeclarationName.h" 2067d25914SHaojian Wu #include "clang/AST/DependenceFlags.h" 21a0f50d73SSaar Raz #include "clang/AST/Expr.h" 22a0f50d73SSaar Raz #include "clang/AST/NestedNameSpecifier.h" 23a0f50d73SSaar Raz #include "clang/AST/TemplateBase.h" 24a0f50d73SSaar Raz #include "clang/AST/Type.h" 25a0f50d73SSaar Raz #include "clang/Basic/SourceLocation.h" 26a0f50d73SSaar Raz #include <algorithm> 27a0f50d73SSaar Raz 28a0f50d73SSaar Raz using namespace clang; 29a0f50d73SSaar Raz 30876bb86eSHaojian Wu ConceptSpecializationExpr::ConceptSpecializationExpr( 31c2bf9bafSJens Massberg const ASTContext &C, ConceptReference *Loc, 32975740bfSErich Keane ImplicitConceptSpecializationDecl *SpecDecl, 33a0f50d73SSaar Raz const ConstraintSatisfaction *Satisfaction) 34aef5d8fdSMatheus Izvekov : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 35c2bf9bafSJens Massberg ConceptRef(Loc), SpecDecl(SpecDecl), 36876bb86eSHaojian Wu Satisfaction(Satisfaction 37876bb86eSHaojian Wu ? ASTConstraintSatisfaction::Create(C, *Satisfaction) 38876bb86eSHaojian Wu : nullptr) { 39876bb86eSHaojian Wu setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction)); 40a0f50d73SSaar Raz 41a0f50d73SSaar Raz // Currently guaranteed by the fact concepts can only be at namespace-scope. 42c2bf9bafSJens Massberg assert(!Loc->getNestedNameSpecifierLoc() || 43c2bf9bafSJens Massberg (!Loc->getNestedNameSpecifierLoc() 44c2bf9bafSJens Massberg .getNestedNameSpecifier() 45c2bf9bafSJens Massberg ->isInstantiationDependent() && 46c2bf9bafSJens Massberg !Loc->getNestedNameSpecifierLoc() 47c2bf9bafSJens Massberg .getNestedNameSpecifier() 48a0f50d73SSaar Raz ->containsUnexpandedParameterPack())); 49a0f50d73SSaar Raz assert((!isValueDependent() || isInstantiationDependent()) && 50a0f50d73SSaar Raz "should not be value-dependent"); 51a0f50d73SSaar Raz } 52a0f50d73SSaar Raz 53975740bfSErich Keane ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty) 54975740bfSErich Keane : Expr(ConceptSpecializationExprClass, Empty) {} 55c83d9bedSSaar Raz 56c2bf9bafSJens Massberg ConceptSpecializationExpr * 57c2bf9bafSJens Massberg ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, 58975740bfSErich Keane ImplicitConceptSpecializationDecl *SpecDecl, 59a0f50d73SSaar Raz const ConstraintSatisfaction *Satisfaction) { 60c2bf9bafSJens Massberg return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction); 61a0f50d73SSaar Raz } 62a0f50d73SSaar Raz 63c83d9bedSSaar Raz ConceptSpecializationExpr::ConceptSpecializationExpr( 64c2bf9bafSJens Massberg const ASTContext &C, ConceptReference *Loc, 65975740bfSErich Keane ImplicitConceptSpecializationDecl *SpecDecl, 66c83d9bedSSaar Raz const ConstraintSatisfaction *Satisfaction, bool Dependent, 67c83d9bedSSaar Raz bool ContainsUnexpandedParameterPack) 68aef5d8fdSMatheus Izvekov : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 69c2bf9bafSJens Massberg ConceptRef(Loc), SpecDecl(SpecDecl), 70876bb86eSHaojian Wu Satisfaction(Satisfaction 71876bb86eSHaojian Wu ? ASTConstraintSatisfaction::Create(C, *Satisfaction) 72876bb86eSHaojian Wu : nullptr) { 73876bb86eSHaojian Wu ExprDependence D = ExprDependence::None; 74876bb86eSHaojian Wu if (!Satisfaction) 75876bb86eSHaojian Wu D |= ExprDependence::Value; 76876bb86eSHaojian Wu if (Dependent) 77876bb86eSHaojian Wu D |= ExprDependence::Instantiation; 78876bb86eSHaojian Wu if (ContainsUnexpandedParameterPack) 79876bb86eSHaojian Wu D |= ExprDependence::UnexpandedPack; 80876bb86eSHaojian Wu setDependence(D); 81c83d9bedSSaar Raz } 82c83d9bedSSaar Raz 83c2bf9bafSJens Massberg ConceptSpecializationExpr * 84c2bf9bafSJens Massberg ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, 85975740bfSErich Keane ImplicitConceptSpecializationDecl *SpecDecl, 86c2bf9bafSJens Massberg const ConstraintSatisfaction *Satisfaction, 87c2bf9bafSJens Massberg bool Dependent, 88c83d9bedSSaar Raz bool ContainsUnexpandedParameterPack) { 89c2bf9bafSJens Massberg return new (C) 90c2bf9bafSJens Massberg ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent, 911f48a1fcSWalter Gray ContainsUnexpandedParameterPack); 92a0f50d73SSaar Raz } 93a0f50d73SSaar Raz 94a0f50d73SSaar Raz const TypeConstraint * 95a0f50d73SSaar Raz concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { 96a0f50d73SSaar Raz assert(isTypeConstraint()); 97*63d9ef5eSKazu Hirata auto TPL = cast<TemplateParameterList *>(TypeConstraintInfo.getPointer()); 98a0f50d73SSaar Raz return cast<TemplateTypeParmDecl>(TPL->getParam(0)) 99a0f50d73SSaar Raz ->getTypeConstraint(); 100a0f50d73SSaar Raz } 101a0f50d73SSaar Raz 10298ea4712SErich Keane // Search through the requirements, and see if any have a RecoveryExpr in it, 10398ea4712SErich Keane // which means this RequiresExpr ALSO needs to be invalid. 10498ea4712SErich Keane static bool RequirementContainsError(concepts::Requirement *R) { 10598ea4712SErich Keane if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R)) 10698ea4712SErich Keane return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors(); 10798ea4712SErich Keane 10898ea4712SErich Keane if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R)) 10998ea4712SErich Keane return !NestedReq->hasInvalidConstraint() && 11098ea4712SErich Keane NestedReq->getConstraintExpr() && 11198ea4712SErich Keane NestedReq->getConstraintExpr()->containsErrors(); 11298ea4712SErich Keane return false; 11398ea4712SErich Keane } 11498ea4712SErich Keane 115a0f50d73SSaar Raz RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, 1164b163e34SRichard Smith RequiresExprBodyDecl *Body, SourceLocation LParenLoc, 117a0f50d73SSaar Raz ArrayRef<ParmVarDecl *> LocalParameters, 1184b163e34SRichard Smith SourceLocation RParenLoc, 119a0f50d73SSaar Raz ArrayRef<concepts::Requirement *> Requirements, 120a0f50d73SSaar Raz SourceLocation RBraceLoc) 121aef5d8fdSMatheus Izvekov : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 122a0f50d73SSaar Raz NumLocalParameters(LocalParameters.size()), 1234b163e34SRichard Smith NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc), 1244b163e34SRichard Smith RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) { 125a0f50d73SSaar Raz RequiresExprBits.IsSatisfied = false; 126a0f50d73SSaar Raz RequiresExprBits.RequiresKWLoc = RequiresKWLoc; 127a0f50d73SSaar Raz bool Dependent = false; 128a0f50d73SSaar Raz bool ContainsUnexpandedParameterPack = false; 129a0f50d73SSaar Raz for (ParmVarDecl *P : LocalParameters) { 130a0f50d73SSaar Raz Dependent |= P->getType()->isInstantiationDependentType(); 131a0f50d73SSaar Raz ContainsUnexpandedParameterPack |= 132a0f50d73SSaar Raz P->getType()->containsUnexpandedParameterPack(); 133a0f50d73SSaar Raz } 134a0f50d73SSaar Raz RequiresExprBits.IsSatisfied = true; 135a0f50d73SSaar Raz for (concepts::Requirement *R : Requirements) { 136a0f50d73SSaar Raz Dependent |= R->isDependent(); 137a0f50d73SSaar Raz ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack(); 138a0f50d73SSaar Raz if (!Dependent) { 139a0f50d73SSaar Raz RequiresExprBits.IsSatisfied = R->isSatisfied(); 140a0f50d73SSaar Raz if (!RequiresExprBits.IsSatisfied) 141a0f50d73SSaar Raz break; 142a0f50d73SSaar Raz } 14398ea4712SErich Keane 14498ea4712SErich Keane if (RequirementContainsError(R)) 14598ea4712SErich Keane setDependence(getDependence() | ExprDependence::Error); 146a0f50d73SSaar Raz } 147a0f50d73SSaar Raz std::copy(LocalParameters.begin(), LocalParameters.end(), 148a0f50d73SSaar Raz getTrailingObjects<ParmVarDecl *>()); 149a0f50d73SSaar Raz std::copy(Requirements.begin(), Requirements.end(), 150a0f50d73SSaar Raz getTrailingObjects<concepts::Requirement *>()); 151a0f50d73SSaar Raz RequiresExprBits.IsSatisfied |= Dependent; 152876bb86eSHaojian Wu // FIXME: move the computing dependency logic to ComputeDependence.h 153ec3060c7SIlya Biryukov if (ContainsUnexpandedParameterPack) 154b4f02d89SSam McCall setDependence(getDependence() | ExprDependence::UnexpandedPack); 155ec3060c7SIlya Biryukov // FIXME: this is incorrect for cases where we have a non-dependent 156ec3060c7SIlya Biryukov // requirement, but its parameters are instantiation-dependent. RequiresExpr 157ec3060c7SIlya Biryukov // should be instantiation-dependent if it has instantiation-dependent 158ec3060c7SIlya Biryukov // parameters. 159ec3060c7SIlya Biryukov if (Dependent) 160b4f02d89SSam McCall setDependence(getDependence() | ExprDependence::ValueInstantiation); 161a0f50d73SSaar Raz } 162a0f50d73SSaar Raz 163a0f50d73SSaar Raz RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, 164a0f50d73SSaar Raz unsigned NumLocalParameters, 165a0f50d73SSaar Raz unsigned NumRequirements) 166a0f50d73SSaar Raz : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), 167a0f50d73SSaar Raz NumRequirements(NumRequirements) { } 168a0f50d73SSaar Raz 1694b163e34SRichard Smith RequiresExpr *RequiresExpr::Create( 1704b163e34SRichard Smith ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, 1714b163e34SRichard Smith SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters, 1724b163e34SRichard Smith SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements, 173a0f50d73SSaar Raz SourceLocation RBraceLoc) { 174a0f50d73SSaar Raz void *Mem = 175a0f50d73SSaar Raz C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 176a0f50d73SSaar Raz LocalParameters.size(), Requirements.size()), 177a0f50d73SSaar Raz alignof(RequiresExpr)); 1784b163e34SRichard Smith return new (Mem) 1794b163e34SRichard Smith RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters, 1804b163e34SRichard Smith RParenLoc, Requirements, RBraceLoc); 181a0f50d73SSaar Raz } 182a0f50d73SSaar Raz 183a0f50d73SSaar Raz RequiresExpr * 184a0f50d73SSaar Raz RequiresExpr::Create(ASTContext &C, EmptyShell Empty, 185a0f50d73SSaar Raz unsigned NumLocalParameters, unsigned NumRequirements) { 186a0f50d73SSaar Raz void *Mem = 187a0f50d73SSaar Raz C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 188a0f50d73SSaar Raz NumLocalParameters, NumRequirements), 189a0f50d73SSaar Raz alignof(RequiresExpr)); 190a0f50d73SSaar Raz return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); 191a0f50d73SSaar Raz } 192