Home | History | Annotate | Line # | Download | only in AST
      1 //===--- ASTConcept.h - Concepts Related AST Data Structures ----*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief This file provides AST data structures related to concepts.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef LLVM_CLANG_AST_ASTCONCEPT_H
     16 #define LLVM_CLANG_AST_ASTCONCEPT_H
     17 #include "clang/AST/Expr.h"
     18 #include "clang/Basic/SourceLocation.h"
     19 #include "llvm/ADT/PointerUnion.h"
     20 #include "llvm/ADT/SmallVector.h"
     21 #include <string>
     22 #include <utility>
     23 namespace clang {
     24 class ConceptDecl;
     25 class ConceptSpecializationExpr;
     26 
     27 /// The result of a constraint satisfaction check, containing the necessary
     28 /// information to diagnose an unsatisfied constraint.
     29 class ConstraintSatisfaction : public llvm::FoldingSetNode {
     30   // The template-like entity that 'owns' the constraint checked here (can be a
     31   // constrained entity or a concept).
     32   const NamedDecl *ConstraintOwner = nullptr;
     33   llvm::SmallVector<TemplateArgument, 4> TemplateArgs;
     34 
     35 public:
     36 
     37   ConstraintSatisfaction() = default;
     38 
     39   ConstraintSatisfaction(const NamedDecl *ConstraintOwner,
     40                          ArrayRef<TemplateArgument> TemplateArgs) :
     41       ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(),
     42                                                      TemplateArgs.end()) { }
     43 
     44   using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
     45   using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
     46 
     47   bool IsSatisfied = false;
     48 
     49   /// \brief Pairs of unsatisfied atomic constraint expressions along with the
     50   /// substituted constraint expr, if the template arguments could be
     51   /// substituted into them, or a diagnostic if substitution resulted in an
     52   /// invalid expression.
     53   llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
     54 
     55   void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
     56     Profile(ID, C, ConstraintOwner, TemplateArgs);
     57   }
     58 
     59   static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
     60                       const NamedDecl *ConstraintOwner,
     61                       ArrayRef<TemplateArgument> TemplateArgs);
     62 };
     63 
     64 /// Pairs of unsatisfied atomic constraint expressions along with the
     65 /// substituted constraint expr, if the template arguments could be
     66 /// substituted into them, or a diagnostic if substitution resulted in
     67 /// an invalid expression.
     68 using UnsatisfiedConstraintRecord =
     69     std::pair<const Expr *,
     70               llvm::PointerUnion<Expr *,
     71                                  std::pair<SourceLocation, StringRef> *>>;
     72 
     73 /// \brief The result of a constraint satisfaction check, containing the
     74 /// necessary information to diagnose an unsatisfied constraint.
     75 ///
     76 /// This is safe to store in an AST node, as opposed to ConstraintSatisfaction.
     77 struct ASTConstraintSatisfaction final :
     78     llvm::TrailingObjects<ASTConstraintSatisfaction,
     79                           UnsatisfiedConstraintRecord> {
     80   std::size_t NumRecords;
     81   bool IsSatisfied : 1;
     82 
     83   const UnsatisfiedConstraintRecord *begin() const {
     84     return getTrailingObjects<UnsatisfiedConstraintRecord>();
     85   }
     86 
     87   const UnsatisfiedConstraintRecord *end() const {
     88     return getTrailingObjects<UnsatisfiedConstraintRecord>() + NumRecords;
     89   }
     90 
     91   ASTConstraintSatisfaction(const ASTContext &C,
     92                             const ConstraintSatisfaction &Satisfaction);
     93 
     94   static ASTConstraintSatisfaction *
     95   Create(const ASTContext &C, const ConstraintSatisfaction &Satisfaction);
     96 };
     97 
     98 /// \brief Common data class for constructs that reference concepts with
     99 /// template arguments.
    100 class ConceptReference {
    101 protected:
    102   // \brief The optional nested name specifier used when naming the concept.
    103   NestedNameSpecifierLoc NestedNameSpec;
    104 
    105   /// \brief The location of the template keyword, if specified when naming the
    106   /// concept.
    107   SourceLocation TemplateKWLoc;
    108 
    109   /// \brief The concept name used.
    110   DeclarationNameInfo ConceptName;
    111 
    112   /// \brief The declaration found by name lookup when the expression was
    113   /// created.
    114   /// Can differ from NamedConcept when, for example, the concept was found
    115   /// through a UsingShadowDecl.
    116   NamedDecl *FoundDecl;
    117 
    118   /// \brief The concept named.
    119   ConceptDecl *NamedConcept;
    120 
    121   /// \brief The template argument list source info used to specialize the
    122   /// concept.
    123   const ASTTemplateArgumentListInfo *ArgsAsWritten;
    124 
    125 public:
    126 
    127   ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
    128                    DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
    129                    ConceptDecl *NamedConcept,
    130                    const ASTTemplateArgumentListInfo *ArgsAsWritten) :
    131       NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
    132       ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
    133       NamedConcept(NamedConcept), ArgsAsWritten(ArgsAsWritten) {}
    134 
    135   ConceptReference() : NestedNameSpec(), TemplateKWLoc(), ConceptName(),
    136       FoundDecl(nullptr), NamedConcept(nullptr), ArgsAsWritten(nullptr) {}
    137 
    138   const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
    139     return NestedNameSpec;
    140   }
    141 
    142   const DeclarationNameInfo &getConceptNameInfo() const { return ConceptName; }
    143 
    144   SourceLocation getConceptNameLoc() const {
    145     return getConceptNameInfo().getLoc();
    146   }
    147 
    148   SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
    149 
    150   NamedDecl *getFoundDecl() const {
    151     return FoundDecl;
    152   }
    153 
    154   ConceptDecl *getNamedConcept() const {
    155     return NamedConcept;
    156   }
    157 
    158   const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
    159     return ArgsAsWritten;
    160   }
    161 
    162   /// \brief Whether or not template arguments were explicitly specified in the
    163   /// concept reference (they might not be in type constraints, for example)
    164   bool hasExplicitTemplateArgs() const {
    165     return ArgsAsWritten != nullptr;
    166   }
    167 };
    168 
    169 class TypeConstraint : public ConceptReference {
    170   /// \brief The immediately-declared constraint expression introduced by this
    171   /// type-constraint.
    172   Expr *ImmediatelyDeclaredConstraint = nullptr;
    173 
    174 public:
    175   TypeConstraint(NestedNameSpecifierLoc NNS,
    176                  DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
    177                  ConceptDecl *NamedConcept,
    178                  const ASTTemplateArgumentListInfo *ArgsAsWritten,
    179                  Expr *ImmediatelyDeclaredConstraint) :
    180       ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), ConceptNameInfo,
    181                        FoundDecl, NamedConcept, ArgsAsWritten),
    182       ImmediatelyDeclaredConstraint(ImmediatelyDeclaredConstraint) {}
    183 
    184   /// \brief Get the immediately-declared constraint expression introduced by
    185   /// this type-constraint, that is - the constraint expression that is added to
    186   /// the associated constraints of the enclosing declaration in practice.
    187   Expr *getImmediatelyDeclaredConstraint() const {
    188     return ImmediatelyDeclaredConstraint;
    189   }
    190 
    191   void print(llvm::raw_ostream &OS, PrintingPolicy Policy) const;
    192 };
    193 
    194 } // clang
    195 
    196 #endif // LLVM_CLANG_AST_ASTCONCEPT_H
    197