Home | History | Annotate | Line # | Download | only in AST
      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 
     31 using namespace clang;
     32 
     33 ConceptSpecializationExpr::ConceptSpecializationExpr(
     34     const ASTContext &C, NestedNameSpecifierLoc NNS,
     35     SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
     36     NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
     37     const ASTTemplateArgumentListInfo *ArgsAsWritten,
     38     ArrayRef<TemplateArgument> ConvertedArgs,
     39     const ConstraintSatisfaction *Satisfaction)
     40     : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
     41       ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
     42                        NamedConcept, ArgsAsWritten),
     43       NumTemplateArgs(ConvertedArgs.size()),
     44       Satisfaction(Satisfaction
     45                        ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
     46                        : nullptr) {
     47   setTemplateArguments(ConvertedArgs);
     48   setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
     49 
     50   // Currently guaranteed by the fact concepts can only be at namespace-scope.
     51   assert(!NestedNameSpec ||
     52          (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
     53           !NestedNameSpec.getNestedNameSpecifier()
     54               ->containsUnexpandedParameterPack()));
     55   assert((!isValueDependent() || isInstantiationDependent()) &&
     56          "should not be value-dependent");
     57 }
     58 
     59 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
     60     unsigned NumTemplateArgs)
     61     : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
     62       NumTemplateArgs(NumTemplateArgs) { }
     63 
     64 void ConceptSpecializationExpr::setTemplateArguments(
     65     ArrayRef<TemplateArgument> Converted) {
     66   assert(Converted.size() == NumTemplateArgs);
     67   std::uninitialized_copy(Converted.begin(), Converted.end(),
     68                           getTrailingObjects<TemplateArgument>());
     69 }
     70 
     71 ConceptSpecializationExpr *
     72 ConceptSpecializationExpr::Create(const ASTContext &C,
     73                                   NestedNameSpecifierLoc NNS,
     74                                   SourceLocation TemplateKWLoc,
     75                                   DeclarationNameInfo ConceptNameInfo,
     76                                   NamedDecl *FoundDecl,
     77                                   ConceptDecl *NamedConcept,
     78                                const ASTTemplateArgumentListInfo *ArgsAsWritten,
     79                                   ArrayRef<TemplateArgument> ConvertedArgs,
     80                                   const ConstraintSatisfaction *Satisfaction) {
     81   void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
     82                                 ConvertedArgs.size()));
     83   return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
     84                                                 ConceptNameInfo, FoundDecl,
     85                                                 NamedConcept, ArgsAsWritten,
     86                                                 ConvertedArgs, Satisfaction);
     87 }
     88 
     89 ConceptSpecializationExpr::ConceptSpecializationExpr(
     90     const ASTContext &C, ConceptDecl *NamedConcept,
     91     ArrayRef<TemplateArgument> ConvertedArgs,
     92     const ConstraintSatisfaction *Satisfaction, bool Dependent,
     93     bool ContainsUnexpandedParameterPack)
     94     : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
     95       ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
     96                        DeclarationNameInfo(), NamedConcept, NamedConcept,
     97                        nullptr),
     98       NumTemplateArgs(ConvertedArgs.size()),
     99       Satisfaction(Satisfaction
    100                        ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
    101                        : nullptr) {
    102   setTemplateArguments(ConvertedArgs);
    103   ExprDependence D = ExprDependence::None;
    104   if (!Satisfaction)
    105     D |= ExprDependence::Value;
    106   if (Dependent)
    107     D |= ExprDependence::Instantiation;
    108   if (ContainsUnexpandedParameterPack)
    109     D |= ExprDependence::UnexpandedPack;
    110   setDependence(D);
    111 }
    112 
    113 ConceptSpecializationExpr *
    114 ConceptSpecializationExpr::Create(const ASTContext &C,
    115                                   ConceptDecl *NamedConcept,
    116                                   ArrayRef<TemplateArgument> ConvertedArgs,
    117                                   const ConstraintSatisfaction *Satisfaction,
    118                                   bool Dependent,
    119                                   bool ContainsUnexpandedParameterPack) {
    120   void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
    121                                 ConvertedArgs.size()));
    122   return new (Buffer) ConceptSpecializationExpr(
    123       C, NamedConcept, ConvertedArgs, Satisfaction, Dependent,
    124       ContainsUnexpandedParameterPack);
    125 }
    126 
    127 ConceptSpecializationExpr *
    128 ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
    129                                   unsigned NumTemplateArgs) {
    130   void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
    131                                 NumTemplateArgs));
    132   return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
    133 }
    134 
    135 const TypeConstraint *
    136 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
    137   assert(isTypeConstraint());
    138   auto TPL =
    139       TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
    140   return cast<TemplateTypeParmDecl>(TPL->getParam(0))
    141       ->getTypeConstraint();
    142 }
    143 
    144 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
    145                            RequiresExprBodyDecl *Body,
    146                            ArrayRef<ParmVarDecl *> LocalParameters,
    147                            ArrayRef<concepts::Requirement *> Requirements,
    148                            SourceLocation RBraceLoc)
    149     : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
    150       NumLocalParameters(LocalParameters.size()),
    151       NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
    152   RequiresExprBits.IsSatisfied = false;
    153   RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
    154   bool Dependent = false;
    155   bool ContainsUnexpandedParameterPack = false;
    156   for (ParmVarDecl *P : LocalParameters) {
    157     Dependent |= P->getType()->isInstantiationDependentType();
    158     ContainsUnexpandedParameterPack |=
    159         P->getType()->containsUnexpandedParameterPack();
    160   }
    161   RequiresExprBits.IsSatisfied = true;
    162   for (concepts::Requirement *R : Requirements) {
    163     Dependent |= R->isDependent();
    164     ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
    165     if (!Dependent) {
    166       RequiresExprBits.IsSatisfied = R->isSatisfied();
    167       if (!RequiresExprBits.IsSatisfied)
    168         break;
    169     }
    170   }
    171   std::copy(LocalParameters.begin(), LocalParameters.end(),
    172             getTrailingObjects<ParmVarDecl *>());
    173   std::copy(Requirements.begin(), Requirements.end(),
    174             getTrailingObjects<concepts::Requirement *>());
    175   RequiresExprBits.IsSatisfied |= Dependent;
    176   // FIXME: move the computing dependency logic to ComputeDependence.h
    177   if (ContainsUnexpandedParameterPack)
    178     setDependence(getDependence() | ExprDependence::UnexpandedPack);
    179   // FIXME: this is incorrect for cases where we have a non-dependent
    180   // requirement, but its parameters are instantiation-dependent. RequiresExpr
    181   // should be instantiation-dependent if it has instantiation-dependent
    182   // parameters.
    183   if (Dependent)
    184     setDependence(getDependence() | ExprDependence::ValueInstantiation);
    185 }
    186 
    187 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
    188                            unsigned NumLocalParameters,
    189                            unsigned NumRequirements)
    190   : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
    191     NumRequirements(NumRequirements) { }
    192 
    193 RequiresExpr *
    194 RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
    195                      RequiresExprBodyDecl *Body,
    196                      ArrayRef<ParmVarDecl *> LocalParameters,
    197                      ArrayRef<concepts::Requirement *> Requirements,
    198                      SourceLocation RBraceLoc) {
    199   void *Mem =
    200       C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
    201                      LocalParameters.size(), Requirements.size()),
    202                  alignof(RequiresExpr));
    203   return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
    204                                 Requirements, RBraceLoc);
    205 }
    206 
    207 RequiresExpr *
    208 RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
    209                      unsigned NumLocalParameters, unsigned NumRequirements) {
    210   void *Mem =
    211       C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
    212                      NumLocalParameters, NumRequirements),
    213                  alignof(RequiresExpr));
    214   return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
    215 }
    216