summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/ExprConcepts.h13
-rw-r--r--clang/lib/AST/ASTContext.cpp8
-rw-r--r--clang/lib/AST/ExprConcepts.cpp63
-rw-r--r--clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp15
4 files changed, 78 insertions, 21 deletions
diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h
index 2a64326e860..271d487e2fc 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -63,6 +63,12 @@ protected:
ArrayRef<TemplateArgument> ConvertedArgs,
const ConstraintSatisfaction *Satisfaction);
+ ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction,
+ bool Dependent,
+ bool ContainsUnexpandedParameterPack);
+
ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
public:
@@ -76,6 +82,13 @@ public:
const ConstraintSatisfaction *Satisfaction);
static ConceptSpecializationExpr *
+ Create(const ASTContext &C, ConceptDecl *NamedConcept,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction,
+ bool Dependent,
+ bool ContainsUnexpandedParameterPack);
+
+ static ConceptSpecializationExpr *
Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
ArrayRef<TemplateArgument> getTemplateArguments() const {
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6d1db38e36c..1be72efe4de 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -756,12 +756,8 @@ canonicalizeImmediatelyDeclaredConstraint(const ASTContext &C, Expr *IDC,
NewConverted.push_back(Arg);
}
Expr *NewIDC = ConceptSpecializationExpr::Create(
- C, NestedNameSpecifierLoc(), /*TemplateKWLoc=*/SourceLocation(),
- CSE->getConceptNameInfo(), /*FoundDecl=*/CSE->getNamedConcept(),
- CSE->getNamedConcept(),
- // Actually canonicalizing a TemplateArgumentLoc is difficult so we
- // simply omit the ArgsAsWritten
- /*ArgsAsWritten=*/nullptr, NewConverted, nullptr);
+ C, CSE->getNamedConcept(), NewConverted, nullptr,
+ CSE->isInstantiationDependent(), CSE->containsUnexpandedParameterPack());
if (auto *OrigFold = dyn_cast<CXXFoldExpr>(IDC))
NewIDC = new (C) CXXFoldExpr(OrigFold->getType(), SourceLocation(), NewIDC,
diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp
index 76d57ed5d5b..b5a3686dc99 100644
--- a/clang/lib/AST/ExprConcepts.cpp
+++ b/clang/lib/AST/ExprConcepts.cpp
@@ -46,24 +46,12 @@ ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C,
ASTConstraintSatisfaction::Create(C, *Satisfaction) :
nullptr) {
setTemplateArguments(ConvertedArgs);
-}
-
-ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
- unsigned NumTemplateArgs)
- : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
- NumTemplateArgs(NumTemplateArgs) { }
-
-void ConceptSpecializationExpr::setTemplateArguments(
- ArrayRef<TemplateArgument> Converted) {
- assert(Converted.size() == NumTemplateArgs);
- std::uninitialized_copy(Converted.begin(), Converted.end(),
- getTrailingObjects<TemplateArgument>());
bool IsInstantiationDependent = false;
bool ContainsUnexpandedParameterPack = false;
- for (const TemplateArgument& Arg : Converted) {
- if (Arg.isInstantiationDependent())
+ for (const TemplateArgumentLoc& ArgLoc : ArgsAsWritten->arguments()) {
+ if (ArgLoc.getArgument().isInstantiationDependent())
IsInstantiationDependent = true;
- if (Arg.containsUnexpandedParameterPack())
+ if (ArgLoc.getArgument().containsUnexpandedParameterPack())
ContainsUnexpandedParameterPack = true;
if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
break;
@@ -80,6 +68,18 @@ void ConceptSpecializationExpr::setTemplateArguments(
"should not be value-dependent");
}
+ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
+ unsigned NumTemplateArgs)
+ : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
+ NumTemplateArgs(NumTemplateArgs) { }
+
+void ConceptSpecializationExpr::setTemplateArguments(
+ ArrayRef<TemplateArgument> Converted) {
+ assert(Converted.size() == NumTemplateArgs);
+ std::uninitialized_copy(Converted.begin(), Converted.end(),
+ getTrailingObjects<TemplateArgument>());
+}
+
ConceptSpecializationExpr *
ConceptSpecializationExpr::Create(const ASTContext &C,
NestedNameSpecifierLoc NNS,
@@ -98,6 +98,39 @@ ConceptSpecializationExpr::Create(const ASTContext &C,
ConvertedArgs, Satisfaction);
}
+ConceptSpecializationExpr::ConceptSpecializationExpr(
+ const ASTContext &C, ConceptDecl *NamedConcept,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction, bool Dependent,
+ bool ContainsUnexpandedParameterPack)
+ : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary,
+ /*TypeDependent=*/false,
+ /*ValueDependent=*/!Satisfaction, Dependent,
+ ContainsUnexpandedParameterPack),
+ ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
+ DeclarationNameInfo(), NamedConcept,
+ NamedConcept, nullptr),
+ NumTemplateArgs(ConvertedArgs.size()),
+ Satisfaction(Satisfaction ?
+ ASTConstraintSatisfaction::Create(C, *Satisfaction) :
+ nullptr) {
+ setTemplateArguments(ConvertedArgs);
+}
+
+ConceptSpecializationExpr *
+ConceptSpecializationExpr::Create(const ASTContext &C,
+ ConceptDecl *NamedConcept,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction,
+ bool Dependent,
+ bool ContainsUnexpandedParameterPack) {
+ void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
+ ConvertedArgs.size()));
+ return new (Buffer) ConceptSpecializationExpr(
+ C, NamedConcept, ConvertedArgs, Satisfaction, Dependent,
+ ContainsUnexpandedParameterPack);
+}
+
ConceptSpecializationExpr *
ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
unsigned NumTemplateArgs) {
diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
index fb3978240af..30ec2a3ab70 100644
--- a/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
@@ -183,3 +183,18 @@ concept C8 = sizeof(T) > sizeof(U);
template<typename... T>
constexpr bool B8 = C8<T...>;
// expected-error@-1{{pack expansion used as argument for non-pack parameter of concept}}
+
+
+// Make sure we correctly check for containsUnexpandedParameterPack
+
+template<typename T>
+concept C9 = true;
+
+template <typename Fn, typename... Args>
+using invoke = typename Fn::template invoke<Args...>;
+
+template <typename C, typename... L>
+// The converted argument here will not containsUnexpandedParameterPack, but the
+// as-written one will.
+requires (C9<invoke<C, L>> &&...)
+struct S { };
OpenPOWER on IntegriCloud