Index: include/clang/AST/DeclTemplate.h =================================================================== --- include/clang/AST/DeclTemplate.h +++ include/clang/AST/DeclTemplate.h @@ -3032,6 +3032,46 @@ static bool classofKind(Kind K) { return K == VarTemplate; } }; +// \brief Definition of concept, not just declaration actually. +class ConceptDecl : public TemplateDecl { +protected: + Expr *ConstraintExpr; + + ConceptDecl(DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, + Expr *ConstraintExpr) + : TemplateDecl(nullptr, Concept, DC, L, Name, Params), + ConstraintExpr(ConstraintExpr) {}; +public: + static ConceptDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, + Expr *ConstraintExpr); + static ConceptDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + Expr *getConstraintExpr() const { + return ConstraintExpr; + } + + void setConstraintExpr(Expr *CE) { + ConstraintExpr = CE; + } + + + SourceRange getSourceRange() const override LLVM_READONLY { + return SourceRange(getLocation(), getConstraintExpr()->getLocEnd()); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Concept; } + + friend class ASTReader; + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + inline NamedDecl *getAsNamedDecl(TemplateParameter P) { if (auto *PD = P.dyn_cast()) return PD; Index: include/clang/AST/ExprCXX.h =================================================================== --- include/clang/AST/ExprCXX.h +++ include/clang/AST/ExprCXX.h @@ -57,6 +57,8 @@ class LambdaCapture; class NonTypeTemplateParmDecl; class TemplateParameterList; +class ConceptDecl; +class Sema; //===--------------------------------------------------------------------===// // C++ Expressions. @@ -4407,6 +4409,96 @@ } }; +/// \brief Represents the specialization of a concept - evaluates to a prvalue +/// of type bool. +/// +/// According to C++2a [expr.prim.id]p3 an id-expression that denotes the +/// specialization of a concepts results in a prvalue of type bool. +class ConceptSpecializationExpr final : public Expr { +protected: + /// \brief The concept specialization this represents. + ConceptDecl *SpecializedConcept; + + /// \brief The template argument list used to specialize the concept. + TemplateArgumentList *TemplateArgs; + TemplateArgumentListInfo TemplateArgInfo; + + /// \brief The location of the concept name in the expression. + SourceLocation ConceptNameLoc; + + /// \brief Whether or not the concept with the given arguments was satisfied + /// when the expression was created. If any of the template arguments are + /// dependent (this expr would then be isValueDependent()), this is to be + /// ignored. + bool IsSatisfied : 1; + + /// \brief Evaluates this concept specialization to determine whether or not + /// the concept is satisfied. Returns true if an error occured and the concept + /// could not be checked for satisfaction. + bool evaluate(Sema &S); + +public: + ConceptSpecializationExpr(ASTContext &C, Sema &S, + SourceLocation ConceptNameLoc, ConceptDecl *CD, + const TemplateArgumentListInfo *TALI); + + ConceptSpecializationExpr(ASTContext &C); + + ConceptDecl *getSpecializedConcept() { + return SpecializedConcept; + } + const ConceptDecl *getSpecializedConcept() const { + return SpecializedConcept; + } + void setSpecializedConcept(ConceptDecl *C) { + SpecializedConcept = C; + } + + const TemplateArgumentList *getTemplateArguments() const { + return TemplateArgs; + } + const TemplateArgumentListInfo *getTemplateArgumentListInfo() const { + return &TemplateArgInfo; + } + + /// \brief Set new template arguments for this concept specialization. Returns + /// true if an error occured (the template arguments do not match the concept, + /// probably) + bool setTemplateArguments(Sema *S, const TemplateArgumentListInfo *TALI); + + /// \brief Whether or not the concept with the given arguments was satisfied + /// when the expression was created. This method assumes that the expression + /// is not dependent! + bool isSatisfied() const { + assert(!isValueDependent() + && "isSatisfied called on a dependent ConceptSpecializationExpr"); + return IsSatisfied; + } + + void setSatisfied(bool Satisfied) { + IsSatisfied = Satisfied; + } + + SourceLocation getConceptNameLoc() const { return ConceptNameLoc; } + void setConceptNameLoc(SourceLocation Loc) { + ConceptNameLoc = Loc; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConceptSpecializationExprClass; + } + + SourceLocation getLocStart() const LLVM_READONLY { return ConceptNameLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + return TemplateArgInfo.getRAngleLoc(); + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } +}; + } // namespace clang #endif // LLVM_CLANG_AST_EXPRCXX_H Index: include/clang/AST/RecursiveASTVisitor.h =================================================================== --- include/clang/AST/RecursiveASTVisitor.h +++ include/clang/AST/RecursiveASTVisitor.h @@ -1722,6 +1722,8 @@ DEF_TRAVERSE_TMPL_DECL(Var) DEF_TRAVERSE_TMPL_DECL(Function) +DEF_TRAVERSE_DECL(ConceptDecl, {}) + DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { // D is the "T" in something like // template