]> granicus.if.org Git - clang/commitdiff
Make sure that we diagnose invalid qualifiers on friend functions.
authorDouglas Gregor <dgregor@apple.com>
Thu, 14 Oct 2010 22:03:51 +0000 (22:03 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 14 Oct 2010 22:03:51 +0000 (22:03 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116527 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaType.cpp
test/CXX/class/class.friend/p1.cpp
test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp [new file with mode: 0644]

index b85d626bd73fb302d8c12e029251dd0dd5d686a5..2b13c213e50c2b8a64f4dd47a65237c30dae2c59 100644 (file)
@@ -1403,13 +1403,16 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
     const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
     assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
 
-    // C++ 8.3.5p4: A cv-qualifier-seq shall only be part of the function type
-    // for a nonstatic member function, the function type to which a pointer
-    // to member refers, or the top-level function type of a function typedef
-    // declaration.
-    bool FreeFunction = (D.getContext() != Declarator::MemberContext &&
+    // C++ 8.3.5p4: 
+    //   A cv-qualifier-seq shall only be part of the function type
+    //   for a nonstatic member function, the function type to which a pointer
+    //   to member refers, or the top-level function type of a function typedef
+    //   declaration.
+    bool FreeFunction = 
+        (D.getContext() != Declarator::MemberContext ||
+         D.getDeclSpec().isFriendSpecified()) &&
         (!D.getCXXScopeSpec().isSet() ||
-         !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true)->isRecord()));
+         !computeDeclContext(D.getCXXScopeSpec(), /*FIXME:*/true)->isRecord());
     if (FnTy->getTypeQuals() != 0 &&
         D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
         (FreeFunction ||
index 3ad4a5f08289d0b7a6ab96f02ddfea9cda2f7fde..bb1af101d242e2f131da0ac5421896a4dc3589af 100644 (file)
@@ -57,7 +57,8 @@ class A {
   friend A operator|(const A& l, const A& r); // okay
   friend A operator|(const A& r); // expected-error {{ overloaded 'operator|' must be a binary operator (has 1 parameter) }}
 
-  friend operator bool() const; // expected-error {{ must use a qualified name when declaring a conversion operator as a friend }}
+  friend operator bool() const; // expected-error {{ must use a qualified name when declaring a conversion operator as a friend }} \
+       // expected-error{{type qualifier is not allowed on this function}}
 
   typedef void ftypedef();
   friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
diff --git a/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp b/test/CXX/dcl.decl/dcl.meaning/dcl.fct/p6.cpp
new file mode 100644 (file)
index 0000000..4873c09
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void f() const; // expected-error{{type qualifier is not allowed on this function}}
+
+struct X {
+  void f() const;
+  friend void g() const; // expected-error{{type qualifier is not allowed on this function}}
+  static void h() const; // expected-error{{type qualifier is not allowed on this function}}
+};
+
+struct Y {
+  friend void X::f() const;
+  friend void ::f() const; // expected-error{{type qualifier is not allowed on this function}}
+};