llvm-project
195 строк · 8.2 Кб
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/ASTConcept.h"15#include "clang/AST/ASTContext.h"16#include "clang/AST/ComputeDependence.h"17#include "clang/AST/Decl.h"18#include "clang/AST/DeclTemplate.h"19#include "clang/AST/DeclarationName.h"20#include "clang/AST/DependenceFlags.h"21#include "clang/AST/Expr.h"22#include "clang/AST/NestedNameSpecifier.h"23#include "clang/AST/TemplateBase.h"24#include "clang/AST/Type.h"25#include "clang/Basic/SourceLocation.h"26#include "llvm/Support/TrailingObjects.h"27#include <algorithm>28#include <string>29#include <utility>30
31using namespace clang;32
33ConceptSpecializationExpr::ConceptSpecializationExpr(34const ASTContext &C, ConceptReference *Loc,35ImplicitConceptSpecializationDecl *SpecDecl,36const ConstraintSatisfaction *Satisfaction)37: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),38ConceptRef(Loc), SpecDecl(SpecDecl),39Satisfaction(Satisfaction40? ASTConstraintSatisfaction::Create(C, *Satisfaction)41: nullptr) {42setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));43
44// Currently guaranteed by the fact concepts can only be at namespace-scope.45assert(!Loc->getNestedNameSpecifierLoc() ||46(!Loc->getNestedNameSpecifierLoc()47.getNestedNameSpecifier()48->isInstantiationDependent() &&49!Loc->getNestedNameSpecifierLoc()50.getNestedNameSpecifier()51->containsUnexpandedParameterPack()));52assert((!isValueDependent() || isInstantiationDependent()) &&53"should not be value-dependent");54}
55
56ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)57: Expr(ConceptSpecializationExprClass, Empty) {}58
59ConceptSpecializationExpr *60ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,61ImplicitConceptSpecializationDecl *SpecDecl,62const ConstraintSatisfaction *Satisfaction) {63return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);64}
65
66ConceptSpecializationExpr::ConceptSpecializationExpr(67const ASTContext &C, ConceptReference *Loc,68ImplicitConceptSpecializationDecl *SpecDecl,69const ConstraintSatisfaction *Satisfaction, bool Dependent,70bool ContainsUnexpandedParameterPack)71: Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),72ConceptRef(Loc), SpecDecl(SpecDecl),73Satisfaction(Satisfaction74? ASTConstraintSatisfaction::Create(C, *Satisfaction)75: nullptr) {76ExprDependence D = ExprDependence::None;77if (!Satisfaction)78D |= ExprDependence::Value;79if (Dependent)80D |= ExprDependence::Instantiation;81if (ContainsUnexpandedParameterPack)82D |= ExprDependence::UnexpandedPack;83setDependence(D);84}
85
86ConceptSpecializationExpr *87ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,88ImplicitConceptSpecializationDecl *SpecDecl,89const ConstraintSatisfaction *Satisfaction,90bool Dependent,91bool ContainsUnexpandedParameterPack) {92return new (C)93ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,94ContainsUnexpandedParameterPack);95}
96
97const TypeConstraint *98concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {99assert(isTypeConstraint());100auto TPL =101TypeConstraintInfo.getPointer().get<TemplateParameterList *>();102return cast<TemplateTypeParmDecl>(TPL->getParam(0))103->getTypeConstraint();104}
105
106// Search through the requirements, and see if any have a RecoveryExpr in it,
107// which means this RequiresExpr ALSO needs to be invalid.
108static bool RequirementContainsError(concepts::Requirement *R) {109if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))110return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();111
112if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))113return !NestedReq->hasInvalidConstraint() &&114NestedReq->getConstraintExpr() &&115NestedReq->getConstraintExpr()->containsErrors();116return false;117}
118
119RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,120RequiresExprBodyDecl *Body, SourceLocation LParenLoc,121ArrayRef<ParmVarDecl *> LocalParameters,122SourceLocation RParenLoc,123ArrayRef<concepts::Requirement *> Requirements,124SourceLocation RBraceLoc)125: Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),126NumLocalParameters(LocalParameters.size()),127NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),128RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {129RequiresExprBits.IsSatisfied = false;130RequiresExprBits.RequiresKWLoc = RequiresKWLoc;131bool Dependent = false;132bool ContainsUnexpandedParameterPack = false;133for (ParmVarDecl *P : LocalParameters) {134Dependent |= P->getType()->isInstantiationDependentType();135ContainsUnexpandedParameterPack |=136P->getType()->containsUnexpandedParameterPack();137}138RequiresExprBits.IsSatisfied = true;139for (concepts::Requirement *R : Requirements) {140Dependent |= R->isDependent();141ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();142if (!Dependent) {143RequiresExprBits.IsSatisfied = R->isSatisfied();144if (!RequiresExprBits.IsSatisfied)145break;146}147
148if (RequirementContainsError(R))149setDependence(getDependence() | ExprDependence::Error);150}151std::copy(LocalParameters.begin(), LocalParameters.end(),152getTrailingObjects<ParmVarDecl *>());153std::copy(Requirements.begin(), Requirements.end(),154getTrailingObjects<concepts::Requirement *>());155RequiresExprBits.IsSatisfied |= Dependent;156// FIXME: move the computing dependency logic to ComputeDependence.h157if (ContainsUnexpandedParameterPack)158setDependence(getDependence() | ExprDependence::UnexpandedPack);159// FIXME: this is incorrect for cases where we have a non-dependent160// requirement, but its parameters are instantiation-dependent. RequiresExpr161// should be instantiation-dependent if it has instantiation-dependent162// parameters.163if (Dependent)164setDependence(getDependence() | ExprDependence::ValueInstantiation);165}
166
167RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,168unsigned NumLocalParameters,169unsigned NumRequirements)170: Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),171NumRequirements(NumRequirements) { }172
173RequiresExpr *RequiresExpr::Create(174ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,175SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,176SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,177SourceLocation RBraceLoc) {178void *Mem =179C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(180LocalParameters.size(), Requirements.size()),181alignof(RequiresExpr));182return new (Mem)183RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,184RParenLoc, Requirements, RBraceLoc);185}
186
187RequiresExpr *188RequiresExpr::Create(ASTContext &C, EmptyShell Empty,189unsigned NumLocalParameters, unsigned NumRequirements) {190void *Mem =191C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(192NumLocalParameters, NumRequirements),193alignof(RequiresExpr));194return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);195}
196