As part of the roadmap for concepts,
https://github.com/saarraz/clang-concepts-roadmap, as discussed on
[cfe-dev] -
http://lists.llvm.org/pipermail/cfe-dev/2017-November/056009.html, we're
doing incremental commits with the end goal of supporting concepts as they
are in the current C++2a working draft.
This is the first step - removing old support for function and variable
concepts in preparation for the addition of concepts as they are defined in
the current working draft.
Tests were removed because they are no longer relevant/true to the current
standard. A very small amount of them can be adapted, and will be salvaged
later when we have some compilation code to support them.
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 2879452f24..d764e485dd 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -383,7 +383,7 @@ protected:
   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);
   }
@@ -396,7 +396,7 @@ protected:
   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);
   }
@@ -428,7 +428,7 @@ public:
   }
 
   /// 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()); }
@@ -438,20 +438,13 @@ public:
 
   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<NamedDecl *, 1, bool> TemplatedDecl;
+  NamedDecl *TemplatedDecl;
 
   /// \brief The template parameter list and optional requires-clause
   /// associated with this declaration; alternatively, a
@@ -481,9 +474,9 @@ public:
   /// \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;
   }
 };
@@ -996,7 +989,7 @@ public:
 
   /// Get the underlying function declaration of the template.
   FunctionDecl *getTemplatedDecl() const {
-    return static_cast<FunctionDecl *>(TemplatedDecl.getPointer());
+    return static_cast<FunctionDecl *>(TemplatedDecl);
   }
 
   /// Returns whether this template declaration defines the primary
@@ -2092,7 +2085,7 @@ public:
 
   /// \brief Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
-    return static_cast<CXXRecordDecl *>(TemplatedDecl.getPointer());
+    return static_cast<CXXRecordDecl *>(TemplatedDecl);
   }
 
   /// \brief Returns whether this template declaration defines the primary
@@ -2345,7 +2338,7 @@ protected:
 public:
   /// Get the underlying function declaration of the template.
   TypeAliasDecl *getTemplatedDecl() const {
-    return static_cast<TypeAliasDecl *>(TemplatedDecl.getPointer());
+    return static_cast<TypeAliasDecl *>(TemplatedDecl);
   }
 
 
@@ -2900,7 +2893,7 @@ public:
 
   /// \brief Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
-    return static_cast<VarDecl *>(TemplatedDecl.getPointer());
+    return static_cast<VarDecl *>(TemplatedDecl);
   }
 
   /// \brief Returns whether this template declaration defines the primary
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 8725415af9..a4719c2260 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2366,30 +2366,15 @@ def note_private_extern : Note<
   "use __attribute__((visibility(\"hidden\"))) attribute instead">;
 
 // C++ Concepts TS
-def err_concept_wrong_decl_kind : Error<
-  "'concept' can only appear on the definition of a function template or variable template">;
 def err_concept_decls_may_only_appear_in_namespace_scope : Error<
   "concept declarations may only appear in namespace scope">;
-def err_function_concept_not_defined : Error<
-  "function concept declaration must be a definition">;
-def err_var_concept_not_initialized : Error<
-  "variable concept declaration must be initialized">;
-def err_function_concept_exception_spec : Error<
-  "function concept cannot have exception specification">;
-def err_concept_decl_invalid_specifiers : Error<
-  "%select{variable|function}0 concept cannot be declared "
-  "'%select{thread_local|inline|friend|constexpr}1'">;
-def err_function_concept_with_params : Error<
-  "function concept cannot have any parameters">;
-def err_function_concept_bool_ret : Error<
-  "declared return type of function concept must be 'bool'">;
-def err_variable_concept_bool_decl : Error<
-  "declared type of variable concept must be 'bool'">;
+def err_concept_not_initialized : Error<
+  "concept declaration must be initialized">;
 def err_concept_specified_specialization : Error<
   "'concept' cannot be applied on an "
   "%select{explicit instantiation|explicit specialization|partial specialization}0">;
 def err_concept_specialized : Error<
-  "%select{function|variable}0 concept cannot be "
+  "concept cannot be "
   "%select{explicitly instantiated|explicitly specialized|partially specialized}1">;
 
 def err_template_different_associated_constraints : Error<
diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h
index 4fc55a1dac..dd06582f75 100644
--- a/include/clang/Sema/DeclSpec.h
+++ b/include/clang/Sema/DeclSpec.h
@@ -361,9 +361,6 @@ private:
   // constexpr-specifier
   unsigned Constexpr_specified : 1;
 
-  // concept-specifier
-  unsigned Concept_specified : 1;
-
   union {
     UnionParsedType TypeRep;
     Decl *DeclRep;
@@ -393,7 +390,7 @@ private:
       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 @@ public:
       FS_noreturn_specified(false),
       Friend_specified(false),
       Constexpr_specified(false),
-      Concept_specified(false),
       Attrs(attrFactory),
       writtenBS(),
       ObjCQualifiers(nullptr) {
@@ -697,8 +693,6 @@ public:
                             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 @@ public:
   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();
   }
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index cc032c8cf3..59649c68c6 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2169,8 +2169,9 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);
     break;
 
-  case ParsedTemplateInfo::Template:
-  case ParsedTemplateInfo::ExplicitSpecialization: {
+  case ParsedTemplateInfo::ExplicitSpecialization:
+    // TODO: Concepts: Fail if this is a concept, else - fallthrough.
+  case ParsedTemplateInfo::Template: {
     ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),
                                                *TemplateInfo.TemplateParams,
                                                D);
@@ -2181,6 +2182,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     break;
   }
   case ParsedTemplateInfo::ExplicitInstantiation: {
+    // TODO: Concepts: Fail if this is a concept.
     if (Tok.is(tok::semi)) {
       DeclResult ThisRes = Actions.ActOnExplicitInstantiation(
           getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);
@@ -2225,7 +2227,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
   // If a '==' or '+=' is found, suggest a fixit to '='.
   if (isTokenEqualOrEqualTypo()) {
     SourceLocation EqualLoc = ConsumeToken();
-
+    // TODO: Concepts: Parse concept body.
     if (Tok.is(tok::kw_delete)) {
       if (D.isFunctionDeclarator())
         Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
@@ -2277,6 +2279,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
                                      /*DirectInit=*/false);
     }
   } else if (Tok.is(tok::l_paren)) {
+    // TODO: Concepts: Fail if this is a concept declarator.
     // Parse C++ direct initializer: '(' expression-list ')'
     BalancedDelimiterTracker T(*this, tok::l_paren);
     T.consumeOpen();
@@ -2322,6 +2325,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(
     }
   } else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&
              (!CurParsedObjCImpl || !D.isFunctionDeclarator())) {
+    // TODO: Concepts: Fail if this is a concept declarator.
     // Parse C++0x braced-init-list.
     Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
 
@@ -3464,11 +3468,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
       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 +4824,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
   case tok::annot_decltype:
   case tok::kw_constexpr:
 
-    // C++ Concepts TS - concept
-  case tok::kw_concept:
-
     // C11 _Atomic
   case tok::kw__Atomic:
     return true;
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 48393d9c00..5c206f4eab 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -1299,11 +1299,9 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
     //   '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:
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp
index bce493989d..6fe2dcc989 100644
--- a/lib/Sema/DeclSpec.cpp
+++ b/lib/Sema/DeclSpec.cpp
@@ -969,18 +969,6 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
   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();
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 41f6f730b2..999f22e07d 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4213,14 +4213,6 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS,
     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 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
   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;
@@ -5493,7 +5468,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D,
   } else {
     New = ActOnVariableDeclarator(S, D, DC, TInfo, Previous, TemplateParamLists,
                                   AddToScope);
-  }
+  } // TODO: Concepts: Add ActOnConceptDeclarator here, check file context and
+    // TemplateParamLists.size(), disallow any declspecs, disallow a template-id
+    // name (partial-specializations).
 
   if (!New)
     return nullptr;
@@ -5694,9 +5671,6 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   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 +6527,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
       if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus1z)
         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 +6777,6 @@ NamedDecl *Sema::ActOnVariableDeclarator(
     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<VarTemplateDecl>(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 +8230,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
     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 +8441,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
         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<FunctionProtoType>()) {
-        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) {
@@ -10745,6 +10576,7 @@ void Sema::ActOnInitializerError(Decl *D) {
   if (!D || D->isInvalidDecl()) return;
 
   VarDecl *VD = dyn_cast<VarDecl>(D);
+  // TODO: Concepts: If this is a concept - fail.
   if (!VD) return;
 
   // Bindings are not usable if we can't make sense of the initializer.
@@ -10825,17 +10657,6 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
       }
     }
 
-    // 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() &&
@@ -11016,6 +10837,7 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
 
     CheckCompleteVariableDeclaration(Var);
   }
