diff options
-rw-r--r-- | clang/include/clang/AST/ExprConcepts.h | 13 | ||||
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 8 | ||||
-rw-r--r-- | clang/lib/AST/ExprConcepts.cpp | 63 | ||||
-rw-r--r-- | clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp | 15 |
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 { }; |