diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 1 |
6 files changed, 36 insertions, 26 deletions
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index ea6481bd8ab..c3a1e752105 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -516,8 +516,9 @@ static AccessResult MatchesFriend(Sema &S, static AccessResult MatchesFriend(Sema &S, const EffectiveContext &EC, FriendDecl *FriendD) { - // Whitelist accesses if there's an invalid friend declaration. - if (FriendD->isInvalidDecl()) + // Whitelist accesses if there's an invalid or unsupported friend + // declaration. + if (FriendD->isInvalidDecl() || FriendD->isUnsupportedFriend()) return AR_accessible; if (TypeSourceInfo *T = FriendD->getFriendType()) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e7714521c84..d11819461ec 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3410,11 +3410,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, = MatchTemplateParametersToScopeSpecifier( D.getDeclSpec().getSourceRange().getBegin(), D.getCXXScopeSpec(), - (TemplateParameterList**)TemplateParamLists.get(), - TemplateParamLists.size(), - isFriend, - isExplicitSpecialization, - Invalid)) { + TemplateParamLists.get(), + TemplateParamLists.size(), + isFriend, + isExplicitSpecialization, + Invalid)) { // All but one template parameter lists have been matching. --NumMatchedTemplateParamLists; @@ -3462,7 +3462,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (NumMatchedTemplateParamLists > 0 && D.getCXXScopeSpec().isSet()) { NewFD->setTemplateParameterListsInfo(Context, NumMatchedTemplateParamLists, - (TemplateParameterList**)TemplateParamLists.release()); + TemplateParamLists.release()); } if (Invalid) { @@ -3732,14 +3732,20 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Qualified decls generally require a previous declaration. if (D.getCXXScopeSpec().isSet()) { - // ...with the major exception of dependent friend declarations. - // In theory, this condition could be whether the qualifier - // is dependent; in practice, the way we nest template parameters - // prevents this sort of matching from working, so we have to base it - // on the general dependence of the context. - if (isFriend && CurContext->isDependentContext()) { + // ...with the major exception of templated-scope or + // dependent-scope friend declarations. + + // TODO: we currently also suppress this check in dependent + // contexts because (1) the parameter depth will be off when + // matching friend templates and (2) we might actually be + // selecting a friend based on a dependent factor. But there + // are situations where these conditions don't apply and we + // can actually do this check immediately. + if (isFriend && + (NumMatchedTemplateParamLists || + D.getCXXScopeSpec().getScopeRep()->isDependent() || + CurContext->isDependentContext())) { // ignore these - } else { // The user tried to provide an out-of-line definition for a // function that is a member of a class or namespace, but there diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index be1ee358e2a..583f7c59b41 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6532,6 +6532,17 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, if (ND->isInvalidDecl()) FrD->setInvalidDecl(); + else { + FunctionDecl *FD; + if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + FD = FTD->getTemplatedDecl(); + else + FD = cast<FunctionDecl>(ND); + + // Mark templated-scope function declarations as unsupported. + if (FD->getNumTemplateParameterLists()) + FrD->setUnsupportedFriend(true); + } return ND; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f85c3f00709..66ded48c240 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1375,13 +1375,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // If there were at least as many template-ids as there were template // parameter lists, then there are no template parameter lists remaining for // the declaration itself. - if (Idx >= NumParamLists) { - // Silently drop template member friend declarations. - // TODO: implement these - if (IsFriend && NumParamLists) Invalid = true; - + if (Idx >= NumParamLists) return 0; - } // If there were too many template parameter lists, complain about that now. if (Idx != NumParamLists - 1) { @@ -1410,11 +1405,6 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, } } - // Silently drop template member template friend declarations. - // TODO: implement these - if (IsFriend && NumParamLists > 1) - Invalid = true; - // Return the last template parameter list, which corresponds to the // entity being declared. return ParamLists[NumParamLists - 1]; diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index c89273567e5..05ade637195 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -908,6 +908,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { else D->Friend = cast<NamedDecl>(Reader.GetDecl(Record[Idx++])); D->NextFriend = cast_or_null<FriendDecl>(Reader.GetDecl(Record[Idx++])); + D->UnsupportedFriend = (Record[Idx++] != 0); D->FriendLoc = ReadSourceLocation(Record, Idx); } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 0dcc822fbc9..bf7c259635f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -835,6 +835,7 @@ void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) { else Writer.AddDeclRef(D->Friend.get<NamedDecl*>(), Record); Writer.AddDeclRef(D->NextFriend, Record); + Record.push_back(D->UnsupportedFriend); Writer.AddSourceLocation(D->FriendLoc, Record); Code = serialization::DECL_FRIEND; } |