]> granicus.if.org Git - clang/commitdiff
[Sema] Don't crash when friending an unqualified templated constructor
authorDavid Majnemer <david.majnemer@gmail.com>
Wed, 30 Sep 2015 22:07:43 +0000 (22:07 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Wed, 30 Sep 2015 22:07:43 +0000 (22:07 +0000)
Unqualified templated constructors cannot be friended and our lack of a
diagnostic led to violated invariants.  Instead, raise a diagnostic when
processing the friend declaration.

This fixes PR20251.

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

lib/Sema/SemaDeclCXX.cpp
test/CXX/class/class.friend/p1.cpp

index 07bf856719406adfcef9c4304126b71ca8f1c448..7617c92e4e481778f0286d7efe871cf56e04c0b3 100644 (file)
@@ -12689,15 +12689,31 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D,
     DC = CurContext;
     assert(isa<CXXRecordDecl>(DC) && "friend declaration not in class?");
   }
-  
+
   if (!DC->isRecord()) {
+    int DiagArg = -1;
+    switch (D.getName().getKind()) {
+    case UnqualifiedId::IK_ConstructorTemplateId:
+    case UnqualifiedId::IK_ConstructorName:
+      DiagArg = 0;
+      break;
+    case UnqualifiedId::IK_DestructorName:
+      DiagArg = 1;
+      break;
+    case UnqualifiedId::IK_ConversionFunctionId:
+      DiagArg = 2;
+      break;
+    case UnqualifiedId::IK_Identifier:
+    case UnqualifiedId::IK_ImplicitSelfParam:
+    case UnqualifiedId::IK_LiteralOperatorId:
+    case UnqualifiedId::IK_OperatorFunctionId:
+    case UnqualifiedId::IK_TemplateId:
+      break;
+      llvm_unreachable("Didn't expect this kind of unqualified-id!");
+    }
     // This implies that it has to be an operator or function.
-    if (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ||
-        D.getName().getKind() == UnqualifiedId::IK_DestructorName ||
-        D.getName().getKind() == UnqualifiedId::IK_ConversionFunctionId) {
-      Diag(Loc, diag::err_introducing_special_friend) <<
-        (D.getName().getKind() == UnqualifiedId::IK_ConstructorName ? 0 :
-         D.getName().getKind() == UnqualifiedId::IK_DestructorName ? 1 : 2);
+    if (DiagArg >= 0) {
+      Diag(Loc, diag::err_introducing_special_friend) << DiagArg;
       return nullptr;
     }
   }
index 96701b3b05a506b93b52e1b001cab030b299fba2..b83dfa36cd351182b27a314168f2755573b7fbb0 100644 (file)
@@ -79,3 +79,9 @@ class PreDeclared;
 int myoperation(float f) {
   return (int) f;
 }
+
+template <typename T>
+class B {
+  template <typename U>
+  friend B<U>() {} // expected-error {{must use a qualified name when declaring a constructor as a friend}}
+};