189 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the subclesses of Expr class declared in ExprCXX.h10//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 27using namespace clang;28 29ConceptSpecializationExpr::ConceptSpecializationExpr(30 const ASTContext &C, ConceptReference *Loc,31 ImplicitConceptSpecializationDecl *SpecDecl,32 const ConstraintSatisfaction *Satisfaction)33 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),34 ConceptRef(Loc), SpecDecl(SpecDecl),35 Satisfaction(Satisfaction36 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)37 : nullptr) {38 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));39 40 // Currently guaranteed by the fact concepts can only be at namespace-scope.41 assert(!Loc->getNestedNameSpecifierLoc() ||42 (!Loc->getNestedNameSpecifierLoc()43 .getNestedNameSpecifier()44 .isInstantiationDependent() &&45 !Loc->getNestedNameSpecifierLoc()46 .getNestedNameSpecifier()47 .containsUnexpandedParameterPack()));48 assert((!isValueDependent() || isInstantiationDependent()) &&49 "should not be value-dependent");50}51 52ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)53 : Expr(ConceptSpecializationExprClass, Empty) {}54 55ConceptSpecializationExpr *56ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,57 ImplicitConceptSpecializationDecl *SpecDecl,58 const ConstraintSatisfaction *Satisfaction) {59 return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);60}61 62ConceptSpecializationExpr::ConceptSpecializationExpr(63 const ASTContext &C, ConceptReference *Loc,64 ImplicitConceptSpecializationDecl *SpecDecl,65 const ConstraintSatisfaction *Satisfaction, bool Dependent,66 bool ContainsUnexpandedParameterPack)67 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),68 ConceptRef(Loc), SpecDecl(SpecDecl),69 Satisfaction(Satisfaction70 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)71 : nullptr) {72 ExprDependence D = ExprDependence::None;73 if (!Satisfaction)74 D |= ExprDependence::Value;75 if (Dependent)76 D |= ExprDependence::Instantiation;77 if (ContainsUnexpandedParameterPack)78 D |= ExprDependence::UnexpandedPack;79 setDependence(D);80}81 82ConceptSpecializationExpr *83ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,84 ImplicitConceptSpecializationDecl *SpecDecl,85 const ConstraintSatisfaction *Satisfaction,86 bool Dependent,87 bool ContainsUnexpandedParameterPack) {88 return new (C)89 ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,90 ContainsUnexpandedParameterPack);91}92 93const TypeConstraint *94concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {95 assert(isTypeConstraint());96 auto TPL = cast<TemplateParameterList *>(TypeConstraintInfo.getPointer());97 return cast<TemplateTypeParmDecl>(TPL->getParam(0))98 ->getTypeConstraint();99}100 101// Search through the requirements, and see if any have a RecoveryExpr in it,102// which means this RequiresExpr ALSO needs to be invalid.103static bool RequirementContainsError(concepts::Requirement *R) {104 if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))105 return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();106 107 if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))108 return !NestedReq->hasInvalidConstraint() &&109 NestedReq->getConstraintExpr() &&110 NestedReq->getConstraintExpr()->containsErrors();111 return false;112}113 114RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,115 RequiresExprBodyDecl *Body, SourceLocation LParenLoc,116 ArrayRef<ParmVarDecl *> LocalParameters,117 SourceLocation RParenLoc,118 ArrayRef<concepts::Requirement *> Requirements,119 SourceLocation RBraceLoc)120 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),121 NumLocalParameters(LocalParameters.size()),122 NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),123 RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {124 RequiresExprBits.IsSatisfied = false;125 RequiresExprBits.RequiresKWLoc = RequiresKWLoc;126 bool Dependent = false;127 bool ContainsUnexpandedParameterPack = false;128 for (ParmVarDecl *P : LocalParameters) {129 Dependent |= P->getType()->isInstantiationDependentType();130 ContainsUnexpandedParameterPack |=131 P->getType()->containsUnexpandedParameterPack();132 }133 RequiresExprBits.IsSatisfied = true;134 for (concepts::Requirement *R : Requirements) {135 Dependent |= R->isDependent();136 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();137 if (!Dependent) {138 RequiresExprBits.IsSatisfied = R->isSatisfied();139 if (!RequiresExprBits.IsSatisfied)140 break;141 }142 143 if (RequirementContainsError(R))144 setDependence(getDependence() | ExprDependence::Error);145 }146 llvm::copy(LocalParameters, getTrailingObjects<ParmVarDecl *>());147 llvm::copy(Requirements, getTrailingObjects<concepts::Requirement *>());148 RequiresExprBits.IsSatisfied |= Dependent;149 // FIXME: move the computing dependency logic to ComputeDependence.h150 if (ContainsUnexpandedParameterPack)151 setDependence(getDependence() | ExprDependence::UnexpandedPack);152 // FIXME: this is incorrect for cases where we have a non-dependent153 // requirement, but its parameters are instantiation-dependent. RequiresExpr154 // should be instantiation-dependent if it has instantiation-dependent155 // parameters.156 if (Dependent)157 setDependence(getDependence() | ExprDependence::ValueInstantiation);158}159 160RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,161 unsigned NumLocalParameters,162 unsigned NumRequirements)163 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),164 NumRequirements(NumRequirements) { }165 166RequiresExpr *RequiresExpr::Create(167 ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,168 SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,169 SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,170 SourceLocation RBraceLoc) {171 void *Mem =172 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(173 LocalParameters.size(), Requirements.size()),174 alignof(RequiresExpr));175 return new (Mem)176 RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,177 RParenLoc, Requirements, RBraceLoc);178}179 180RequiresExpr *181RequiresExpr::Create(ASTContext &C, EmptyShell Empty,182 unsigned NumLocalParameters, unsigned NumRequirements) {183 void *Mem =184 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(185 NumLocalParameters, NumRequirements),186 alignof(RequiresExpr));187 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);188}189