Skip to content

Commit

Permalink
[Concepts] Requires Expressions
Browse files Browse the repository at this point in the history
Implement support for C++2a requires-expressions.

Re-commit after compilation failure on some platforms due to alignment issues with PointerIntPair.

Differential Revision: https://reviews.llvm.org/D50360

(cherry picked from commit a0f50d7)
  • Loading branch information
saarraz committed Jan 24, 2020
1 parent ab514b9 commit c96ef51
Show file tree
Hide file tree
Showing 66 changed files with 3,811 additions and 302 deletions.
1 change: 1 addition & 0 deletions clang/include/clang/AST/ASTConcept.h
Expand Up @@ -22,6 +22,7 @@
#include <utility>
namespace clang {
class ConceptDecl;
class ConceptSpecializationExpr;

/// \brief The result of a constraint satisfaction check, containing the
/// necessary information to diagnose an unsatisfied constraint.
Expand Down
31 changes: 31 additions & 0 deletions clang/include/clang/AST/DeclCXX.h
Expand Up @@ -1893,6 +1893,37 @@ class CXXDeductionGuideDecl : public FunctionDecl {
static bool classofKind(Kind K) { return K == CXXDeductionGuide; }
};

/// \brief Represents the body of a requires-expression.
///
/// This decl exists merely to serve as the DeclContext for the local
/// parameters of the requires expression as well as other declarations inside
/// it.
///
/// \code
/// template<typename T> requires requires (T t) { {t++} -> regular; }
/// \endcode
///
/// In this example, a RequiresExpr object will be generated for the expression,
/// and a RequiresExprBodyDecl will be created to hold the parameter t and the
/// template argument list imposed by the compound requirement.
class RequiresExprBodyDecl : public Decl, public DeclContext {
RequiresExprBodyDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc)
: Decl(RequiresExprBody, DC, StartLoc), DeclContext(RequiresExprBody) {}

public:
friend class ASTDeclReader;
friend class ASTDeclWriter;

static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation StartLoc);

static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, unsigned ID);

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == RequiresExprBody; }
};

/// Represents a static or instance method of a struct/union/class.
///
/// In the terminology of the C++ Standard, these are the (static and
Expand Down
94 changes: 0 additions & 94 deletions clang/include/clang/AST/ExprCXX.h
Expand Up @@ -14,7 +14,6 @@
#ifndef LLVM_CLANG_AST_EXPRCXX_H
#define LLVM_CLANG_AST_EXPRCXX_H

#include "clang/AST/ASTConcept.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
Expand Down Expand Up @@ -4836,99 +4835,6 @@ class BuiltinBitCastExpr final
}
};

/// \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 concept results in a prvalue of type bool.
class ConceptSpecializationExpr final : public Expr, public ConceptReference,
private llvm::TrailingObjects<ConceptSpecializationExpr,
TemplateArgument> {
friend class ASTStmtReader;
friend TrailingObjects;
public:
using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;

protected:
/// \brief The number of template arguments in the tail-allocated list of
/// converted template arguments.
unsigned NumTemplateArgs;

/// \brief Information about the satisfaction of the named concept with the
/// given arguments. If this expression is value dependent, this is to be
/// ignored.
ASTConstraintSatisfaction *Satisfaction;

ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction);

ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);

public:

static ConceptSpecializationExpr *
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten,
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction);

static ConceptSpecializationExpr *
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);

ArrayRef<TemplateArgument> getTemplateArguments() const {
return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
NumTemplateArgs);
}

/// \brief Set new template arguments for this concept specialization.
void setTemplateArguments(ArrayRef<TemplateArgument> Converted);

/// \brief Whether or not the concept with the given arguments was satisfied
/// when the expression was created.
/// The expression must not be dependent.
bool isSatisfied() const {
assert(!isValueDependent()
&& "isSatisfied called on a dependent ConceptSpecializationExpr");
return Satisfaction->IsSatisfied;
}

/// \brief Get elaborated satisfaction info about the template arguments'
/// satisfaction of the named concept.
/// The expression must not be dependent.
const ASTConstraintSatisfaction &getSatisfaction() const {
assert(!isValueDependent()
&& "getSatisfaction called on dependent ConceptSpecializationExpr");
return *Satisfaction;
}

static bool classof(const Stmt *T) {
return T->getStmtClass() == ConceptSpecializationExprClass;
}

SourceLocation getBeginLoc() const LLVM_READONLY {
return ConceptName.getBeginLoc();
}

SourceLocation getEndLoc() const LLVM_READONLY {
return ArgsAsWritten->RAngleLoc;
}

// Iterators
child_range children() {
return child_range(child_iterator(), child_iterator());
}
const_child_range children() const {
return const_child_range(const_child_iterator(), const_child_iterator());
}
};

} // namespace clang

#endif // LLVM_CLANG_AST_EXPRCXX_H

0 comments on commit c96ef51

Please sign in to comment.