From 20061ec1625cad5306bf6da999caebb50fba6d8f Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 30 Sep 2015 22:07:43 +0000 Subject: [PATCH] [Sema] Don't crash when friending an unqualified templated constructor 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 | 30 +++++++++++++++++++++++------- test/CXX/class/class.friend/p1.cpp | 6 ++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 07bf856719..7617c92e4e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -12689,15 +12689,31 @@ NamedDecl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, DC = CurContext; assert(isa(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; } } diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp index 96701b3b05..b83dfa36cd 100644 --- a/test/CXX/class/class.friend/p1.cpp +++ b/test/CXX/class/class.friend/p1.cpp @@ -79,3 +79,9 @@ class PreDeclared; int myoperation(float f) { return (int) f; } + +template +class B { + template + friend B() {} // expected-error {{must use a qualified name when declaring a constructor as a friend}} +}; -- 2.40.0