]> granicus.if.org Git - clang/commitdiff
Implement [dcl.fct.spec]p6.
authorAnders Carlsson <andersca@mac.com>
Sun, 24 Jan 2010 16:49:46 +0000 (16:49 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 24 Jan 2010 16:49:46 +0000 (16:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94365 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.fct.spec/p6.cpp

index aec03f705a4d6562244aa2a48e71f1dcd9999d07..5f1e5f16e38a7eebe3a2072449ba9f10c7846262 100644 (file)
@@ -446,10 +446,14 @@ def err_mutable_nonmember : Error<
   "'mutable' can only be applied to member variables">;
 def err_virtual_non_function : Error<
   "'virtual' can only appear on non-static member functions">;
-def err_explicit_non_function : Error<
-  "'explicit' can only appear on non-static member functions">;
 def err_virtual_out_of_class : Error<
   "'virtual' can only be specified inside the class definition">;
+def err_explicit_non_function : Error<
+  "'explicit' can only appear on non-static member functions">;
+def err_explicit_out_of_class : Error<
+  "'explicit' can only be specified inside the class definition">;
+def err_explicit_non_ctor_or_conv_function : Error<
+  "'explicit' can only be applied to a constructor or conversion function">;
 def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
 def err_static_out_of_line : Error<
   "'static' can only be specified inside the class definition">;
index fbe02894ace5ff2311753828191711ba72674a65..938c41efbe6c90e85e2445d531054fc6c23265fa 100644 (file)
@@ -2783,6 +2783,28 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
     }
   }
 
+  // C++ [dcl.fct.spec]p6:
+  //  The explicit specifier shall be used only in the declaration of a
+  //  constructor or conversion function within its class definition; see 12.3.1
+  //  and 12.3.2.
+  if (isExplicit && !NewFD->isInvalidDecl()) {
+    if (!CurContext->isRecord()) {
+      // 'explicit' was specified outside of the class.
+      Diag(D.getDeclSpec().getExplicitSpecLoc(), 
+           diag::err_explicit_out_of_class)
+        << CodeModificationHint::CreateRemoval(
+                                          D.getDeclSpec().getExplicitSpecLoc());
+    } else if (!isa<CXXConstructorDecl>(NewFD) && 
+               !isa<CXXConversionDecl>(NewFD)) {
+      // 'explicit' was specified on a function that wasn't a constructor
+      // or conversion function.
+      Diag(D.getDeclSpec().getExplicitSpecLoc(),
+           diag::err_explicit_non_ctor_or_conv_function)
+        << CodeModificationHint::CreateRemoval(
+                                          D.getDeclSpec().getExplicitSpecLoc());
+    }      
+  }
+
   // Filter out previous declarations that don't match the scope.
   FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
 
index 16a09d836d16b819d0352e91611a55bb0776abe6..fcc1334b1506d48b6f4b2b6f388a627b75480684 100644 (file)
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -verify %s
-// XFAIL: *
 
 class A {
 public:
@@ -7,7 +6,11 @@ public:
   
   explicit operator int(); // expected-warning {{explicit conversion functions are a C++0x extension}}
 
-  explicit void f0(); // expected-error {{'explicit' cannot only be applied to constructor or conversion function}}
+  explicit void f0(); // expected-error {{'explicit' can only be applied to a constructor or conversion function}}
+  
+  operator bool();
 };
 
-explicit A::A() { } // expected-error {{'explicit' cannot be specified outside class definition}}
+explicit A::A() { } // expected-error {{'explicit' can only be specified inside the class definition}}
+explicit A::operator bool() { return false; }  // expected-warning {{explicit conversion functions are a C++0x extension}}\
+                                               // expected-error {{'explicit' can only be specified inside the class definition}}