+  // TODO: Concepts: Fail if this is a concept.
 }
 
 void Sema::ActOnCXXForRangeDecl(Decl *D) {
@@ -11751,8 +11573,6 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
   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);
 
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index a5ccce6154..f9414706e1 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -8342,8 +8342,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
   // 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 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R,
     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");
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 26b80f11fb..2fbee60769 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -8037,15 +8037,6 @@ bool Sema::CheckFunctionTemplateSpecialization(
   // Ignore access information;  it doesn't figure into redeclaration checking.
   FunctionDecl *Specialization = cast<FunctionDecl>(*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,14 +8923,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
     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;
-  }
+  // TODO: Concepts: Fail if this is a concept declarator.
 
   // A deduction guide is not on the list of entities that can be explicitly
   // instantiated.
@@ -9020,15 +9004,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
         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);
@@ -9265,16 +9240,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
          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(),
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
deleted file mode 100644
index 3baf238241..0000000000
--- a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -fcxx-exceptions -x c++ -verify %s
-
-namespace A {
-  template<typename T> concept bool C1() { return true; }
-
-  template<typename T> concept bool C2 = true;
-}
-
-template<typename T> concept bool C3() { return (throw 0, true); }
-static_assert(noexcept(C3<int>()), "function concept should be treated as if noexcept(true) specified");
-
-template<typename T> concept bool D1(); // expected-error {{function concept declaration must be a definition}}
-
-struct B {
-  template<typename T> concept bool D2() { return true; } // expected-error {{concept declarations may only appear in namespace scope}}
-};
-
-struct C {
-  template<typename T> static concept bool D3 = true; // expected-error {{concept declarations may only appear in namespace scope}}
-};
-
-concept bool D4() { return true; } // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-
-concept bool D5 = true; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-
-template<typename T>
-concept bool D6; // expected-error {{variable concept declaration must be initialized}}
-
-template<typename T>
-concept bool D7() throw(int) { return true; } // expected-error {{function concept cannot have exception specification}}
-
-// Tag
-concept class CC1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-concept struct CS1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-concept union CU1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-concept enum CE1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-template <typename T> concept class TCC1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-template <typename T> concept struct TCS1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-template <typename T> concept union TCU1 {}; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-typedef concept int CI; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-void fpc(concept int i) {} // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-
-concept bool; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
-
-template <typename T> concept bool VCEI{ true };
-template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
-extern template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
-
-template <typename T> concept bool VCPS{ true };
-template <typename T> concept bool VCPS<T *>{ true }; // expected-error {{'concept' cannot be applied on an partial specialization}}
-
-template <typename T> concept bool VCES{ true };
-template <> concept bool VCES<int>{ true }; // expected-error {{'concept' cannot be applied on an explicit specialization}}
-
-template <typename T> concept bool FCEI() { return true; }
-template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
-extern template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
-
-template <typename T> concept bool FCES() { return true; }
-template <> concept bool FCES<bool>() { return true; } // expected-error {{'concept' cannot be applied on an explicit specialization}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p2.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p2.cpp
deleted file mode 100644
index 477910986d..0000000000
--- a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p2.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
-
-template<typename T> concept thread_local bool VCTL = true; // expected-error {{variable concept cannot be declared 'thread_local'}}
-
-template<typename T> concept constexpr bool VCC = true; // expected-error {{variable concept cannot be declared 'constexpr'}}
-
-template<typename T> concept inline bool FCI() { return true; } // expected-error {{function concept cannot be declared 'inline'}}
-
-struct X {
-  template<typename T> concept friend bool FCF() { return true; } // expected-error {{function concept cannot be declared 'friend'}}
-};
-
-template<typename T> concept constexpr bool FCC() { return true; } // expected-error {{function concept cannot be declared 'constexpr'}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p5.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p5.cpp
deleted file mode 100644
index 69672ca830..0000000000
--- a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p5.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
-
-template<typename T>
-concept bool fcpv(void) { return true; }
-
-template<typename T>
-concept bool fcpi(int i = 0) { return true; } // expected-error {{function concept cannot have any parameters}}
-
-template<typename... Ts>
-concept bool fcpp(Ts... ts) { return true; } // expected-error {{function concept cannot have any parameters}}
-
-template<typename T>
-concept bool fcpva(...) { return true; } // expected-error {{function concept cannot have any parameters}}
-
-template<typename T>
-concept const bool fcrtc() { return true; } // expected-error {{declared return type of function concept must be 'bool'}}
-
-template<typename T>
-concept int fcrti() { return 5; } // expected-error {{declared return type of function concept must be 'bool'}}
-
-template<typename T>
-concept float fcrtf() { return 5.5; } // expected-error {{declared return type of function concept must be 'bool'}}
-
-template<typename T>
-concept decltype(auto) fcrtd(void) { return true; } // expected-error {{declared return type of function concept must be 'bool'}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p6.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p6.cpp
deleted file mode 100644
index f8a1bb72e3..0000000000
--- a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p6.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
-
-template<typename T>
-concept bool vc { true };
-
-template<typename T>
-struct B { typedef bool Boolean; };
-
-template<int N>
-B<void>::Boolean concept vctb(!0);
-
-template<typename T>
-concept const bool vctc { true }; // expected-error {{declared type of variable concept must be 'bool'}}
-
-template<typename T>
-concept int vcti { 5 }; // expected-error {{declared type of variable concept must be 'bool'}}
-
-template<typename T>
-concept float vctf { 5.5 }; // expected-error {{declared type of variable concept must be 'bool'}}
-
-template<typename T>
-concept auto vcta { true }; // expected-error {{declared type of variable concept must be 'bool'}}
-
-template<typename T>
-concept decltype(auto) vctd { true }; // expected-error {{declared type of variable concept must be 'bool'}}
diff --git a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp b/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp
deleted file mode 100644
index 1bad6bb932..0000000000
--- a/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
-
-template <typename T> concept bool FCEI() { return true; } // expected-note {{previous declaration is here}} expected-note {{previous declaration is here}}
-template bool FCEI<int>(); // expected-error {{function concept cannot be explicitly instantiated}}
-extern template bool FCEI<double>(); // expected-error {{function concept cannot be explicitly instantiated}}
-
-template <typename T> concept bool FCES() { return true; } // expected-note {{previous declaration is here}}
-template <> bool FCES<int>() { return true; } // expected-error {{function concept cannot be explicitly specialized}}
-
-template <typename T> concept bool VC { true }; // expected-note {{previous declaration is here}} expected-note {{previous declaration is here}}
-template bool VC<int>; // expected-error {{variable concept cannot be explicitly instantiated}}
-extern template bool VC<double>; // expected-error {{variable concept cannot be explicitly instantiated}}
-
-template <typename T> concept bool VCES { true }; // expected-note {{previous declaration is here}}
-template <> bool VCES<int> { true }; // expected-error {{variable concept cannot be explicitly specialized}}
-
-template <typename T> concept bool VCPS { true }; // expected-note {{previous declaration is here}}
-template <typename T> bool VCPS<T *> { true }; // expected-error {{variable concept cannot be partially specialized}}
diff --git a/test/Parser/cxx-concept-declaration.cpp b/test/Parser/cxx-concept-declaration.cpp
deleted file mode 100644
index fad5975e4a..0000000000
--- a/test/Parser/cxx-concept-declaration.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-
-// Support parsing of function concepts and variable concepts
-
-// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
-
-template<typename T> concept bool C1 = true;
-
-template<typename T> concept bool C2() { return true; }
-
-template<typename T>
-struct A { typedef bool Boolean; };
-
-template<int N>
-A<void>::Boolean concept C3(!0);
-
-template<typename T, int = 0>
-concept auto C4(void) -> bool { return true; }
-
-constexpr int One = 1;
-
-template <typename>
-static concept decltype(!0) C5 { bool(One) };
-
-template<typename T> concept concept bool C6 = true; // expected-warning {{duplicate 'concept' declaration specifier}}
-
-template<typename T> concept concept bool C7() { return true; } // expected-warning {{duplicate 'concept' declaration specifier}}
-
-template<concept T> concept bool D1 = true; // expected-error {{unknown type name 'T'}}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to