diff options
| author | John McCall <rjmccall@apple.com> | 2010-06-16 08:42:20 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-06-16 08:42:20 +0000 | 
| commit | e9cccd86da2fe29b7488e4888fa09c6834c82f31 (patch) | |
| tree | 5a7b17c3fc2c082838d3ecae813af472a552eab5 /clang/lib/Sema/SemaOverload.cpp | |
| parent | f128bdcb557e20b20d02ca0351aa4ff19a1b0c42 (diff) | |
| download | bcm5719-llvm-e9cccd86da2fe29b7488e4888fa09c6834c82f31.tar.gz bcm5719-llvm-e9cccd86da2fe29b7488e4888fa09c6834c82f31.zip | |
Fix a point of semantics with using declaration hiding:  method templates
introduced by using decls are hidden even if their template parameter lists
or return types differ from the "overriding" declaration.
Propagate using shadow declarations around more effectively when looking up
template-ids.  Reperform lookup for template-ids in member expressions so that
access control is properly set up.
Fix some number of latent bugs involving template-ids with totally invalid
base types.  You can only actually get these with a scope specifier, since
otherwise the template-id won't parse as a template-id.
Fixes PR7384.
llvm-svn: 106093
Diffstat (limited to 'clang/lib/Sema/SemaOverload.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 53 | 
1 files changed, 46 insertions, 7 deletions
| diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 24fdff37572..4baa307890e 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -500,19 +500,54 @@ void OverloadCandidateSet::clear() {  // identical (return types of functions are not part of the  // signature), IsOverload returns false and MatchedDecl will be set to  // point to the FunctionDecl for #2. +// +// 'NewIsUsingShadowDecl' indicates that 'New' is being introduced +// into a class by a using declaration.  The rules for whether to hide +// shadow declarations ignore some properties which otherwise figure +// into a function template's signature.  Sema::OverloadKind -Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old, -                    NamedDecl *&Match) { +Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, +                    NamedDecl *&Match, bool NewIsUsingDecl) {    for (LookupResult::iterator I = Old.begin(), E = Old.end();           I != E; ++I) { -    NamedDecl *OldD = (*I)->getUnderlyingDecl(); +    NamedDecl *OldD = *I; + +    bool OldIsUsingDecl = false; +    if (isa<UsingShadowDecl>(OldD)) { +      OldIsUsingDecl = true; + +      // We can always introduce two using declarations into the same +      // context, even if they have identical signatures. +      if (NewIsUsingDecl) continue; + +      OldD = cast<UsingShadowDecl>(OldD)->getTargetDecl(); +    } + +    // If either declaration was introduced by a using declaration, +    // we'll need to use slightly different rules for matching. +    // Essentially, these rules are the normal rules, except that +    // function templates hide function templates with different +    // return types or template parameter lists. +    bool UseMemberUsingDeclRules = +      (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord(); +      if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) { -      if (!IsOverload(New, OldT->getTemplatedDecl())) { +      if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { +        if (UseMemberUsingDeclRules && OldIsUsingDecl) { +          HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); +          continue; +        } +          Match = *I;          return Ovl_Match;        }      } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) { -      if (!IsOverload(New, OldF)) { +      if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) { +        if (UseMemberUsingDeclRules && OldIsUsingDecl) { +          HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); +          continue; +        } +          Match = *I;          return Ovl_Match;        } @@ -536,7 +571,8 @@ Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old,    return Ovl_Overload;  } -bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) { +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old, +                      bool UseUsingDeclRules) {    FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();    FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate(); @@ -581,7 +617,10 @@ bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {    //    // We check the return type and template parameter lists for function    // templates first; the remaining checks follow. -  if (NewTemplate && +  // +  // However, we don't consider either of these when deciding whether +  // a member introduced by a shadow declaration is hidden. +  if (!UseUsingDeclRules && NewTemplate &&        (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),                                         OldTemplate->getTemplateParameters(),                                         false, TPL_TemplateMatch) || | 

