зеркало из https://github.com/microsoft/clang-1.git
Support friend function specializations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@99389 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
2eef829b19
Коммит
7ad650f88e
|
@ -1256,6 +1256,8 @@ def err_template_spec_decl_function_scope : Error<
|
|||
"explicit specialization of %0 in function scope">;
|
||||
def err_template_spec_decl_class_scope : Error<
|
||||
"explicit specialization of %0 in class scope">;
|
||||
def err_template_spec_decl_friend : Error<
|
||||
"cannot declare an explicit specialization in a friend">;
|
||||
def err_template_spec_decl_out_of_scope_global : Error<
|
||||
"%select{class template|class template partial|function template|member "
|
||||
"function|static data member|member class}0 specialization of %1 must "
|
||||
|
|
|
@ -53,10 +53,11 @@ bool Sema::SetMemberAccessSpecifier(NamedDecl *MemberDecl,
|
|||
|
||||
namespace {
|
||||
struct EffectiveContext {
|
||||
EffectiveContext() : Function(0), Dependent(false) {}
|
||||
EffectiveContext() : Inner(0), Function(0), Dependent(false) {}
|
||||
|
||||
explicit EffectiveContext(DeclContext *DC) {
|
||||
Dependent = DC->isDependentContext();
|
||||
explicit EffectiveContext(DeclContext *DC)
|
||||
: Inner(DC),
|
||||
Dependent(DC->isDependentContext()) {
|
||||
|
||||
if (isa<FunctionDecl>(DC)) {
|
||||
Function = cast<FunctionDecl>(DC)->getCanonicalDecl();
|
||||
|
@ -86,14 +87,15 @@ struct EffectiveContext {
|
|||
!= Records.end();
|
||||
}
|
||||
|
||||
DeclContext *getPrimaryContext() const {
|
||||
assert((Function || !Records.empty()) && "context has no primary context");
|
||||
if (Function) return Function;
|
||||
return Records[0];
|
||||
/// Retrieves the innermost "useful" context. Can be null if we're
|
||||
/// doing access-control without privileges.
|
||||
DeclContext *getInnerContext() const {
|
||||
return Inner;
|
||||
}
|
||||
|
||||
typedef llvm::SmallVectorImpl<CXXRecordDecl*>::const_iterator record_iterator;
|
||||
|
||||
DeclContext *Inner;
|
||||
llvm::SmallVector<CXXRecordDecl*, 4> Records;
|
||||
FunctionDecl *Function;
|
||||
bool Dependent;
|
||||
|
@ -636,7 +638,7 @@ static void DelayAccess(Sema &S,
|
|||
SourceLocation Loc,
|
||||
const Sema::AccessedEntity &Entity) {
|
||||
assert(EC.isDependent() && "delaying non-dependent access");
|
||||
DeclContext *DC = EC.getPrimaryContext();
|
||||
DeclContext *DC = EC.getInnerContext();
|
||||
assert(DC->isDependentContext() && "delaying non-dependent access");
|
||||
DependentDiagnostic::Create(S.Context, DC, DependentDiagnostic::Access,
|
||||
Loc,
|
||||
|
|
|
@ -2918,6 +2918,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
} else {
|
||||
// This is a function template specialization.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
|
||||
// C++0x [temp.expl.spec]p20 forbids "template<> void foo(int);".
|
||||
if (isFriend && isFunctionTemplateSpecialization) {
|
||||
SourceRange Range = TemplateParams->getSourceRange();
|
||||
Diag(D.getIdentifierLoc(), diag::err_template_spec_decl_friend)
|
||||
<< Name << Range << CodeModificationHint::CreateRemoval(Range);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Free this memory properly.
|
||||
|
@ -3101,6 +3108,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
|
|||
D.getDeclSpec().getSourceRange().getBegin(),
|
||||
"template<> ");
|
||||
isFunctionTemplateSpecialization = true;
|
||||
} else {
|
||||
// "friend void foo<>(int);" is an implicit specialization decl.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3961,9 +3961,14 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
|
||||
// FIXME: Check if the prior specialization has a point of instantiation.
|
||||
// If so, we have run afoul of .
|
||||
|
||||
// If this is a friend declaration, then we're not really declaring
|
||||
// an explicit specialization.
|
||||
bool isFriend = (FD->getFriendObjectKind() != Decl::FOK_None);
|
||||
|
||||
// Check the scope of this explicit specialization.
|
||||
if (CheckTemplateSpecializationScope(*this,
|
||||
if (!isFriend &&
|
||||
CheckTemplateSpecializationScope(*this,
|
||||
Specialization->getPrimaryTemplate(),
|
||||
Specialization, FD->getLocation(),
|
||||
false))
|
||||
|
@ -3980,7 +3985,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
assert(SpecInfo && "Function template specialization info missing?");
|
||||
|
||||
bool SuppressNew = false;
|
||||
if (CheckSpecializationInstantiationRedecl(FD->getLocation(),
|
||||
if (!isFriend &&
|
||||
CheckSpecializationInstantiationRedecl(FD->getLocation(),
|
||||
TSK_ExplicitSpecialization,
|
||||
Specialization,
|
||||
SpecInfo->getTemplateSpecializationKind(),
|
||||
|
@ -3990,7 +3996,8 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
|
||||
// Mark the prior declaration as an explicit specialization, so that later
|
||||
// clients know that this is an explicit specialization.
|
||||
SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
|
||||
if (!isFriend)
|
||||
SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
|
||||
|
||||
// Turn the given function declaration into a function template
|
||||
// specialization, with the template arguments from the previous
|
||||
|
@ -3999,7 +4006,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
|
|||
new (Context) TemplateArgumentList(
|
||||
*Specialization->getTemplateSpecializationArgs()),
|
||||
/*InsertPos=*/0,
|
||||
TSK_ExplicitSpecialization);
|
||||
SpecInfo->getTemplateSpecializationKind());
|
||||
|
||||
// The "previous declaration" for this function template specialization is
|
||||
// the prior function template specialization.
|
||||
|
|
|
@ -95,7 +95,7 @@ namespace test3 {
|
|||
friend class User<bool>;
|
||||
friend bool transform<>(Bool, bool);
|
||||
|
||||
bool value; // expected-note {{declared private here}}
|
||||
bool value; // expected-note 2 {{declared private here}}
|
||||
};
|
||||
|
||||
template <class T> class User {
|
||||
|
@ -105,13 +105,13 @@ namespace test3 {
|
|||
};
|
||||
|
||||
template <class T> T transform(Bool b, T value) {
|
||||
if (b.value)
|
||||
if (b.value) // expected-error {{'value' is a private member of 'test3::Bool'}}
|
||||
return value;
|
||||
return value + 1;
|
||||
}
|
||||
|
||||
template bool transform(Bool, bool);
|
||||
template int transform(Bool, int);
|
||||
template int transform(Bool, int); // expected-note {{requested here}}
|
||||
|
||||
template class User<bool>;
|
||||
template class User<int>; // expected-note {{requested here}}
|
||||
|
|
|
@ -6,7 +6,7 @@ template<typename T>
|
|||
struct A { };
|
||||
|
||||
struct X {
|
||||
template<> friend void f<int>(int); // expected-error{{in class scope}}
|
||||
template<> friend void f<int>(int); // expected-error{{in a friend}}
|
||||
template<> friend class A<int>; // expected-error{{cannot be a friend}}
|
||||
|
||||
friend void f<float>(float); // okay
|
||||
|
|
Загрузка…
Ссылка в новой задаче