Author: majnemer Date: Wed Sep 30 17:07:43 2015 New Revision: 248953 URL: http://llvm.org/viewvc/llvm-project?rev=248953&view=rev Log: [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. Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/test/CXX/class/class.friend/p1.cpp Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=248953&r1=248952&r2=248953&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Sep 30 17:07:43 2015 @@ -12689,15 +12689,31 @@ NamedDecl *Sema::ActOnFriendFunctionDecl 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; } } Modified: cfe/trunk/test/CXX/class/class.friend/p1.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/class.friend/p1.cpp?rev=248953&r1=248952&r2=248953&view=diff ============================================================================== --- cfe/trunk/test/CXX/class/class.friend/p1.cpp (original) +++ cfe/trunk/test/CXX/class/class.friend/p1.cpp Wed Sep 30 17:07:43 2015 @@ -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}} +}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits