Index: include/clang/AST/DeclTemplate.h =================================================================== --- include/clang/AST/DeclTemplate.h +++ include/clang/AST/DeclTemplate.h @@ -405,7 +405,7 @@ TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), + : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), TemplateParams(CTDI) { this->setTemplateParameters(Params); } @@ -418,7 +418,7 @@ TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false), + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(CTDI) { this->setTemplateParameters(Params); } @@ -450,7 +450,7 @@ } /// Get the underlying, templated declaration. - NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); } + NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -461,21 +461,11 @@ SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getTemplateParameters()->getTemplateLoc(), - TemplatedDecl.getPointer()->getSourceRange().getEnd()); + TemplatedDecl->getSourceRange().getEnd()); } - /// Whether this is a (C++ Concepts TS) function or variable concept. - bool isConcept() const { return TemplatedDecl.getInt(); } - void setConcept() { TemplatedDecl.setInt(true); } - protected: - /// \brief The named declaration from which this template was instantiated. - /// (or null). - /// - /// The boolean value will be true to indicate that this template - /// (function or variable) is a concept. - llvm::PointerIntPair TemplatedDecl; - + NamedDecl *TemplatedDecl; /// \brief The template parameter list and optional requires-clause /// associated with this declaration; alternatively, a /// \c ConstrainedTemplateDeclInfo if the associated constraints of the @@ -504,9 +494,9 @@ /// \brief Initialize the underlying templated declaration and /// template parameters. void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!"); + assert(!TemplatedDecl && "TemplatedDecl already set!"); assert(!TemplateParams && "TemplateParams already set!"); - TemplatedDecl.setPointer(templatedDecl); + TemplatedDecl = templatedDecl; TemplateParams = templateParams; } }; @@ -1028,7 +1018,7 @@ /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl.getPointer()); + return static_cast(TemplatedDecl); } /// Returns whether this template declaration defines the primary @@ -2120,7 +2110,7 @@ /// \brief Get the underlying class declarations of the template. CXXRecordDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl.getPointer()); + return static_cast(TemplatedDecl); } /// \brief Returns whether this template declaration defines the primary @@ -2367,7 +2357,7 @@ /// Get the underlying function declaration of the template. TypeAliasDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl.getPointer()); + return static_cast(TemplatedDecl); } @@ -2934,7 +2924,7 @@ /// \brief Get the underlying variable declarations of the template. VarDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl.getPointer()); + return static_cast(TemplatedDecl); } /// \brief Returns whether this template declaration defines the primary Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -361,9 +361,6 @@ // constexpr-specifier unsigned Constexpr_specified : 1; - // concept-specifier - unsigned Concept_specified : 1; - union { UnionParsedType TypeRep; Decl *DeclRep; @@ -393,7 +390,7 @@ TQ_unalignedLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FS_forceinlineLoc; - SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc; + SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc; SourceLocation TQ_pipeLoc; WrittenBuiltinSpecs writtenBS; @@ -439,7 +436,6 @@ FS_noreturn_specified(false), Friend_specified(false), Constexpr_specified(false), - Concept_specified(false), Attrs(attrFactory), writtenBS(), ObjCQualifiers(nullptr) { @@ -697,8 +693,6 @@ unsigned &DiagID); bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); - bool SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID); bool isFriendSpecified() const { return Friend_specified; } SourceLocation getFriendSpecLoc() const { return FriendLoc; } @@ -709,19 +703,11 @@ bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } - bool isConceptSpecified() const { return Concept_specified; } - SourceLocation getConceptSpecLoc() const { return ConceptLoc; } - void ClearConstexprSpec() { Constexpr_specified = false; ConstexprLoc = SourceLocation(); } - void ClearConceptSpec() { - Concept_specified = false; - ConceptLoc = SourceLocation(); - } - AttributePool &getAttributePool() const { return Attrs.getPool(); } Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3464,11 +3464,6 @@ isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID); break; - // concept - case tok::kw_concept: - isInvalid = DS.SetConceptSpec(Loc, PrevSpec, DiagID); - break; - // type-specifier case tok::kw_short: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, @@ -4825,9 +4820,6 @@ case tok::annot_decltype: case tok::kw_constexpr: - // C++ Concepts TS - concept - case tok::kw_concept: - // C11 _Atomic case tok::kw__Atomic: return true; Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -1299,11 +1299,9 @@ // 'friend' // 'typedef' // 'constexpr' - // 'concept' case tok::kw_friend: case tok::kw_typedef: case tok::kw_constexpr: - case tok::kw_concept: // storage-class-specifier case tok::kw_register: case tok::kw_static: Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -969,18 +969,6 @@ return false; } -bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, - unsigned &DiagID) { - if (Concept_specified) { - DiagID = diag::ext_duplicate_declspec; - PrevSpec = "concept"; - return true; - } - Concept_specified = true; - ConceptLoc = Loc; - return false; -} - void DeclSpec::SaveWrittenBuiltinSpecs() { writtenBS.Sign = getTypeSpecSign(); writtenBS.Width = getTypeSpecWidth(); Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -4213,14 +4213,6 @@ return TagD; } - if (DS.isConceptSpecified()) { - // C++ Concepts TS [dcl.spec.concept]p1: A concept definition refers to - // either a function concept and its definition or a variable concept and - // its initializer. - Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); - return TagD; - } - DiagnoseFunctionSpecifiers(DS); if (DS.isFriendSpecified()) { @@ -5459,23 +5451,6 @@ if (getLangOpts().CPlusPlus) CheckExtraCXXDefaultArguments(D); - if (D.getDeclSpec().isConceptSpecified()) { - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable - // template, declared in namespace scope - if (!TemplateParamLists.size()) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag:: err_concept_wrong_decl_kind); - return nullptr; - } - - if (!DC->getRedeclContext()->isFileContext()) { - Diag(D.getIdentifierLoc(), - diag::err_concept_decls_may_only_appear_in_namespace_scope); - return nullptr; - } - } - NamedDecl *New; bool AddToScope = true; @@ -5694,9 +5669,6 @@ if (D.getDeclSpec().isConstexprSpecified()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) << 1; - if (D.getDeclSpec().isConceptSpecified()) - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_wrong_decl_kind); if (D.getName().Kind != UnqualifiedId::IK_Identifier) { if (D.getName().Kind == UnqualifiedId::IK_DeductionGuideName) @@ -6553,46 +6525,6 @@ if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus17) NewVD->setImplicitlyInline(); } - - if (D.getDeclSpec().isConceptSpecified()) { - if (VarTemplateDecl *VTD = NewVD->getDescribedVarTemplate()) - VTD->setConcept(); - - // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not - // be declared with the thread_local, inline, friend, or constexpr - // specifiers, [...] - if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) { - Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 0 << 0; - NewVD->setInvalidDecl(true); - } - - if (D.getDeclSpec().isConstexprSpecified()) { - Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 0 << 3; - NewVD->setInvalidDecl(true); - } - - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable - // template, declared in namespace scope. - if (IsVariableTemplateSpecialization) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_specified_specialization) - << (IsPartialSpecialization ? 2 : 1); - } - - // C++ Concepts TS [dcl.spec.concept]p6: A variable concept has the - // following restrictions: - // - The declared type shall have the type bool. - if (!Context.hasSameType(NewVD->getType(), Context.BoolTy) && - !NewVD->isInvalidDecl()) { - Diag(D.getIdentifierLoc(), diag::err_variable_concept_bool_decl); - NewVD->setInvalidDecl(true); - } - } } if (D.getDeclSpec().isInlineSpecified()) { @@ -6843,25 +6775,6 @@ if (!IsVariableTemplateSpecialization) D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous)); - // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...] - // an explicit specialization (14.8.3) or a partial specialization of a - // concept definition. - if (IsVariableTemplateSpecialization && - !D.getDeclSpec().isConceptSpecified() && !Previous.empty() && - Previous.isSingleResult()) { - NamedDecl *PreviousDecl = Previous.getFoundDecl(); - if (VarTemplateDecl *VarTmpl = dyn_cast(PreviousDecl)) { - if (VarTmpl->isConcept()) { - Diag(NewVD->getLocation(), diag::err_concept_specialized) - << 1 /*variable*/ - << (IsPartialSpecialization ? 2 /*partially specialized*/ - : 1 /*explicitly specialized*/); - Diag(VarTmpl->getLocation(), diag::note_previous_declaration); - NewVD->setInvalidDecl(); - } - } - } - if (NewTemplate) { VarTemplateDecl *PrevVarTemplate = NewVD->getPreviousDecl() @@ -8315,7 +8228,6 @@ bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool isExplicit = D.getDeclSpec().isExplicitSpecified(); bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); - bool isConcept = D.getDeclSpec().isConceptSpecified(); isFriend = D.getDeclSpec().isFriendSpecified(); if (isFriend && !isInline && D.isFunctionDefinition()) { // C++ [class.friend]p5 @@ -8527,89 +8439,6 @@ Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); } - if (isConcept) { - // This is a function concept. - if (FunctionTemplateDecl *FTD = NewFD->getDescribedFunctionTemplate()) - FTD->setConcept(); - - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template [...] - if (!D.isFunctionDefinition()) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_function_concept_not_defined); - NewFD->setInvalidDecl(); - } - - // C++ Concepts TS [dcl.spec.concept]p1: [...] A function concept shall - // have no exception-specification and is treated as if it were specified - // with noexcept(true) (15.4). [...] - if (const FunctionProtoType *FPT = R->getAs()) { - if (FPT->hasExceptionSpec()) { - SourceRange Range; - if (D.isFunctionDeclarator()) - Range = D.getFunctionTypeInfo().getExceptionSpecRange(); - Diag(NewFD->getLocation(), diag::err_function_concept_exception_spec) - << FixItHint::CreateRemoval(Range); - NewFD->setInvalidDecl(); - } else { - Context.adjustExceptionSpec(NewFD, EST_BasicNoexcept); - } - - // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the - // following restrictions: - // - The declared return type shall have the type bool. - if (!Context.hasSameType(FPT->getReturnType(), Context.BoolTy)) { - Diag(D.getIdentifierLoc(), diag::err_function_concept_bool_ret); - NewFD->setInvalidDecl(); - } - - // C++ Concepts TS [dcl.spec.concept]p5: A function concept has the - // following restrictions: - // - The declaration's parameter list shall be equivalent to an empty - // parameter list. - if (FPT->getNumParams() > 0 || FPT->isVariadic()) - Diag(NewFD->getLocation(), diag::err_function_concept_with_params); - } - - // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is - // implicity defined to be a constexpr declaration (implicitly inline) - NewFD->setImplicitlyInline(); - - // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not - // be declared with the thread_local, inline, friend, or constexpr - // specifiers, [...] - if (isInline) { - Diag(D.getDeclSpec().getInlineSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 1 << 1; - NewFD->setInvalidDecl(true); - } - - if (isFriend) { - Diag(D.getDeclSpec().getFriendSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 1 << 2; - NewFD->setInvalidDecl(true); - } - - if (isConstexpr) { - Diag(D.getDeclSpec().getConstexprSpecLoc(), - diag::err_concept_decl_invalid_specifiers) - << 1 << 3; - NewFD->setInvalidDecl(true); - } - - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable - // template, declared in namespace scope. - if (isFunctionTemplateSpecialization) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_specified_specialization) << 1; - NewFD->setInvalidDecl(true); - return NewFD; - } - } - // If __module_private__ was specified, mark the function accordingly. if (D.getDeclSpec().isModulePrivateSpecified()) { if (isFunctionTemplateSpecialization) { @@ -10825,17 +10654,6 @@ } } - // C++ Concepts TS [dcl.spec.concept]p1: [...] A variable template - // definition having the concept specifier is called a variable concept. A - // concept definition refers to [...] a variable concept and its initializer. - if (VarTemplateDecl *VTD = Var->getDescribedVarTemplate()) { - if (VTD->isConcept()) { - Diag(Var->getLocation(), diag::err_var_concept_not_initialized); - Var->setInvalidDecl(); - return; - } - } - // OpenCL v1.1 s6.5.3: variables declared in the constant address space must // be initialized. if (!Var->isInvalidDecl() && @@ -11751,8 +11569,6 @@ if (DS.isConstexprSpecified()) Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr) << 0; - if (DS.isConceptSpecified()) - Diag(DS.getConceptSpecLoc(), diag::err_concept_wrong_decl_kind); DiagnoseFunctionSpecifiers(DS); Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -8342,8 +8342,7 @@ // We leave 'friend' and 'virtual' to be rejected in the normal way. if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() || DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() || - DS.isNoreturnSpecified() || DS.isConstexprSpecified() || - DS.isConceptSpecified()) { + DS.isNoreturnSpecified() || DS.isConstexprSpecified()) { BadSpecifierDiagnoser Diagnoser( *this, D.getIdentifierLoc(), diag::err_deduction_guide_invalid_specifier); @@ -8356,9 +8355,7 @@ Diagnoser.check(DS.getInlineSpecLoc(), "inline"); Diagnoser.check(DS.getNoreturnSpecLoc(), "_Noreturn"); Diagnoser.check(DS.getConstexprSpecLoc(), "constexpr"); - Diagnoser.check(DS.getConceptSpecLoc(), "concept"); DS.ClearConstexprSpec(); - DS.ClearConceptSpec(); Diagnoser.check(DS.getConstSpecLoc(), "const"); Diagnoser.check(DS.getRestrictSpecLoc(), "__restrict"); Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -8037,15 +8037,6 @@ // Ignore access information; it doesn't figure into redeclaration checking. FunctionDecl *Specialization = cast(*Result); - // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...] - // an explicit specialization (14.8.3) [...] of a concept definition. - if (Specialization->getPrimaryTemplate()->isConcept()) { - Diag(FD->getLocation(), diag::err_concept_specialized) - << 0 /*function*/ << 1 /*explicitly specialized*/; - Diag(Specialization->getLocation(), diag::note_previous_declaration); - return true; - } - FunctionTemplateSpecializationInfo *SpecInfo = Specialization->getTemplateSpecializationInfo(); assert(SpecInfo && "Function template specialization info missing?"); @@ -8932,15 +8923,6 @@ Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_explicit_instantiation_constexpr); - // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be - // applied only to the definition of a function template or variable template, - // declared in namespace scope. - if (D.getDeclSpec().isConceptSpecified()) { - Diag(D.getDeclSpec().getConceptSpecLoc(), - diag::err_concept_specified_specialization) << 0; - return true; - } - // A deduction guide is not on the list of entities that can be explicitly // instantiated. if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { @@ -9020,15 +9002,6 @@ return true; } - // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an - // explicit instantiation (14.8.2) [...] of a concept definition. - if (PrevTemplate->isConcept()) { - Diag(D.getIdentifierLoc(), diag::err_concept_specialized) - << 1 /*variable*/ << 0 /*explicitly instantiated*/; - Diag(PrevTemplate->getLocation(), diag::note_previous_declaration); - return true; - } - // Translate the parser's template argument list into our AST format. TemplateArgumentListInfo TemplateArgs = makeTemplateArgumentListInfo(*this, *D.getName().TemplateId); @@ -9272,16 +9245,6 @@ diag::ext_explicit_instantiation_without_qualified_id) << Specialization << D.getCXXScopeSpec().getRange(); - // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an - // explicit instantiation (14.8.2) [...] of a concept definition. - if (FunTmpl && FunTmpl->isConcept() && - !D.getDeclSpec().isConceptSpecified()) { - Diag(D.getIdentifierLoc(), diag::err_concept_specialized) - << 0 /*function*/ << 0 /*explicitly instantiated*/; - Diag(FunTmpl->getLocation(), diag::note_previous_declaration); - return true; - } - CheckExplicitInstantiationScope(*this, FunTmpl? (NamedDecl *)FunTmpl : Specialization->getInstantiatedFromMemberFunction(), Index: test/CXX/concepts-ts/dcl.dcl/lit.cfg.py =================================================================== --- test/CXX/concepts-ts/dcl.dcl/lit.cfg.py +++ test/CXX/concepts-ts/dcl.dcl/lit.cfg.py @@ -0,0 +1,26 @@ +# -*- Python -*- + +import os +import lit.formats + +from lit.llvm import llvm_config + +# Configuration file for the 'lit' test runner. + +# name: The name of this test suite. +config.name = 'Clang-Concepts-TS-Unsupported' + +# testFormat: The test format to use to interpret tests. +# +# For now we require '&&' between commands, until they get globally killed and +# the test runner updated. +config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) + +# suffixes: A list of file extensions to treat as test files. +config.suffixes = ['.c', '.cpp', '.cppm', '.m', '.mm', '.cu', + '.ll', '.cl', '.s', '.S', '.modulemap', '.test', '.rs'] + +config.unsupported = True + +# test_source_root: The root path where tests are located. +config.test_source_root = os.path.dirname(__file__) Index: test/Parser/cxx-concept-declaration.cpp =================================================================== --- test/Parser/cxx-concept-declaration.cpp +++ test/Parser/cxx-concept-declaration.cpp @@ -1,28 +1,7 @@ -// Support parsing of function concepts and variable concepts +// Support parsing of concepts +// Disabled for now. +// expected-no-diagnostics // RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s - -template concept bool C1 = true; - -template concept bool C2() { return true; } - -template -struct A { typedef bool Boolean; }; - -template -A::Boolean concept C3(!0); - -template -concept auto C4(void) -> bool { return true; } - -constexpr int One = 1; - -template -static concept decltype(!0) C5 { bool(One) }; - -template concept concept bool C6 = true; // expected-warning {{duplicate 'concept' declaration specifier}} - -template concept concept bool C7() { return true; } // expected-warning {{duplicate 'concept' declaration specifier}} - -template concept bool D1 = true; // expected-error {{unknown type name 'T'}} +// template concept C1 = true;