aboutsummaryrefslogtreecommitdiff
path: root/include/clang/AST/DeclTemplate.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/DeclTemplate.h')
-rw-r--r--include/clang/AST/DeclTemplate.h81
1 files changed, 53 insertions, 28 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index d553e739c388..2af95c02c460 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -21,7 +21,6 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
-#include <limits>
#include <utility>
namespace clang {
@@ -49,7 +48,8 @@ NamedDecl *getAsNamedDecl(TemplateParameter P);
/// \brief Stores a list of template parameters for a TemplateDecl and its
/// derived classes.
class TemplateParameterList final
- : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *> {
+ : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *,
+ Expr *> {
/// The location of the 'template' keyword.
SourceLocation TemplateLoc;
@@ -59,26 +59,35 @@ class TemplateParameterList final
/// The number of template parameters in this template
/// parameter list.
- unsigned NumParams : 31;
+ unsigned NumParams : 30;
/// Whether this template parameter list contains an unexpanded parameter
/// pack.
unsigned ContainsUnexpandedParameterPack : 1;
+ /// Whether this template parameter list has an associated requires-clause
+ unsigned HasRequiresClause : 1;
+
protected:
size_t numTrailingObjects(OverloadToken<NamedDecl *>) const {
return NumParams;
}
+ size_t numTrailingObjects(OverloadToken<Expr *>) const {
+ return HasRequiresClause;
+ }
+
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
- ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc);
+ ArrayRef<NamedDecl *> Params, SourceLocation RAngleLoc,
+ Expr *RequiresClause);
public:
static TemplateParameterList *Create(const ASTContext &C,
SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc);
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause);
/// \brief Iterates through the template parameters in this list.
typedef NamedDecl** iterator;
@@ -130,6 +139,16 @@ public:
return ContainsUnexpandedParameterPack;
}
+ /// \brief The constraint-expression of the associated requires-clause.
+ Expr *getRequiresClause() {
+ return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
+ }
+
+ /// \brief The constraint-expression of the associated requires-clause.
+ const Expr *getRequiresClause() const {
+ return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
+ }
+
SourceLocation getTemplateLoc() const { return TemplateLoc; }
SourceLocation getLAngleLoc() const { return LAngleLoc; }
SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -139,36 +158,37 @@ public:
}
friend TrailingObjects;
- template <size_t N> friend class FixedSizeTemplateParameterListStorage;
+
+ template <size_t N, bool HasRequiresClause>
+ friend class FixedSizeTemplateParameterListStorage;
+
+public:
+ // FIXME: workaround for MSVC 2013; remove when no longer needed
+ using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner;
};
-/// \brief Stores a list of template parameters for a TemplateDecl and its
-/// derived classes. Suitable for creating on the stack.
-template <size_t N> class FixedSizeTemplateParameterListStorage {
- // This is kinda ugly: TemplateParameterList usually gets allocated
- // in a block of memory with NamedDecls appended to it. Here, to get
- // it stack allocated, we include the params as a separate
- // variable. After allocation, the TemplateParameterList object
- // treats them as part of itself.
- TemplateParameterList List;
- NamedDecl *Params[N];
+/// \brief Stores a list of template parameters and the associated
+/// requires-clause (if any) for a TemplateDecl and its derived classes.
+/// Suitable for creating on the stack.
+template <size_t N, bool HasRequiresClause>
+class FixedSizeTemplateParameterListStorage
+ : public TemplateParameterList::FixedSizeStorageOwner {
+ typename TemplateParameterList::FixedSizeStorage<
+ NamedDecl *, Expr *>::with_counts<
+ N, HasRequiresClause ? 1u : 0u
+ >::type storage;
public:
FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc,
SourceLocation LAngleLoc,
ArrayRef<NamedDecl *> Params,
- SourceLocation RAngleLoc)
- : List(TemplateLoc, LAngleLoc, Params, RAngleLoc) {
- // Because we're doing an evil layout hack above, have some
- // asserts, just to double-check everything is laid out like
- // expected.
- assert(sizeof(*this) ==
- TemplateParameterList::totalSizeToAlloc<NamedDecl *>(N) &&
- "Object layout not as expected");
- assert(this->Params == List.getTrailingObjects<NamedDecl *>() &&
- "Object layout not as expected");
- }
- TemplateParameterList *get() { return &List; }
+ SourceLocation RAngleLoc,
+ Expr *RequiresClause)
+ : FixedSizeStorageOwner(
+ (assert(N == Params.size()),
+ assert(HasRequiresClause == static_cast<bool>(RequiresClause)),
+ new (static_cast<void *>(&storage)) TemplateParameterList(
+ TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {}
};
/// \brief A template argument list.
@@ -356,6 +376,11 @@ public:
return TemplateParams;
}
+ /// Get the constraint-expression from the associated requires-clause (if any)
+ const Expr *getRequiresClause() const {
+ return TemplateParams ? TemplateParams->getRequiresClause() : nullptr;
+ }
+
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); }