r374882 - [Concepts] Concept Specialization Expressions
Saar Raz via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 15 08:22:18 PDT 2019
Hi,
Sorry for the late reply, I was driving.
Fixed the test and recommitted in r374903
On Tue, Oct 15, 2019 at 5:44 PM Nico Weber <thakis at chromium.org> wrote:
> Reverted in r374899.
>
> On Tue, Oct 15, 2019 at 8:58 AM Nico Weber <thakis at chromium.org> wrote:
>
>> The test is failing on Windows. Please take a look, and if it takes a
>> while to fix please revert while you investigate:
>>
>>
>> http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/11533/steps/stage%201%20check/logs/stdio
>>
>> On Tue, Oct 15, 2019 at 7:46 AM Saar Raz via cfe-commits <
>> cfe-commits at lists.llvm.org> wrote:
>>
>>> Author: saar.raz
>>> Date: Tue Oct 15 04:48:58 2019
>>> New Revision: 374882
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=374882&view=rev
>>> Log:
>>> [Concepts] Concept Specialization Expressions
>>>
>>> Part of C++20 Concepts implementation effort. Added Concept
>>> Specialization Expressions that are created when a concept is referenced
>>> with arguments, and tests thereof.
>>>
>>>
>>>
>>> Added:
>>> cfe/trunk/lib/Sema/SemaConcept.cpp
>>> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/
>>> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
>>> cfe/trunk/test/CXX/temp/temp.constr/
>>> cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/
>>>
>>> cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
>>> cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp
>>> Removed:
>>> cfe/trunk/test/CXX/concepts-ts/
>>> Modified:
>>> cfe/trunk/include/clang/AST/ExprCXX.h
>>> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> cfe/trunk/include/clang/Basic/StmtNodes.td
>>> cfe/trunk/include/clang/Sema/Sema.h
>>> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>>> cfe/trunk/lib/AST/Expr.cpp
>>> cfe/trunk/lib/AST/ExprCXX.cpp
>>> cfe/trunk/lib/AST/ExprClassification.cpp
>>> cfe/trunk/lib/AST/ExprConstant.cpp
>>> cfe/trunk/lib/AST/ItaniumMangle.cpp
>>> cfe/trunk/lib/AST/StmtPrinter.cpp
>>> cfe/trunk/lib/AST/StmtProfile.cpp
>>> cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>>> cfe/trunk/lib/Frontend/FrontendActions.cpp
>>> cfe/trunk/lib/Parse/ParseExpr.cpp
>>> cfe/trunk/lib/Sema/CMakeLists.txt
>>> cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
>>> cfe/trunk/lib/Sema/SemaTemplate.cpp
>>> cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
>>> cfe/trunk/lib/Sema/TreeTransform.h
>>> cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
>>> cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
>>> cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
>>> cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp
>>> cfe/trunk/tools/libclang/CXCursor.cpp
>>>
>>> Modified: cfe/trunk/include/clang/AST/ExprCXX.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/AST/ExprCXX.h (original)
>>> +++ cfe/trunk/include/clang/AST/ExprCXX.h Tue Oct 15 04:48:58 2019
>>> @@ -17,6 +17,7 @@
>>> #include "clang/AST/Decl.h"
>>> #include "clang/AST/DeclBase.h"
>>> #include "clang/AST/DeclCXX.h"
>>> +#include "clang/AST/DeclTemplate.h"
>>> #include "clang/AST/DeclarationName.h"
>>> #include "clang/AST/Expr.h"
>>> #include "clang/AST/NestedNameSpecifier.h"
>>> @@ -56,6 +57,7 @@ class IdentifierInfo;
>>> class LambdaCapture;
>>> class NonTypeTemplateParmDecl;
>>> class TemplateParameterList;
>>> +class Sema;
>>>
>>>
>>> //===--------------------------------------------------------------------===//
>>> // C++ Expressions.
>>> @@ -4750,6 +4752,125 @@ public:
>>> }
>>> };
>>>
>>> +/// \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,
>>> + private llvm::TrailingObjects<ConceptSpecializationExpr,
>>> + TemplateArgument> {
>>> + friend class ASTStmtReader;
>>> + friend TrailingObjects;
>>> +
>>> + // \brief The optional nested name specifier used when naming the
>>> concept.
>>> + NestedNameSpecifierLoc NestedNameSpec;
>>> +
>>> + /// \brief The location of the template keyword, if specified when
>>> naming the
>>> + /// concept.
>>> + SourceLocation TemplateKWLoc;
>>> +
>>> + /// \brief The location of the concept name in the expression.
>>> + SourceLocation ConceptNameLoc;
>>> +
>>> + /// \brief The declaration found by name lookup when the expression
>>> was
>>> + /// created.
>>> + /// Can differ from NamedConcept when, for example, the concept was
>>> found
>>> + /// through a UsingShadowDecl.
>>> + NamedDecl *FoundDecl;
>>> +
>>> + /// \brief The concept named, and 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 bit is to be ignored.
>>> + llvm::PointerIntPair<ConceptDecl *, 1, bool> NamedConcept;
>>> +
>>> + /// \brief The template argument list source info used to specialize
>>> the
>>> + /// concept.
>>> + const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr;
>>> +
>>> + /// \brief The number of template arguments in the tail-allocated
>>> list of
>>> + /// converted template arguments.
>>> + unsigned NumTemplateArgs;
>>> +
>>> + ConceptSpecializationExpr(ASTContext &C, NestedNameSpecifierLoc NNS,
>>> + SourceLocation TemplateKWLoc,
>>> + SourceLocation ConceptNameLoc, NamedDecl
>>> *FoundDecl,
>>> + ConceptDecl *NamedConcept,
>>> + const ASTTemplateArgumentListInfo
>>> *ArgsAsWritten,
>>> + ArrayRef<TemplateArgument> ConvertedArgs,
>>> + Optional<bool> IsSatisfied);
>>> +
>>> + ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs);
>>> +
>>> +public:
>>> +
>>> + static ConceptSpecializationExpr *
>>> + Create(ASTContext &C, NestedNameSpecifierLoc NNS,
>>> + SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
>>> + NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
>>> + const ASTTemplateArgumentListInfo *ArgsAsWritten,
>>> + ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool>
>>> IsSatisfied);
>>> +
>>> + static ConceptSpecializationExpr *
>>> + Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
>>> +
>>> + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
>>> + return NestedNameSpec;
>>> + }
>>> +
>>> + NamedDecl *getFoundDecl() const {
>>> + return FoundDecl;
>>> + }
>>> +
>>> + ConceptDecl *getNamedConcept() const {
>>> + return NamedConcept.getPointer();
>>> + }
>>> +
>>> + ArrayRef<TemplateArgument> getTemplateArguments() const {
>>> + return
>>> ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
>>> + NumTemplateArgs);
>>> + }
>>> +
>>> + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
>>> + return ArgsAsWritten;
>>> + }
>>> +
>>> + /// \brief Set new template arguments for this concept specialization.
>>> + void setTemplateArguments(const ASTTemplateArgumentListInfo
>>> *ArgsAsWritten,
>>> + ArrayRef<TemplateArgument> Converted);
>>> +
>>> + /// \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 NamedConcept.getInt();
>>> + }
>>> +
>>> + SourceLocation getConceptNameLoc() const { return ConceptNameLoc; }
>>> +
>>> + SourceLocation getTemplateKWLoc() const { return TemplateKWLoc; }
>>> +
>>> + static bool classof(const Stmt *T) {
>>> + return T->getStmtClass() == ConceptSpecializationExprClass;
>>> + }
>>> +
>>> + SourceLocation getBeginLoc() const LLVM_READONLY { return
>>> ConceptNameLoc; }
>>> + 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
>>>
>>> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
>>> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Oct 15
>>> 04:48:58 2019
>>> @@ -2659,6 +2659,12 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
>>> }
>>> })
>>>
>>> +DEF_TRAVERSE_STMT(ConceptSpecializationExpr, {
>>> + TRY_TO(TraverseTemplateArgumentLocsHelper(
>>> + S->getTemplateArgsAsWritten()->getTemplateArgs(),
>>> + S->getTemplateArgsAsWritten()->NumTemplateArgs));
>>> +})
>>> +
>>> // These literals (all of them) do not need any action.
>>> DEF_TRAVERSE_STMT(IntegerLiteral, {})
>>> DEF_TRAVERSE_STMT(FixedPointLiteral, {})
>>>
>>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct 15
>>> 04:48:58 2019
>>> @@ -2526,8 +2526,6 @@ def note_private_extern : Note<
>>> "use __attribute__((visibility(\"hidden\"))) attribute instead">;
>>>
>>> // C++ Concepts
>>> -def err_concept_initialized_with_non_bool_type : Error<
>>> - "constraint expression must be of type 'bool' but is of type %0">;
>>> def err_concept_decls_may_only_appear_in_global_namespace_scope : Error<
>>> "concept declarations may only appear in global or namespace scope">;
>>> def err_concept_no_parameters : Error<
>>> @@ -2539,6 +2537,11 @@ def err_concept_no_associated_constraint
>>> "concept cannot have associated constraints">;
>>> def err_concept_not_implemented : Error<
>>> "sorry, unimplemented concepts feature %0 used">;
>>> +def err_non_constant_constraint_expression : Error<
>>> + "substitution into constraint expression resulted in a non-constant "
>>> + "expression">;
>>> +def err_non_bool_atomic_constraint : Error<
>>> + "atomic constraint must be of type 'bool' (found %0)">;
>>>
>>> def err_template_different_associated_constraints : Error<
>>> "associated constraints differ in template redeclaration">;
>>> @@ -4496,6 +4499,10 @@ def note_prior_template_arg_substitution
>>> " template parameter%1 %2">;
>>> def note_template_default_arg_checking : Note<
>>> "while checking a default template argument used here">;
>>> +def note_concept_specialization_here : Note<
>>> + "while checking the satisfaction of concept '%0' requested here">;
>>> +def note_constraint_substitution_here : Note<
>>> + "while substituting template arguments into constraint expression
>>> here">;
>>> def note_instantiation_contexts_suppressed : Note<
>>> "(skipping %0 context%s0 in backtrace; use
>>> -ftemplate-backtrace-limit=0 to "
>>> "see all)">;
>>>
>>> Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
>>> +++ cfe/trunk/include/clang/Basic/StmtNodes.td Tue Oct 15 04:48:58 2019
>>> @@ -163,6 +163,9 @@ def CoawaitExpr : DStmt<CoroutineSuspend
>>> def DependentCoawaitExpr : DStmt<Expr>;
>>> def CoyieldExpr : DStmt<CoroutineSuspendExpr>;
>>>
>>> +// C++2a Concepts expressions
>>> +def ConceptSpecializationExpr : DStmt<Expr>;
>>> +
>>> // Obj-C Expressions.
>>> def ObjCStringLiteral : DStmt<Expr>;
>>> def ObjCBoxedExpr : DStmt<Expr>;
>>>
>>> Modified: cfe/trunk/include/clang/Sema/Sema.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Sema/Sema.h (original)
>>> +++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 15 04:48:58 2019
>>> @@ -6047,7 +6047,16 @@ public:
>>> CXXConversionDecl *Conv,
>>> Expr *Src);
>>>
>>> - // ParseObjCStringLiteral - Parse Objective-C string literals.
>>> + /// Check whether the given expression is a valid constraint
>>> expression.
>>> + /// A diagnostic is emitted if it is not, and false is returned.
>>> + bool CheckConstraintExpression(Expr *CE);
>>> +
>>> + bool CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
>>> + MultiLevelTemplateArgumentList
>>> &MLTAL,
>>> + Expr *ConstraintExpr,
>>> + bool &IsSatisfied);
>>> +
>>> + // ParseObjCStringLiteral - Parse Objective-C string literals.
>>> ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
>>> ArrayRef<Expr *> Strings);
>>>
>>> @@ -6718,9 +6727,9 @@ public:
>>>
>>> ExprResult
>>> CheckConceptTemplateId(const CXXScopeSpec &SS,
>>> - const DeclarationNameInfo &NameInfo,
>>> - ConceptDecl *Template,
>>> - SourceLocation TemplateLoc,
>>> + SourceLocation TemplateKWLoc,
>>> + SourceLocation ConceptNameLoc, NamedDecl
>>> *FoundDecl,
>>> + ConceptDecl *NamedConcept,
>>> const TemplateArgumentListInfo *TemplateArgs);
>>>
>>> void diagnoseMissingTemplateArguments(TemplateName Name,
>>> SourceLocation Loc);
>>> @@ -7639,6 +7648,15 @@ public:
>>> /// member).
>>> DefiningSynthesizedFunction,
>>>
>>> + // We are checking the constraints associated with a constrained
>>> entity or
>>> + // the constraint expression of a concept. This includes the
>>> checks that
>>> + // atomic constraints have the type 'bool' and that they can be
>>> constant
>>> + // evaluated.
>>> + ConstraintsCheck,
>>> +
>>> + // We are substituting template arguments into a constraint
>>> expression.
>>> + ConstraintSubstitution,
>>> +
>>> /// Added for Template instantiation observation.
>>> /// Memoization means we are _not_ instantiating a template
>>> because
>>> /// it is already instantiated (but we entered a context where we
>>> @@ -7899,6 +7917,23 @@ public:
>>> ArrayRef<TemplateArgument> TemplateArgs,
>>> SourceRange InstantiationRange);
>>>
>>> + struct ConstraintsCheck {};
>>> + /// \brief Note that we are checking the constraints associated
>>> with some
>>> + /// constrained entity (a concept declaration or a template with
>>> associated
>>> + /// constraints).
>>> + InstantiatingTemplate(Sema &SemaRef, SourceLocation
>>> PointOfInstantiation,
>>> + ConstraintsCheck, TemplateDecl *Template,
>>> + ArrayRef<TemplateArgument> TemplateArgs,
>>> + SourceRange InstantiationRange);
>>> +
>>> + struct ConstraintSubstitution {};
>>> + /// \brief Note that we are checking a constraint expression
>>> associated
>>> + /// with a template declaration or as part of the satisfaction
>>> check of a
>>> + /// concept.
>>> + InstantiatingTemplate(Sema &SemaRef, SourceLocation
>>> PointOfInstantiation,
>>> + ConstraintSubstitution, TemplateDecl
>>> *Template,
>>> + sema::TemplateDeductionInfo &DeductionInfo,
>>> + SourceRange InstantiationRange);
>>>
>>> /// Note that we have finished instantiating this template.
>>> void Clear();
>>>
>>> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
>>> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Oct 15
>>> 04:48:58 2019
>>> @@ -1912,6 +1912,7 @@ namespace serialization {
>>> EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr
>>> EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
>>> EXPR_CXX_FOLD, // CXXFoldExpr
>>> + EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr
>>>
>>> // CUDA
>>> EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
>>>
>>> Modified: cfe/trunk/lib/AST/Expr.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/Expr.cpp (original)
>>> +++ cfe/trunk/lib/AST/Expr.cpp Tue Oct 15 04:48:58 2019
>>> @@ -3403,6 +3403,7 @@ bool Expr::HasSideEffects(const ASTConte
>>> case CXXUuidofExprClass:
>>> case OpaqueValueExprClass:
>>> case SourceLocExprClass:
>>> + case ConceptSpecializationExprClass:
>>> // These never have a side-effect.
>>> return false;
>>>
>>>
>>> Modified: cfe/trunk/lib/AST/ExprCXX.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/ExprCXX.cpp (original)
>>> +++ cfe/trunk/lib/AST/ExprCXX.cpp Tue Oct 15 04:48:58 2019
>>> @@ -28,6 +28,9 @@
>>> #include "clang/Basic/OperatorKinds.h"
>>> #include "clang/Basic/SourceLocation.h"
>>> #include "clang/Basic/Specifiers.h"
>>> +#include "clang/Sema/Template.h"
>>> +#include "clang/Sema/SemaDiagnostic.h"
>>> +#include "clang/Sema/Sema.h"
>>> #include "llvm/ADT/ArrayRef.h"
>>> #include "llvm/Support/Casting.h"
>>> #include "llvm/Support/ErrorHandling.h"
>>> @@ -1680,3 +1683,82 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::
>>> alignof(CUDAKernelCallExpr));
>>> return new (Mem) CUDAKernelCallExpr(NumArgs, Empty);
>>> }
>>> +
>>> +ConceptSpecializationExpr::ConceptSpecializationExpr(ASTContext &C,
>>> + NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
>>> + SourceLocation ConceptNameLoc, NamedDecl *FoundDecl,
>>> + ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo
>>> *ArgsAsWritten,
>>> + ArrayRef<TemplateArgument> ConvertedArgs, Optional<bool>
>>> IsSatisfied)
>>> + : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue,
>>> OK_Ordinary,
>>> + /*TypeDependent=*/false,
>>> + // All the flags below are set in setTemplateArguments.
>>> + /*ValueDependent=*/!IsSatisfied.hasValue(),
>>> + /*InstantiationDependent=*/false,
>>> + /*ContainsUnexpandedParameterPacks=*/false),
>>> + NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
>>> + ConceptNameLoc(ConceptNameLoc), FoundDecl(FoundDecl),
>>> + NamedConcept(NamedConcept, IsSatisfied ? *IsSatisfied : true),
>>> + NumTemplateArgs(ConvertedArgs.size()) {
>>> +
>>> + setTemplateArguments(ArgsAsWritten, ConvertedArgs);
>>> +}
>>> +
>>> +ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
>>> + unsigned NumTemplateArgs)
>>> + : Expr(ConceptSpecializationExprClass, Empty),
>>> + NumTemplateArgs(NumTemplateArgs) { }
>>> +
>>> +void ConceptSpecializationExpr::setTemplateArguments(
>>> + const ASTTemplateArgumentListInfo *ArgsAsWritten,
>>> + ArrayRef<TemplateArgument> Converted) {
>>> + assert(Converted.size() == NumTemplateArgs);
>>> + assert(!this->ArgsAsWritten && "setTemplateArguments can only be used
>>> once");
>>> + this->ArgsAsWritten = ArgsAsWritten;
>>> + std::uninitialized_copy(Converted.begin(), Converted.end(),
>>> + getTrailingObjects<TemplateArgument>());
>>> + bool IsInstantiationDependent = false;
>>> + bool ContainsUnexpandedParameterPack = false;
>>> + for (const TemplateArgumentLoc& LocInfo : ArgsAsWritten->arguments())
>>> {
>>> + if (LocInfo.getArgument().isInstantiationDependent())
>>> + IsInstantiationDependent = true;
>>> + if (LocInfo.getArgument().containsUnexpandedParameterPack())
>>> + ContainsUnexpandedParameterPack = true;
>>> + if (ContainsUnexpandedParameterPack && IsInstantiationDependent)
>>> + break;
>>> + }
>>> +
>>> + // Currently guaranteed by the fact concepts can only be at
>>> namespace-scope.
>>> + assert(!NestedNameSpec ||
>>> +
>>> (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
>>> + !NestedNameSpec.getNestedNameSpecifier()
>>> + ->containsUnexpandedParameterPack()));
>>> + setInstantiationDependent(IsInstantiationDependent);
>>> + setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack);
>>> + assert((!isValueDependent() || isInstantiationDependent()) &&
>>> + "should not be value-dependent");
>>> +}
>>> +
>>> +ConceptSpecializationExpr *
>>> +ConceptSpecializationExpr::Create(ASTContext &C, NestedNameSpecifierLoc
>>> NNS,
>>> + SourceLocation TemplateKWLoc,
>>> + SourceLocation ConceptNameLoc,
>>> + NamedDecl *FoundDecl,
>>> + ConceptDecl *NamedConcept,
>>> + const ASTTemplateArgumentListInfo
>>> *ArgsAsWritten,
>>> + ArrayRef<TemplateArgument>
>>> ConvertedArgs,
>>> + Optional<bool> IsSatisfied) {
>>> + void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
>>> + ConvertedArgs.size()));
>>> + return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
>>> + ConceptNameLoc,
>>> FoundDecl,
>>> + NamedConcept,
>>> ArgsAsWritten,
>>> + ConvertedArgs,
>>> IsSatisfied);
>>> +}
>>> +
>>> +ConceptSpecializationExpr *
>>> +ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
>>> + unsigned NumTemplateArgs) {
>>> + void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
>>> + NumTemplateArgs));
>>> + return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
>>> +}
>>> \ No newline at end of file
>>>
>>> Modified: cfe/trunk/lib/AST/ExprClassification.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/ExprClassification.cpp (original)
>>> +++ cfe/trunk/lib/AST/ExprClassification.cpp Tue Oct 15 04:48:58 2019
>>> @@ -192,6 +192,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
>>> case Expr::NoInitExprClass:
>>> case Expr::DesignatedInitUpdateExprClass:
>>> case Expr::SourceLocExprClass:
>>> + case Expr::ConceptSpecializationExprClass:
>>> return Cl::CL_PRValue;
>>>
>>> case Expr::ConstantExprClass:
>>>
>>> Modified: cfe/trunk/lib/AST/ExprConstant.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/ExprConstant.cpp (original)
>>> +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Oct 15 04:48:58 2019
>>> @@ -9768,6 +9768,7 @@ public:
>>> bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
>>> bool VisitSizeOfPackExpr(const SizeOfPackExpr *E);
>>> bool VisitSourceLocExpr(const SourceLocExpr *E);
>>> + bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr
>>> *E);
>>> // FIXME: Missing: array subscript of vector, member of vector
>>> };
>>>
>>> @@ -12250,6 +12251,12 @@ bool IntExprEvaluator::VisitCXXNoexceptE
>>> return Success(E->getValue(), E);
>>> }
>>>
>>> +bool IntExprEvaluator::VisitConceptSpecializationExpr(
>>> + const ConceptSpecializationExpr *E) {
>>> + return Success(E->isSatisfied(), E);
>>> +}
>>> +
>>> +
>>> bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator
>>> *E) {
>>> switch (E->getOpcode()) {
>>> default:
>>> @@ -13923,6 +13930,7 @@ static ICEDiag CheckICE(const Expr* E, c
>>> case Expr::CXXBoolLiteralExprClass:
>>> case Expr::CXXScalarValueInitExprClass:
>>> case Expr::TypeTraitExprClass:
>>> + case Expr::ConceptSpecializationExprClass:
>>> case Expr::ArrayTypeTraitExprClass:
>>> case Expr::ExpressionTraitExprClass:
>>> case Expr::CXXNoexceptExprClass:
>>>
>>> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
>>> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Oct 15 04:48:58 2019
>>> @@ -3658,6 +3658,7 @@ recurse:
>>> case Expr::ConvertVectorExprClass:
>>> case Expr::StmtExprClass:
>>> case Expr::TypeTraitExprClass:
>>> + case Expr::ConceptSpecializationExprClass:
>>> case Expr::ArrayTypeTraitExprClass:
>>> case Expr::ExpressionTraitExprClass:
>>> case Expr::VAArgExprClass:
>>>
>>> Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
>>> +++ cfe/trunk/lib/AST/StmtPrinter.cpp Tue Oct 15 04:48:58 2019
>>> @@ -2231,6 +2231,17 @@ void StmtPrinter::VisitCXXFoldExpr(CXXFo
>>> OS << ")";
>>> }
>>>
>>> +void
>>> StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) {
>>> + NestedNameSpecifierLoc NNS = E->getNestedNameSpecifierLoc();
>>> + if (NNS)
>>> + NNS.getNestedNameSpecifier()->print(OS, Policy);
>>> + if (E->getTemplateKWLoc().isValid())
>>> + OS << "template ";
>>> + OS << E->getFoundDecl()->getName();
>>> + printTemplateArgumentList(OS,
>>> E->getTemplateArgsAsWritten()->arguments(),
>>> + Policy);
>>> +}
>>> +
>>> // C++ Coroutines TS
>>>
>>> void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) {
>>>
>>> Modified: cfe/trunk/lib/AST/StmtProfile.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/StmtProfile.cpp (original)
>>> +++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Oct 15 04:48:58 2019
>>> @@ -1309,6 +1309,14 @@ void StmtProfiler::VisitAtomicExpr(const
>>> ID.AddInteger(S->getOp());
>>> }
>>>
>>> +void StmtProfiler::VisitConceptSpecializationExpr(
>>> + const
>>> ConceptSpecializationExpr *S) {
>>> + VisitExpr(S);
>>> + VisitDecl(S->getFoundDecl());
>>> +
>>> VisitTemplateArguments(S->getTemplateArgsAsWritten()->getTemplateArgs(),
>>> +
>>> S->getTemplateArgsAsWritten()->NumTemplateArgs);
>>> +}
>>> +
>>> static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S,
>>> UnaryOperatorKind &UnaryOp,
>>> BinaryOperatorKind &BinaryOp)
>>> {
>>>
>>> Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
>>> +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Tue Oct 15 04:48:58 2019
>>> @@ -673,6 +673,10 @@ public:
>>> return llvm::ConstantInt::get(ConvertType(E->getType()),
>>> E->getValue());
>>> }
>>>
>>> + Value *VisitConceptSpecializationExpr(const ConceptSpecializationExpr
>>> *E) {
>>> + return Builder.getInt1(E->isSatisfied());
>>> + }
>>> +
>>> Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
>>> return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue());
>>> }
>>>
>>> Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
>>> +++ cfe/trunk/lib/Frontend/FrontendActions.cpp Tue Oct 15 04:48:58 2019
>>> @@ -417,6 +417,10 @@ private:
>>> return "DefiningSynthesizedFunction";
>>> case CodeSynthesisContext::Memoization:
>>> return "Memoization";
>>> + case CodeSynthesisContext::ConstraintsCheck:
>>> + return "ConstraintsCheck";
>>> + case CodeSynthesisContext::ConstraintSubstitution:
>>> + return "ConstraintSubstitution";
>>> }
>>> return "";
>>> }
>>>
>>> Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
>>> +++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Oct 15 04:48:58 2019
>>> @@ -228,18 +228,16 @@ ExprResult Parser::ParseCaseExpression(S
>>> /// Parse a constraint-expression.
>>> ///
>>> /// \verbatim
>>> -/// constraint-expression: [Concepts TS temp.constr.decl p1]
>>> +/// constraint-expression: C++2a[temp.constr.decl]p1
>>> /// logical-or-expression
>>> /// \endverbatim
>>> ExprResult Parser::ParseConstraintExpression() {
>>> - // FIXME: this may erroneously consume a function-body as the braced
>>> - // initializer list of a compound literal
>>> - //
>>> - // FIXME: this may erroneously consume a parenthesized rvalue
>>> reference
>>> - // declarator as a parenthesized address-of-label expression
>>> + EnterExpressionEvaluationContext ConstantEvaluated(
>>> + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
>>> ExprResult LHS(ParseCastExpression(/*isUnaryExpression=*/false));
>>> ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::LogicalOr));
>>> -
>>> + if (Res.isUsable() && !Actions.CheckConstraintExpression(Res.get()))
>>> + return ExprError();
>>> return Res;
>>> }
>>>
>>>
>>> Modified: cfe/trunk/lib/Sema/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/CMakeLists.txt (original)
>>> +++ cfe/trunk/lib/Sema/CMakeLists.txt Tue Oct 15 04:48:58 2019
>>> @@ -32,6 +32,7 @@ add_clang_library(clangSema
>>> SemaCast.cpp
>>> SemaChecking.cpp
>>> SemaCodeComplete.cpp
>>> + SemaConcept.cpp
>>> SemaConsumer.cpp
>>> SemaCoroutine.cpp
>>> SemaCUDA.cpp
>>>
>>> Added: cfe/trunk/lib/Sema/SemaConcept.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaConcept.cpp?rev=374882&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaConcept.cpp (added)
>>> +++ cfe/trunk/lib/Sema/SemaConcept.cpp Tue Oct 15 04:48:58 2019
>>> @@ -0,0 +1,125 @@
>>> +//===-- SemaConcept.cpp - Semantic Analysis for Constraints and
>>> Concepts --===//
>>> +//
>>> +// The LLVM Compiler Infrastructure
>>> +//
>>> +// This file is distributed under the University of Illinois Open Source
>>> +// License. See LICENSE.TXT for details.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +//
>>> +// This file implements semantic analysis for C++ constraints and
>>> concepts.
>>> +//
>>>
>>> +//===----------------------------------------------------------------------===//
>>> +
>>> +#include "clang/Sema/Sema.h"
>>> +#include "clang/Sema/SemaDiagnostic.h"
>>> +#include "clang/Sema/TemplateDeduction.h"
>>> +#include "clang/Sema/Template.h"
>>> +#include "clang/AST/ExprCXX.h"
>>> +using namespace clang;
>>> +using namespace sema;
>>> +
>>> +bool Sema::CheckConstraintExpression(Expr *ConstraintExpression) {
>>> + // C++2a [temp.constr.atomic]p1
>>> + // ..E shall be a constant expression of type bool.
>>> +
>>> + ConstraintExpression = ConstraintExpression->IgnoreParenImpCasts();
>>> +
>>> + if (auto *BinOp = dyn_cast<BinaryOperator>(ConstraintExpression)) {
>>> + if (BinOp->getOpcode() == BO_LAnd || BinOp->getOpcode() == BO_LOr)
>>> + return CheckConstraintExpression(BinOp->getLHS()) &&
>>> + CheckConstraintExpression(BinOp->getRHS());
>>> + } else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpression))
>>> + return CheckConstraintExpression(C->getSubExpr());
>>> +
>>> + // An atomic constraint!
>>> + if (ConstraintExpression->isTypeDependent())
>>> + return true;
>>> +
>>> + QualType Type = ConstraintExpression->getType();
>>> + if (!Context.hasSameUnqualifiedType(Type, Context.BoolTy)) {
>>> + Diag(ConstraintExpression->getExprLoc(),
>>> + diag::err_non_bool_atomic_constraint) << Type
>>> + << ConstraintExpression->getSourceRange();
>>> + return false;
>>> + }
>>> + return true;
>>> +}
>>> +
>>> +bool
>>> +Sema::CalculateConstraintSatisfaction(ConceptDecl *NamedConcept,
>>> + MultiLevelTemplateArgumentList
>>> &MLTAL,
>>> + Expr *ConstraintExpr,
>>> + bool &IsSatisfied) {
>>> + ConstraintExpr = ConstraintExpr->IgnoreParenImpCasts();
>>> +
>>> + if (auto *BO = dyn_cast<BinaryOperator>(ConstraintExpr)) {
>>> + if (BO->getOpcode() == BO_LAnd) {
>>> + if (CalculateConstraintSatisfaction(NamedConcept, MLTAL,
>>> BO->getLHS(),
>>> + IsSatisfied))
>>> + return true;
>>> + if (!IsSatisfied)
>>> + return false;
>>> + return CalculateConstraintSatisfaction(NamedConcept, MLTAL,
>>> BO->getRHS(),
>>> + IsSatisfied);
>>> + } else if (BO->getOpcode() == BO_LOr) {
>>> + if (CalculateConstraintSatisfaction(NamedConcept, MLTAL,
>>> BO->getLHS(),
>>> + IsSatisfied))
>>> + return true;
>>> + if (IsSatisfied)
>>> + return false;
>>> + return CalculateConstraintSatisfaction(NamedConcept, MLTAL,
>>> BO->getRHS(),
>>> + IsSatisfied);
>>> + }
>>> + }
>>> + else if (auto *C = dyn_cast<ExprWithCleanups>(ConstraintExpr))
>>> + return CalculateConstraintSatisfaction(NamedConcept, MLTAL,
>>> C->getSubExpr(),
>>> + IsSatisfied);
>>> +
>>> + EnterExpressionEvaluationContext ConstantEvaluated(
>>> + *this, Sema::ExpressionEvaluationContext::ConstantEvaluated);
>>> +
>>> + // Atomic constraint - substitute arguments and check satisfaction.
>>> + ExprResult E;
>>> + {
>>> + TemplateDeductionInfo Info(ConstraintExpr->getBeginLoc());
>>> + InstantiatingTemplate Inst(*this, ConstraintExpr->getBeginLoc(),
>>> +
>>> InstantiatingTemplate::ConstraintSubstitution{},
>>> + NamedConcept, Info,
>>> + ConstraintExpr->getSourceRange());
>>> + if (Inst.isInvalid())
>>> + return true;
>>> + // We do not want error diagnostics escaping here.
>>> + Sema::SFINAETrap Trap(*this);
>>> +
>>> + E = SubstExpr(ConstraintExpr, MLTAL);
>>> + if (E.isInvalid() || Trap.hasErrorOccurred()) {
>>> + // C++2a [temp.constr.atomic]p1
>>> + // ...If substitution results in an invalid type or expression,
>>> the
>>> + // constraint is not satisfied.
>>> + IsSatisfied = false;
>>> + return false;
>>> + }
>>> + }
>>> +
>>> + if (!CheckConstraintExpression(E.get()))
>>> + return true;
>>> +
>>> + SmallVector<PartialDiagnosticAt, 2> EvaluationDiags;
>>> + Expr::EvalResult EvalResult;
>>> + EvalResult.Diag = &EvaluationDiags;
>>> + if (!E.get()->EvaluateAsRValue(EvalResult, Context)) {
>>> + // C++2a [temp.constr.atomic]p1
>>> + // ...E shall be a constant expression of type bool.
>>> + Diag(E.get()->getBeginLoc(),
>>> + diag::err_non_constant_constraint_expression)
>>> + << E.get()->getSourceRange();
>>> + for (const PartialDiagnosticAt &PDiag : EvaluationDiags)
>>> + Diag(PDiag.first, PDiag.second);
>>> + return true;
>>> + }
>>> +
>>> + IsSatisfied = EvalResult.Val.getInt().getBoolValue();
>>> +
>>> + return false;
>>> +}
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Tue Oct 15 04:48:58 2019
>>> @@ -1314,6 +1314,7 @@ CanThrowResult Sema::canThrow(const Expr
>>> case Expr::SizeOfPackExprClass:
>>> case Expr::StringLiteralClass:
>>> case Expr::SourceLocExprClass:
>>> + case Expr::ConceptSpecializationExprClass:
>>> // These expressions can never throw.
>>> return CT_Cannot;
>>>
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Oct 15 04:48:58 2019
>>> @@ -4271,14 +4271,47 @@ void Sema::diagnoseMissingTemplateArgume
>>>
>>> ExprResult
>>> Sema::CheckConceptTemplateId(const CXXScopeSpec &SS,
>>> - const DeclarationNameInfo &NameInfo,
>>> - ConceptDecl *Template,
>>> - SourceLocation TemplateLoc,
>>> + SourceLocation TemplateKWLoc,
>>> + SourceLocation ConceptNameLoc,
>>> + NamedDecl *FoundDecl,
>>> + ConceptDecl *NamedConcept,
>>> const TemplateArgumentListInfo
>>> *TemplateArgs) {
>>> - // TODO: Do concept specialization here.
>>> - Diag(NameInfo.getBeginLoc(), diag::err_concept_not_implemented) <<
>>> - "concept specialization";
>>> - return ExprError();
>>> + assert(NamedConcept && "A concept template id without a template?");
>>> +
>>> + llvm::SmallVector<TemplateArgument, 4> Converted;
>>> + if (CheckTemplateArgumentList(NamedConcept, ConceptNameLoc,
>>> +
>>> const_cast<TemplateArgumentListInfo&>(*TemplateArgs),
>>> + /*PartialTemplateArgs=*/false,
>>> Converted,
>>> + /*UpdateArgsWithConversion=*/false))
>>> + return ExprError();
>>> +
>>> + Optional<bool> IsSatisfied;
>>> + bool AreArgsDependent = false;
>>> + for (TemplateArgument &Arg : Converted) {
>>> + if (Arg.isDependent()) {
>>> + AreArgsDependent = true;
>>> + break;
>>> + }
>>> + }
>>> + if (!AreArgsDependent) {
>>> + InstantiatingTemplate Inst(*this, ConceptNameLoc,
>>> + InstantiatingTemplate::ConstraintsCheck{}, NamedConcept,
>>> Converted,
>>> + SourceRange(SS.isSet() ? SS.getBeginLoc() : ConceptNameLoc,
>>> + TemplateArgs->getRAngleLoc()));
>>> + MultiLevelTemplateArgumentList MLTAL;
>>> + MLTAL.addOuterTemplateArguments(Converted);
>>> + bool Satisfied;
>>> + if (CalculateConstraintSatisfaction(NamedConcept, MLTAL,
>>> +
>>> NamedConcept->getConstraintExpr(),
>>> + Satisfied))
>>> + return ExprError();
>>> + IsSatisfied = Satisfied;
>>> + }
>>> + return ConceptSpecializationExpr::Create(Context,
>>> + SS.isSet() ? SS.getWithLocInContext(Context) :
>>> NestedNameSpecifierLoc{},
>>> + TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept,
>>> + ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs),
>>> Converted,
>>> + IsSatisfied);
>>> }
>>>
>>> ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS,
>>> @@ -4322,9 +4355,10 @@ ExprResult Sema::BuildTemplateIdExpr(con
>>> }
>>>
>>> if (R.getAsSingle<ConceptDecl>() && !AnyDependentArguments()) {
>>> - return CheckConceptTemplateId(SS, R.getLookupNameInfo(),
>>> - R.getAsSingle<ConceptDecl>(),
>>> - TemplateKWLoc, TemplateArgs);
>>> + return CheckConceptTemplateId(SS, TemplateKWLoc,
>>> + R.getLookupNameInfo().getBeginLoc(),
>>> + R.getFoundDecl(),
>>> + R.getAsSingle<ConceptDecl>(),
>>> TemplateArgs);
>>> }
>>>
>>> // We don't want lookup warnings at this point.
>>> @@ -8054,20 +8088,7 @@ Decl *Sema::ActOnConceptDefinition(Scope
>>> ConceptDecl *NewDecl = ConceptDecl::Create(Context, DC, NameLoc, Name,
>>>
>>> TemplateParameterLists.front(),
>>> ConstraintExpr);
>>> -
>>> - if (!ConstraintExpr->isTypeDependent() &&
>>> - ConstraintExpr->getType() != Context.BoolTy) {
>>> - // C++2a [temp.constr.atomic]p3:
>>> - // E shall be a constant expression of type bool.
>>> - // TODO: Do this check for individual atomic constraints
>>> - // and not the constraint expression. Probably should do it in
>>> - // ParseConstraintExpression.
>>> - Diag(ConstraintExpr->getSourceRange().getBegin(),
>>> - diag::err_concept_initialized_with_non_bool_type)
>>> - << ConstraintExpr->getType();
>>> - NewDecl->setInvalidDecl();
>>> - }
>>> -
>>> +
>>> if (NewDecl->getAssociatedConstraints()) {
>>> // C++2a [temp.concept]p4:
>>> // A concept shall not have associated constraints.
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Oct 15 04:48:58
>>> 2019
>>> @@ -198,12 +198,14 @@ bool Sema::CodeSynthesisContext::isInsta
>>> case ExplicitTemplateArgumentSubstitution:
>>> case DeducedTemplateArgumentSubstitution:
>>> case PriorTemplateArgumentSubstitution:
>>> + case ConstraintsCheck:
>>> return true;
>>>
>>> case DefaultTemplateArgumentChecking:
>>> case DeclaringSpecialMember:
>>> case DefiningSynthesizedFunction:
>>> case ExceptionSpecEvaluation:
>>> + case ConstraintSubstitution:
>>> return false;
>>>
>>> // This function should never be called when Kind's value is
>>> Memoization.
>>> @@ -358,6 +360,24 @@ Sema::InstantiatingTemplate::Instantiati
>>> PointOfInstantiation, InstantiationRange, Param, Template,
>>> TemplateArgs) {}
>>>
>>> +Sema::InstantiatingTemplate::InstantiatingTemplate(
>>> + Sema &SemaRef, SourceLocation PointOfInstantiation,
>>> + ConstraintsCheck, TemplateDecl *Template,
>>> + ArrayRef<TemplateArgument> TemplateArgs, SourceRange
>>> InstantiationRange)
>>> + : InstantiatingTemplate(
>>> + SemaRef, CodeSynthesisContext::ConstraintsCheck,
>>> + PointOfInstantiation, InstantiationRange, Template, nullptr,
>>> + TemplateArgs) {}
>>> +
>>> +Sema::InstantiatingTemplate::InstantiatingTemplate(
>>> + Sema &SemaRef, SourceLocation PointOfInstantiation,
>>> + ConstraintSubstitution, TemplateDecl *Template,
>>> + sema::TemplateDeductionInfo &DeductionInfo, SourceRange
>>> InstantiationRange)
>>> + : InstantiatingTemplate(
>>> + SemaRef, CodeSynthesisContext::ConstraintSubstitution,
>>> + PointOfInstantiation, InstantiationRange, Template, nullptr,
>>> + {}, &DeductionInfo) {}
>>> +
>>> void Sema::pushCodeSynthesisContext(CodeSynthesisContext Ctx) {
>>> Ctx.SavedInNonInstantiationSFINAEContext =
>>> InNonInstantiationSFINAEContext;
>>> InNonInstantiationSFINAEContext = false;
>>> @@ -664,6 +684,30 @@ void Sema::PrintInstantiationStack() {
>>>
>>> case CodeSynthesisContext::Memoization:
>>> break;
>>> +
>>> + case CodeSynthesisContext::ConstraintsCheck:
>>> + if (auto *CD = dyn_cast<ConceptDecl>(Active->Entity)) {
>>> + SmallVector<char, 128> TemplateArgsStr;
>>> + llvm::raw_svector_ostream OS(TemplateArgsStr);
>>> + CD->printName(OS);
>>> + printTemplateArgumentList(OS, Active->template_arguments(),
>>> + getPrintingPolicy());
>>> + Diags.Report(Active->PointOfInstantiation,
>>> + diag::note_concept_specialization_here)
>>> + << OS.str()
>>> + << Active->InstantiationRange;
>>> + break;
>>> + }
>>> + // TODO: Concepts - implement this for constrained templates and
>>> partial
>>> + // specializations.
>>> + llvm_unreachable("only concept constraints are supported right
>>> now");
>>> + break;
>>> +
>>> + case CodeSynthesisContext::ConstraintSubstitution:
>>> + Diags.Report(Active->PointOfInstantiation,
>>> + diag::note_constraint_substitution_here)
>>> + << Active->InstantiationRange;
>>> + break;
>>> }
>>> }
>>> }
>>> @@ -687,6 +731,7 @@ Optional<TemplateDeductionInfo *> Sema::
>>> LLVM_FALLTHROUGH;
>>> case CodeSynthesisContext::DefaultFunctionArgumentInstantiation:
>>> case CodeSynthesisContext::ExceptionSpecInstantiation:
>>> + case CodeSynthesisContext::ConstraintsCheck:
>>> // This is a template instantiation, so there is no SFINAE.
>>> return None;
>>>
>>> @@ -700,8 +745,10 @@ Optional<TemplateDeductionInfo *> Sema::
>>>
>>> case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution:
>>> case CodeSynthesisContext::DeducedTemplateArgumentSubstitution:
>>> - // We're either substitution explicitly-specified template
>>> arguments
>>> - // or deduced template arguments, so SFINAE applies.
>>> + case CodeSynthesisContext::ConstraintSubstitution:
>>> + // We're either substituting explicitly-specified template
>>> arguments
>>> + // or deduced template arguments or a constraint expression, so
>>> SFINAE
>>> + // applies.
>>> assert(Active->DeductionInfo && "Missing deduction info pointer");
>>> return Active->DeductionInfo;
>>>
>>>
>>> Modified: cfe/trunk/lib/Sema/TreeTransform.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
>>> +++ cfe/trunk/lib/Sema/TreeTransform.h Tue Oct 15 04:48:58 2019
>>> @@ -3019,6 +3019,25 @@ public:
>>> ///
>>> /// By default, performs semantic analysis to build the new
>>> expression.
>>> /// Subclasses may override this routine to provide different
>>> behavior.
>>> + ExprResult RebuildConceptSpecializationExpr(NestedNameSpecifierLoc
>>> NNS,
>>> + SourceLocation TemplateKWLoc, SourceLocation ConceptNameLoc,
>>> + NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
>>> + TemplateArgumentListInfo *TALI) {
>>> + CXXScopeSpec SS;
>>> + SS.Adopt(NNS);
>>> + ExprResult Result = getSema().CheckConceptTemplateId(SS,
>>> TemplateKWLoc,
>>> + ConceptNameLoc,
>>> + FoundDecl,
>>> + NamedConcept,
>>> TALI);
>>> + if (Result.isInvalid())
>>> + return ExprError();
>>> + return Result;
>>> + }
>>> +
>>> + /// \brief Build a new Objective-C boxed expression.
>>> + ///
>>> + /// By default, performs semantic analysis to build the new
>>> expression.
>>> + /// Subclasses may override this routine to provide different
>>> behavior.
>>> ExprResult RebuildObjCBoxedExpr(SourceRange SR, Expr *ValueExpr) {
>>> return getSema().BuildObjCBoxedExpr(SR, ValueExpr);
>>> }
>>> @@ -11016,6 +11035,23 @@ TreeTransform<Derived>::TransformTypeTra
>>>
>>> template<typename Derived>
>>> ExprResult
>>> +TreeTransform<Derived>::TransformConceptSpecializationExpr(
>>> +
>>> ConceptSpecializationExpr *E) {
>>> + const ASTTemplateArgumentListInfo *Old =
>>> E->getTemplateArgsAsWritten();
>>> + TemplateArgumentListInfo TransArgs(Old->LAngleLoc, Old->RAngleLoc);
>>> + if (getDerived().TransformTemplateArguments(Old->getTemplateArgs(),
>>> + Old->NumTemplateArgs,
>>> TransArgs))
>>> + return ExprError();
>>> +
>>> + return getDerived().RebuildConceptSpecializationExpr(
>>> + E->getNestedNameSpecifierLoc(), E->getTemplateKWLoc(),
>>> + E->getConceptNameLoc(), E->getFoundDecl(), E->getNamedConcept(),
>>> + &TransArgs);
>>> +}
>>> +
>>> +
>>> +template<typename Derived>
>>> +ExprResult
>>> TreeTransform<Derived>::TransformArrayTypeTraitExpr(ArrayTypeTraitExpr
>>> *E) {
>>> TypeSourceInfo *T =
>>> getDerived().TransformType(E->getQueriedTypeSourceInfo());
>>> if (!T)
>>>
>>> Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Tue Oct 15 04:48:58
>>> 2019
>>> @@ -734,6 +734,24 @@ void ASTStmtReader::VisitUnaryExprOrType
>>> E->setRParenLoc(ReadSourceLocation());
>>> }
>>>
>>> +void ASTStmtReader::VisitConceptSpecializationExpr(
>>> + ConceptSpecializationExpr *E) {
>>> + VisitExpr(E);
>>> + unsigned NumTemplateArgs = Record.readInt();
>>> + E->NestedNameSpec = Record.readNestedNameSpecifierLoc();
>>> + E->TemplateKWLoc = Record.readSourceLocation();
>>> + E->ConceptNameLoc = Record.readSourceLocation();
>>> + E->FoundDecl = ReadDeclAs<NamedDecl>();
>>> + E->NamedConcept.setPointer(ReadDeclAs<ConceptDecl>());
>>> + const ASTTemplateArgumentListInfo *ArgsAsWritten =
>>> + Record.readASTTemplateArgumentListInfo();
>>> + llvm::SmallVector<TemplateArgument, 4> Args;
>>> + for (unsigned I = 0; I < NumTemplateArgs; ++I)
>>> + Args.push_back(Record.readTemplateArgument());
>>> + E->setTemplateArguments(ArgsAsWritten, Args);
>>> + E->NamedConcept.setInt(Record.readInt() == 1);
>>> +}
>>> +
>>> void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
>>> VisitExpr(E);
>>> E->setLHS(Record.readSubExpr());
>>> @@ -3490,6 +3508,12 @@ Stmt *ASTReader::ReadStmtFromStream(Modu
>>> case EXPR_DEPENDENT_COAWAIT:
>>> S = new (Context) DependentCoawaitExpr(Empty);
>>> break;
>>> +
>>> + case EXPR_CONCEPT_SPECIALIZATION:
>>> + unsigned numTemplateArgs = Record[ASTStmtReader::NumExprFields];
>>> + S = ConceptSpecializationExpr::Create(Context, Empty,
>>> numTemplateArgs);
>>> + break;
>>> +
>>> }
>>>
>>> // We hit a STMT_STOP, so we're done with this expression.
>>>
>>> Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
>>> +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Tue Oct 15 04:48:58
>>> 2019
>>> @@ -388,6 +388,24 @@ void ASTStmtWriter::VisitDependentCoawai
>>> Code = serialization::EXPR_DEPENDENT_COAWAIT;
>>> }
>>>
>>> +void ASTStmtWriter::VisitConceptSpecializationExpr(
>>> + ConceptSpecializationExpr *E) {
>>> + VisitExpr(E);
>>> + ArrayRef<TemplateArgument> TemplateArgs = E->getTemplateArguments();
>>> + Record.push_back(TemplateArgs.size());
>>> + Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc());
>>> + Record.AddSourceLocation(E->getTemplateKWLoc());
>>> + Record.AddSourceLocation(E->getConceptNameLoc());
>>> + Record.AddDeclRef(E->getFoundDecl());
>>> + Record.AddDeclRef(E->getNamedConcept());
>>> + Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten());
>>> + for (const TemplateArgument &Arg : TemplateArgs)
>>> + Record.AddTemplateArgument(Arg);
>>> + Record.push_back(E->isSatisfied());
>>> + Code = serialization::EXPR_CONCEPT_SPECIALIZATION;
>>> +}
>>> +
>>> +
>>> void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) {
>>> VisitStmt(S);
>>> // NumCaptures
>>>
>>> Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
>>> +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Tue Oct 15 04:48:58
>>> 2019
>>> @@ -1370,6 +1370,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
>>> case Stmt::CUDAKernelCallExprClass:
>>> case Stmt::OpaqueValueExprClass:
>>> case Stmt::AsTypeExprClass:
>>> + case Stmt::ConceptSpecializationExprClass:
>>> // Fall through.
>>>
>>> // Cases we intentionally don't evaluate, since they don't need
>>>
>>> Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp?rev=374882&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp (added)
>>> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp Tue Oct 15
>>> 04:48:58 2019
>>> @@ -0,0 +1,149 @@
>>> +// RUN: %clang_cc1 -std=c++2a -verify -triple x86_64-linux-gnu %s
>>> +
>>> +template<typename T> concept C1 = true; // expected-note{{template is
>>> declared here}}
>>> +static_assert(C1<int>);
>>> +static_assert(C1);
>>> +// expected-error at -1{{use of concept 'C1' requires template arguments}}
>>> +
>>> +template<typename T> concept C2 = sizeof(T) == 4;
>>> +static_assert(C2<int>);
>>> +static_assert(!C2<long long int>);
>>> +static_assert(C2<char[4]>);
>>> +static_assert(!C2<char[5]>);
>>> +
>>> +template<typename T> concept C3 = sizeof(*T{}) == 4;
>>> +static_assert(C3<int*>);
>>> +static_assert(!C3<long long int>);
>>> +
>>> +struct A {
>>> + static constexpr int add(int a, int b) {
>>> + return a + b;
>>> + }
>>> +};
>>> +struct B {
>>> + static int add(int a, int b) { // expected-note{{declared here}}
>>> + return a + b;
>>> + }
>>> +};
>>> +template<typename U>
>>> +concept C4 = U::add(1, 2) == 3;
>>> +// expected-error at -1{{substitution into constraint expression resulted
>>> in a non-constant expression}}
>>> +// expected-note at -2{{non-constexpr function 'add' cannot be used in a
>>> constant expression}}
>>> +static_assert(C4<A>);
>>> +static_assert(!C4<B>); // expected-note {{while checking the
>>> satisfaction of concept 'C4<B>' requested here}}
>>> +
>>> +template<typename T, typename U>
>>> +constexpr bool is_same_v = false;
>>> +
>>> +template<typename T>
>>> +constexpr bool is_same_v<T, T> = true;
>>> +
>>> +template<typename T, typename U>
>>> +concept Same = is_same_v<T, U>;
>>> +
>>> +static_assert(Same<int, int>);
>>> +static_assert(Same<int, decltype(1)>);
>>> +static_assert(!Same<int, unsigned int>);
>>> +static_assert(!Same<A, B>);
>>> +static_assert(Same<A, A>);
>>> +
>>> +static_assert(Same<bool, decltype(C1<int>)>);
>>> +static_assert(Same<bool, decltype(C2<int>)>);
>>> +static_assert(Same<bool, decltype(C3<int*>)>);
>>> +static_assert(Same<bool, decltype(C4<A>)>);
>>> +
>>> +template<typename T> concept C5 = T{}; // expected-error {{atomic
>>> constraint must be of type 'bool' (found 'int')}}
>>> +constexpr bool x = C5<int>; // expected-note {{while checking the
>>> satisfaction of concept 'C5<int>' requested here}}
>>> +
>>> +template<int x>
>>> +concept IsEven = (x % 2) == 0;
>>> +
>>> +static_assert(IsEven<20>);
>>> +static_assert(!IsEven<11>);
>>> +
>>> +template<template<typename T> typename P>
>>> +concept IsTypePredicate = is_same_v<decltype(P<bool>::value), const
>>> bool>
>>> + && is_same_v<decltype(P<int>::value), const
>>> bool>
>>> + && is_same_v<decltype(P<long long>::value),
>>> const bool>;
>>> +
>>> +template<typename T> struct T1 {};
>>> +template<typename T> struct T2 { static constexpr bool value =
>>> sizeof(T) == 2; };
>>> +
>>> +static_assert(IsTypePredicate<T2>);
>>> +static_assert(!IsTypePredicate<T1>);
>>> +
>>> +namespace piecewise_substitution {
>>> + template <typename T>
>>> + concept True = true;
>>> +
>>> + template <typename T>
>>> + concept A = True<T> || T::value;
>>> +
>>> + template <typename T>
>>> + concept B = (True<T> || T::value);
>>> +
>>> + template <typename T>
>>> + concept C = !True<T> && T::value || true;
>>> +
>>> + template <typename T>
>>> + concept D = (!True<T> && T::value) || true;
>>> +
>>> + template <typename T>
>>> + concept E = T::value || True<T>;
>>> +
>>> + template <typename T>
>>> + concept F = (T::value || True<T>);
>>> +
>>> + template <typename T>
>>> + concept G = T::value && !True<T> || true;
>>> +
>>> + template <typename T>
>>> + concept H = (T::value && !True<T>) || true;
>>> +
>>> + template <typename T>
>>> + concept I = T::value;
>>> +
>>> + static_assert(A<int>);
>>> + static_assert(B<int>);
>>> + static_assert(C<int>);
>>> + static_assert(D<int>);
>>> + static_assert(E<int>);
>>> + static_assert(F<int>);
>>> + static_assert(G<int>);
>>> + static_assert(H<int>);
>>> + static_assert(!I<int>);
>>> +}
>>> +
>>> +// Short ciruiting
>>> +
>>> +template<typename T> struct T3 { using type = typename T::type; };
>>> +// expected-error at -1{{type 'char' cannot be used prior to '::' because
>>> it has no members}}
>>> +// expected-error at -2{{type 'short' cannot be used prior to '::'
>>> because it has no members}}
>>> +
>>> +template<typename T>
>>> +concept C6 = sizeof(T) == 1 && sizeof(typename T3<T>::type) == 1;
>>> +// expected-note at -1{{while substituting template arguments into
>>> constraint expression here}}
>>> +// expected-note at -2{{in instantiation of template class 'T3<char>'
>>> requested here}}
>>> +
>>> +template<typename T>
>>> +concept C7 = sizeof(T) == 1 || sizeof(
>>> +// expected-note at -1{{while substituting template arguments into
>>> constraint expression here}}
>>> + typename
>>> + T3<T>
>>> +// expected-note at -1{{in instantiation of template class 'T3<short>'
>>> requested here}}
>>> + ::type) == 1;
>>> +
>>> +static_assert(!C6<short>);
>>> +static_assert(!C6<char>); // expected-note{{while checking the
>>> satisfaction of concept 'C6<char>' requested here}}
>>> +static_assert(C7<char>);
>>> +static_assert(!C7<short>); // expected-note{{while checking the
>>> satisfaction of concept 'C7<short>' requested here}}
>>> +
>>> +// Make sure argument list is converted when instantiating a CSE.
>>> +
>>> +template<typename T, typename U = int>
>>> +concept SameSize = sizeof(T) == sizeof(U);
>>> +
>>> +template<typename T>
>>> +struct X { static constexpr bool a = SameSize<T>; };
>>> +
>>> +static_assert(X<unsigned>::a);
>>>
>>> Added:
>>> cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp?rev=374882&view=auto
>>>
>>> ==============================================================================
>>> ---
>>> cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
>>> (added)
>>> +++
>>> cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
>>> Tue Oct 15 04:48:58 2019
>>> @@ -0,0 +1,65 @@
>>> +// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
>>> +
>>> +namespace nodiag {
>>> +
>>> +template <typename T> requires bool(T())
>>> +struct A;
>>> +template <typename U> requires bool(U())
>>> +struct A;
>>> +
>>> +} // end namespace nodiag
>>> +
>>> +namespace diag {
>>> +
>>> +template <typename T> requires true // expected-note{{previous template
>>> declaration is here}}
>>> +struct A;
>>> +template <typename T> struct A; // expected-error{{associated
>>> constraints differ in template redeclaration}}
>>> +
>>> +template <typename T> struct B; // expected-note{{previous template
>>> declaration is here}}
>>> +template <typename T> requires true // expected-error{{associated
>>> constraints differ in template redeclaration}}
>>> +struct B;
>>> +
>>> +template <typename T> requires true // expected-note{{previous template
>>> declaration is here}}
>>> +struct C;
>>> +template <typename T> requires !0 // expected-error{{associated
>>> constraints differ in template redeclaration}}
>>> +struct C;
>>> +
>>> +} // end namespace diag
>>> +
>>> +namespace nodiag {
>>> +
>>> +struct AA {
>>> + template <typename T> requires someFunc(T())
>>> + struct A;
>>> +};
>>> +
>>> +template <typename T> requires someFunc(T())
>>> +struct AA::A { };
>>> +
>>> +struct AAF {
>>> + template <typename T> requires someFunc(T())
>>> + friend struct AA::A;
>>> +};
>>> +
>>> +} // end namespace nodiag
>>> +
>>> +namespace diag {
>>> +
>>> +template <unsigned N>
>>> +struct TA {
>>> + template <template <unsigned> class TT> requires TT<N>::happy //
>>> expected-note 2{{previous template declaration is here}}
>>> + struct A;
>>> +
>>> + struct AF;
>>> +};
>>> +
>>> +template <unsigned N>
>>> +template <template <unsigned> class TT> struct TA<N>::A { }; //
>>> expected-error{{associated constraints differ in template redeclaration}}
>>> +
>>> +template <unsigned N>
>>> +struct TA<N>::AF {
>>> + template <template <unsigned> class TT> requires TT<N + 0>::happy //
>>> expected-error{{associated constraints differ in template redeclaration}}
>>> + friend struct TA::A;
>>> +};
>>> +
>>> +} // end namespace diag
>>>
>>> Added: cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp?rev=374882&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp (added)
>>> +++ cfe/trunk/test/PCH/cxx2a-concept-specialization-expr.cpp Tue Oct 15
>>> 04:48:58 2019
>>> @@ -0,0 +1,32 @@
>>> +// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
>>> +// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
>>> +
>>> +// expected-no-diagnostics
>>> +
>>> +#ifndef HEADER
>>> +#define HEADER
>>> +
>>> +template<typename... T>
>>> +concept C = true;
>>> +
>>> +namespace n {
>>> + template<typename... T>
>>> + concept C = true;
>>> +}
>>> +
>>> +void f() {
>>> + (void)C<int>;
>>> + (void)C<int, void>;
>>> + (void)n::C<void>;
>>> +}
>>> +
>>> +#else /*included pch*/
>>> +
>>> +int main() {
>>> + (void)C<int>;
>>> + (void)C<int, void>;
>>> + (void)n::C<void>;
>>> + f();
>>> +}
>>> +
>>> +#endif // HEADER
>>>
>>> Modified: cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp (original)
>>> +++ cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp Tue Oct 15
>>> 04:48:58 2019
>>> @@ -14,8 +14,6 @@ template<template<typename> concept T> c
>>> // expected-error at -2{{template template parameter requires 'class'
>>> after the parameter list}}
>>> // expected-error at -3{{concept template parameter list must have at
>>> least one parameter; explicit specialization of concepts is not allowed}}
>>>
>>> -template<typename T> concept C2 = 0.f; // expected-error {{constraint
>>> expression must be of type 'bool' but is of type 'float'}}
>>> -
>>> struct S1 {
>>> template<typename T> concept C1 = true; // expected-error {{concept
>>> declarations may only appear in global or namespace scope}}
>>> };
>>> @@ -26,15 +24,15 @@ extern "C++" {
>>>
>>> template<typename A>
>>> template<typename B>
>>> -concept C4 = true; // expected-error {{extraneous template parameter
>>> list in concept definition}}
>>> +concept C2 = true; // expected-error {{extraneous template parameter
>>> list in concept definition}}
>>>
>>> -template<typename T> concept C5 = true; // expected-note {{previous}}
>>> expected-note {{previous}}
>>> -int C5; // expected-error {{redefinition}}
>>> -struct C5 {}; // expected-error {{redefinition}}
>>> -
>>> -struct C6 {}; // expected-note{{previous definition is here}}
>>> -template<typename T> concept C6 = true;
>>> -// expected-error at -1{{redefinition of 'C6' as different kind of
>>> symbol}}
>>> +template<typename T> concept C3 = true; // expected-note {{previous}}
>>> expected-note {{previous}}
>>> +int C3; // expected-error {{redefinition}}
>>> +struct C3 {}; // expected-error {{redefinition}}
>>> +
>>> +struct C4 {}; // expected-note{{previous definition is here}}
>>> +template<typename T> concept C4 = true;
>>> +// expected-error at -1{{redefinition of 'C4' as different kind of
>>> symbol}}
>>>
>>> // TODO: Add test to prevent explicit specialization, partial
>>> specialization
>>> // and explicit instantiation of concepts.
>>> @@ -43,31 +41,60 @@ template<typename T, T v>
>>> struct integral_constant { static constexpr T value = v; };
>>>
>>> namespace N {
>>> - template<typename T> concept C7 = true;
>>> + template<typename T> concept C5 = true;
>>> }
>>> -using N::C7;
>>> +using N::C5;
>>>
>>> -template <bool word> concept C8 = integral_constant<bool, wor>::value;
>>> +template <bool word> concept C6 = integral_constant<bool, wor>::value;
>>> // expected-error at -1{{use of undeclared identifier 'wor'; did you mean
>>> 'word'?}}
>>> // expected-note at -2{{'word' declared here}}
>>>
>>> -template<typename T> concept bool C9 = true;
>>> +template<typename T> concept bool C7 = true;
>>> // expected-warning at -1{{ISO C++2a does not permit the 'bool' keyword
>>> after 'concept'}}
>>>
>>> -template<> concept C10 = false;
>>> +template<> concept C8 = false;
>>> // expected-error at -1{{concept template parameter list must have at
>>> least one parameter; explicit specialization of concepts is not allowed}}
>>>
>>> -template<> concept C9<int> = false;
>>> +template<> concept C7<int> = false;
>>> // expected-error at -1{{name defined in concept definition must be an
>>> identifier}}
>>>
>>> -template<typename T> concept N::C11 = false;
>>> +template<typename T> concept N::C9 = false;
>>> // expected-error at -1{{name defined in concept definition must be an
>>> identifier}}
>>>
>>> class A { };
>>> // expected-note at -1{{'A' declared here}}
>>>
>>> -template<typename T> concept A::C12 = false;
>>> +template<typename T> concept A::C10 = false;
>>> // expected-error at -1{{expected namespace name}}
>>>
>>> template<typename T> concept operator int = false;
>>> // expected-error at -1{{name defined in concept definition must be an
>>> identifier}}
>>> +
>>> +template<bool x> concept C11 = 2; // expected-error {{atomic constraint
>>> must be of type 'bool' (found 'int')}}
>>> +template<bool x> concept C12 = 2 && x; // expected-error {{atomic
>>> constraint must be of type 'bool' (found 'int')}}
>>> +template<bool x> concept C13 = x || 2 || x; // expected-error {{atomic
>>> constraint must be of type 'bool' (found 'int')}}
>>> +template<bool x> concept C14 = 8ull && x || x; // expected-error
>>> {{atomic constraint must be of type 'bool' (found 'unsigned long long')}}
>>> +template<typename T> concept C15 = sizeof(T); // expected-error
>>> {{atomic constraint must be of type 'bool' (found 'unsigned long')}}
>>> +template<typename T> concept C16 = true && (0 && 0); // expected-error
>>> {{atomic constraint must be of type 'bool' (found 'int')}}
>>> +// expected-warning at -1{{use of logical '&&' with constant operand}}
>>> +// expected-note at -2{{use '&' for a bitwise operation}}
>>> +// expected-note at -3{{remove constant to silence this warning}}
>>> +template<typename T> concept C17 = T{};
>>> +static_assert(!C17<bool>);
>>> +template<typename T> concept C18 = (bool&&)true;
>>> +static_assert(C18<int>);
>>> +template<typename T> concept C19 = (const bool&)true;
>>> +static_assert(C19<int>);
>>> +template<typename T> concept C20 = (const bool)true;
>>> +static_assert(C20<int>);
>>> +template <bool c> concept C21 = integral_constant<bool, c>::value &&
>>> true;
>>> +static_assert(C21<true>);
>>> +static_assert(!C21<false>);
>>> +template <bool c> concept C22 = integral_constant<bool, c>::value;
>>> +static_assert(C22<true>);
>>> +static_assert(!C22<false>);
>>> +
>>> +template <bool word> concept C23 = integral_constant<bool, wor>::value;
>>> +// expected-error at -1{{use of undeclared identifier 'wor'; did you mean
>>> 'word'?}}
>>> +// expected-note at -2{{'word' declared here}}
>>> +
>>>
>>> Modified: cfe/trunk/tools/libclang/CXCursor.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=374882&r1=374881&r2=374882&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/tools/libclang/CXCursor.cpp (original)
>>> +++ cfe/trunk/tools/libclang/CXCursor.cpp Tue Oct 15 04:48:58 2019
>>> @@ -256,6 +256,7 @@ CXCursor cxcursor::MakeCXCursor(const St
>>> case Stmt::BinaryConditionalOperatorClass:
>>> case Stmt::TypeTraitExprClass:
>>> case Stmt::CoawaitExprClass:
>>> + case Stmt::ConceptSpecializationExprClass:
>>> case Stmt::DependentCoawaitExprClass:
>>> case Stmt::CoyieldExprClass:
>>> case Stmt::CXXBindTemporaryExprClass:
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at lists.llvm.org
>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191015/7119a10d/attachment-0001.html>
More information about the cfe-commits
mailing list