diff options
Diffstat (limited to 'clang/lib/Sema')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 15 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 60 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 44 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 |
6 files changed, 109 insertions, 20 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index acf52c97fde..fea6f80e545 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1197,6 +1197,7 @@ public: LookupKind(LookupKind), IDNS(0), Redecl(Redecl != NotForRedeclaration), + HideTags(true), Diagnose(Redecl == NotForRedeclaration) {} @@ -1212,6 +1213,7 @@ public: LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl), + HideTags(Other.HideTags), Diagnose(false) {} @@ -1235,6 +1237,12 @@ public: return Redecl; } + /// Sets whether tag declarations should be hidden by non-tag + /// declarations during resolution. The default is true. + void setHideTags(bool Hide) { + HideTags = Hide; + } + /// The identifier namespace of this lookup. This information is /// private to the lookup routines. unsigned getIdentifierNamespace() const { @@ -1441,6 +1449,10 @@ public: unsigned IDNS; // ill-defined until set by lookup bool Redecl; + /// \brief True if tag declarations should be hidden if non-tags + /// are present + bool HideTags; + bool Diagnose; }; @@ -2007,7 +2019,8 @@ public: SourceLocation IdentLoc, IdentifierInfo *Ident); - NamedDecl *BuildUsingDeclaration(SourceLocation UsingLoc, + NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation IdentLoc, DeclarationName Name, diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 84262a4c8f0..de30441c531 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -198,7 +198,7 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { return; // Look through using declarations. - if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration)) + if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier), CurContext); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9ba03a90fc0..698d81e30f3 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2835,7 +2835,7 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, } DeclarationName TargetName = GetNameFromUnqualifiedId(Name); - NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, + NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, Name.getSourceRange().getBegin(), TargetName, AttrList, IsTypeName); if (UD) { @@ -2846,7 +2846,34 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, return DeclPtrTy::make(UD); } -NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, +/// Builds a shadow declaration corresponding to a 'using' declaration. +static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S, + AccessSpecifier AS, + UsingDecl *UD, NamedDecl *Orig) { + // FIXME: diagnose hiding, collisions + + // If we resolved to another shadow declaration, just coalesce them. + if (isa<UsingShadowDecl>(Orig)) { + Orig = cast<UsingShadowDecl>(Orig)->getTargetDecl(); + assert(!isa<UsingShadowDecl>(Orig) && "nested shadow declaration"); + } + + UsingShadowDecl *Shadow + = UsingShadowDecl::Create(SemaRef.Context, SemaRef.CurContext, + UD->getLocation(), UD, Orig); + UD->addShadowDecl(Shadow); + + if (S) + SemaRef.PushOnScopeChains(Shadow, S); + else + SemaRef.CurContext->addDecl(Shadow); + Shadow->setAccess(AS); + + return Shadow; +} + +NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, + SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation IdentLoc, DeclarationName Name, @@ -2880,7 +2907,7 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, // anonymous union that is a member of a base class of the class being // defined, or shall refer to an enumerator for an enumeration type that is // a member of a base class of the class being defined. - + CXXRecordDecl *LookupRD = dyn_cast<CXXRecordDecl>(LookupContext); if (!LookupRD || !RD->isDerivedFrom(LookupRD)) { Diag(SS.getRange().getBegin(), @@ -2898,8 +2925,12 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, } } - // Lookup target name. + // Look up the target name. Unlike most lookups, we do not want to + // hide tag declarations: tag names are visible through the using + // declaration even if hidden by ordinary names. LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName); + R.setHideTags(false); + LookupQualifiedName(R, LookupContext); if (R.empty()) { @@ -2908,24 +2939,33 @@ NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc, return 0; } - // FIXME: handle ambiguity? - NamedDecl *ND = R.getAsSingleDecl(Context); + if (R.isAmbiguous()) + return 0; - if (IsTypeName && !isa<TypeDecl>(ND)) { + if (IsTypeName && + (R.getResultKind() != LookupResult::Found + || !isa<TypeDecl>(R.getFoundDecl()))) { Diag(IdentLoc, diag::err_using_typename_non_type); return 0; } // C++0x N2914 [namespace.udecl]p6: // A using-declaration shall not name a namespace. - if (isa<NamespaceDecl>(ND)) { + if (R.getResultKind() == LookupResult::Found + && isa<NamespaceDecl>(R.getFoundDecl())) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace) << SS.getRange(); return 0; } - return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(), - ND->getLocation(), UsingLoc, ND, NNS, IsTypeName); + UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc, + SS.getRange(), UsingLoc, NNS, Name, + IsTypeName); + + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + BuildUsingShadowDecl(*this, S, AS, UD, *I); + + return UD; } /// getNamespaceDecl - Returns the namespace a decl represents. If the decl diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 1c7dce0def1..58b95fc6790 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -297,7 +297,7 @@ void Sema::LookupResult::resolveKind() { // wherever the object, function, or enumerator name is visible. // But it's still an error if there are distinct tag types found, // even if they're not visible. (ref?) - if (HasTag && !Ambiguous && (HasFunction || HasNonFunction)) + if (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction)) Decls[UniqueTagIndex] = Decls[--N]; Decls.set_size(N); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 721bfb9004c..58fe59e321c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -788,10 +788,46 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E, if (!InstD) return SemaRef.ExprError(); - // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl, - // we need to get the underlying decl. - // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this? - InstD = InstD->getUnderlyingDecl(); + // Flatten using declarations into their shadow declarations. + if (isa<UsingDecl>(InstD)) { + UsingDecl *UD = cast<UsingDecl>(InstD); + + bool HasNonFunction = false; + + llvm::SmallVector<NamedDecl*, 8> Decls; + for (UsingDecl::shadow_iterator I = UD->shadow_begin(), + E = UD->shadow_end(); I != E; ++I) { + NamedDecl *TD = (*I)->getTargetDecl(); + if (!TD->isFunctionOrFunctionTemplate()) + HasNonFunction = true; + + Decls.push_back(TD); + } + + if (Decls.empty()) + return SemaRef.ExprError(); + + if (Decls.size() == 1) + InstD = Decls[0]; + else if (!HasNonFunction) { + OverloadedFunctionDecl *OFD + = OverloadedFunctionDecl::Create(SemaRef.Context, + UD->getDeclContext(), + UD->getDeclName()); + for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(), + E = Decls.end(); I != E; ++I) + if (isa<FunctionDecl>(*I)) + OFD->addOverload(cast<FunctionDecl>(*I)); + else + OFD->addOverload(cast<FunctionTemplateDecl>(*I)); + + InstD = OFD; + } else { + // FIXME + assert(false && "using declaration resolved to mixed set"); + return SemaRef.ExprError(); + } + } CXXScopeSpec SS; NestedNameSpecifier *Qualifier = 0; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a37f3a2b99d..208352fb532 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1019,9 +1019,9 @@ TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) { SS.setScopeRep(NNS); NamedDecl *UD = - SemaRef.BuildUsingDeclaration(D->getLocation(), SS, - D->getTargetNameLocation(), - D->getTargetName(), 0, D->isTypeName()); + SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(), + D->getLocation(), SS, D->getTargetNameLocation(), + D->getDeclName(), 0, D->isTypeName()); if (UD) SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD), D); |

