]> granicus.if.org Git - clang/commitdiff
[CONCEPTS] Add diagnostics: non-defining function; non-namespace scope
authorHubert Tong <hubert.reinterpretcast@gmail.com>
Wed, 22 Jul 2015 13:32:36 +0000 (13:32 +0000)
committerHubert Tong <hubert.reinterpretcast@gmail.com>
Wed, 22 Jul 2015 13:32:36 +0000 (13:32 +0000)
Summary:
Create diagnostic for function concept declaration which is not a
definition.

Create diagnostic for concept declaration which isn't in namespace
scope.

Create associated tests.

Reviewers: rsmith, faisalv, fraggamuffin, hubert.reinterpretcast

Subscribers: cfe-commits

Differential Revision: http://reviews.llvm.org/D11027

Patch by Nathan Wilson!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@242899 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/SemaCXX/cxx-concept-declaration.cpp [new file with mode: 0644]

index 7174bbe95ef0c1fe94026b9bcf710644729c9504..56597714ff9db402ac49f21ccebfe6073022d06f 100644 (file)
@@ -1965,6 +1965,12 @@ def warn_private_extern : Warning<
 def note_private_extern : Note<
   "use __attribute__((visibility(\"hidden\"))) attribute instead">;
 
+// C++ Concepts TS
+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">;
+
 // C++11 char16_t/char32_t
 def warn_cxx98_compat_unicode_type : Warning<
   "'%0' type specifier is incompatible with C++98">,
index 22803653edffd0431269247b36cb53f8b3a9977a..d25b4dda88525706e43d41bb72e0c7291e17fe39 100644 (file)
@@ -4861,6 +4861,17 @@ 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 (!DC->getRedeclContext()->isFileContext()) {
+      Diag(D.getIdentifierLoc(),
+           diag::err_concept_decls_may_only_appear_in_namespace_scope);
+      return nullptr;
+    }
+  }
+
   NamedDecl *New;
 
   bool AddToScope = true;
@@ -7203,6 +7214,7 @@ 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
@@ -7419,6 +7431,20 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
         Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor);
     }
 
+    if (isConcept) {
+      // 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]p2: Every concept definition is
+      // implicity defined to be a constexpr declaration (implicitly inline)
+      NewFD->setImplicitlyInline();
+    }
+
     // If __module_private__ was specified, mark the function accordingly.
     if (D.getDeclSpec().isModulePrivateSpecified()) {
       if (isFunctionTemplateSpecialization) {
diff --git a/test/SemaCXX/cxx-concept-declaration.cpp b/test/SemaCXX/cxx-concept-declaration.cpp
new file mode 100644 (file)
index 0000000..6bc2d48
--- /dev/null
@@ -0,0 +1,17 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -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 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}}
+};