Path: blob/main/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp
35260 views
//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the subclesses of Expr class declared in ExprCXX.h9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/ExprConcepts.h"13#include "clang/AST/ASTConcept.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/ComputeDependence.h"16#include "clang/AST/Decl.h"17#include "clang/AST/DeclTemplate.h"18#include "clang/AST/DeclarationName.h"19#include "clang/AST/DependenceFlags.h"20#include "clang/AST/Expr.h"21#include "clang/AST/NestedNameSpecifier.h"22#include "clang/AST/TemplateBase.h"23#include "clang/AST/Type.h"24#include "clang/Basic/SourceLocation.h"25#include "llvm/Support/TrailingObjects.h"26#include <algorithm>27#include <string>28#include <utility>2930using namespace clang;3132ConceptSpecializationExpr::ConceptSpecializationExpr(33const ASTContext &C, ConceptReference *Loc,34ImplicitConceptSpecializationDecl *SpecDecl,35const ConstraintSatisfaction *Satisfaction)36: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),37ConceptRef(Loc), SpecDecl(SpecDecl),38Satisfaction(Satisfaction39? ASTConstraintSatisfaction::Create(C, *Satisfaction)40: nullptr) {41setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));4243// Currently guaranteed by the fact concepts can only be at namespace-scope.44assert(!Loc->getNestedNameSpecifierLoc() ||45(!Loc->getNestedNameSpecifierLoc()46.getNestedNameSpecifier()47->isInstantiationDependent() &&48!Loc->getNestedNameSpecifierLoc()49.getNestedNameSpecifier()50->containsUnexpandedParameterPack()));51assert((!isValueDependent() || isInstantiationDependent()) &&52"should not be value-dependent");53}5455ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)56: Expr(ConceptSpecializationExprClass, Empty) {}5758ConceptSpecializationExpr *59ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,60ImplicitConceptSpecializationDecl *SpecDecl,61const ConstraintSatisfaction *Satisfaction) {62return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);63}6465ConceptSpecializationExpr::ConceptSpecializationExpr(66const ASTContext &C, ConceptReference *Loc,67ImplicitConceptSpecializationDecl *SpecDecl,68const ConstraintSatisfaction *Satisfaction, bool Dependent,69bool ContainsUnexpandedParameterPack)70: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),71ConceptRef(Loc), SpecDecl(SpecDecl),72Satisfaction(Satisfaction73? ASTConstraintSatisfaction::Create(C, *Satisfaction)74: nullptr) {75ExprDependence D = ExprDependence::None;76if (!Satisfaction)77D |= ExprDependence::Value;78if (Dependent)79D |= ExprDependence::Instantiation;80if (ContainsUnexpandedParameterPack)81D |= ExprDependence::UnexpandedPack;82setDependence(D);83}8485ConceptSpecializationExpr *86ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,87ImplicitConceptSpecializationDecl *SpecDecl,88const ConstraintSatisfaction *Satisfaction,89bool Dependent,90bool ContainsUnexpandedParameterPack) {91return new (C)92ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,93ContainsUnexpandedParameterPack);94}9596const TypeConstraint *97concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {98assert(isTypeConstraint());99auto TPL =100TypeConstraintInfo.getPointer().get<TemplateParameterList *>();101return cast<TemplateTypeParmDecl>(TPL->getParam(0))102->getTypeConstraint();103}104105// Search through the requirements, and see if any have a RecoveryExpr in it,106// which means this RequiresExpr ALSO needs to be invalid.107static bool RequirementContainsError(concepts::Requirement *R) {108if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))109return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();110111if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))112return !NestedReq->hasInvalidConstraint() &&113NestedReq->getConstraintExpr() &&114NestedReq->getConstraintExpr()->containsErrors();115return false;116}117118RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,119RequiresExprBodyDecl *Body, SourceLocation LParenLoc,120ArrayRef<ParmVarDecl *> LocalParameters,121SourceLocation RParenLoc,122ArrayRef<concepts::Requirement *> Requirements,123SourceLocation RBraceLoc)124: Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),125NumLocalParameters(LocalParameters.size()),126NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),127RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {128RequiresExprBits.IsSatisfied = false;129RequiresExprBits.RequiresKWLoc = RequiresKWLoc;130bool Dependent = false;131bool ContainsUnexpandedParameterPack = false;132for (ParmVarDecl *P : LocalParameters) {133Dependent |= P->getType()->isInstantiationDependentType();134ContainsUnexpandedParameterPack |=135P->getType()->containsUnexpandedParameterPack();136}137RequiresExprBits.IsSatisfied = true;138for (concepts::Requirement *R : Requirements) {139Dependent |= R->isDependent();140ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();141if (!Dependent) {142RequiresExprBits.IsSatisfied = R->isSatisfied();143if (!RequiresExprBits.IsSatisfied)144break;145}146147if (RequirementContainsError(R))148setDependence(getDependence() | ExprDependence::Error);149}150std::copy(LocalParameters.begin(), LocalParameters.end(),151getTrailingObjects<ParmVarDecl *>());152std::copy(Requirements.begin(), Requirements.end(),153getTrailingObjects<concepts::Requirement *>());154RequiresExprBits.IsSatisfied |= Dependent;155// FIXME: move the computing dependency logic to ComputeDependence.h156if (ContainsUnexpandedParameterPack)157setDependence(getDependence() | ExprDependence::UnexpandedPack);158// FIXME: this is incorrect for cases where we have a non-dependent159// requirement, but its parameters are instantiation-dependent. RequiresExpr160// should be instantiation-dependent if it has instantiation-dependent161// parameters.162if (Dependent)163setDependence(getDependence() | ExprDependence::ValueInstantiation);164}165166RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,167unsigned NumLocalParameters,168unsigned NumRequirements)169: Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),170NumRequirements(NumRequirements) { }171172RequiresExpr *RequiresExpr::Create(173ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,174SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,175SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,176SourceLocation RBraceLoc) {177void *Mem =178C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(179LocalParameters.size(), Requirements.size()),180alignof(RequiresExpr));181return new (Mem)182RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,183RParenLoc, Requirements, RBraceLoc);184}185186RequiresExpr *187RequiresExpr::Create(ASTContext &C, EmptyShell Empty,188unsigned NumLocalParameters, unsigned NumRequirements) {189void *Mem =190C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(191NumLocalParameters, NumRequirements),192alignof(RequiresExpr));193return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);194}195196197