diff options
author | John McCall <rjmccall@apple.com> | 2009-11-18 02:36:19 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-11-18 02:36:19 +0000 |
commit | 7ba107a1863ddfa1664555854f0d7bdb3c491c92 (patch) | |
tree | f0d6842fdd852e98703fce9d62f092d4802dbbec /lib/Sema/SemaDeclCXX.cpp | |
parent | 1d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2 (diff) |
Incremental progress on using declarations. Split UnresolvedUsingDecl into
two classes, one for typenames and one for values; this seems to have some
support from Doug if not necessarily from the extremely-vague-on-this-point
standard. Track the location of the 'typename' keyword in a using-typename
decl. Make a new lookup result for unresolved values and deal with it in
most places.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89184 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 4f04bd2604..cb18064638 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2809,7 +2809,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, const CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsTypeName, + SourceLocation TypenameLoc) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); switch (Name.getKind()) { @@ -2837,7 +2838,9 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, DeclarationName TargetName = GetNameFromUnqualifiedId(Name); NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, Name.getSourceRange().getBegin(), - TargetName, AttrList, IsTypeName); + TargetName, AttrList, + /* IsInstantiation */ false, + IsTypeName, TypenameLoc); if (UD) { PushOnScopeChains(UD, S); UD->setAccess(AS); @@ -2872,13 +2875,20 @@ static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S, return Shadow; } +/// Builds a using declaration. +/// +/// \param IsInstantiation - Whether this call arises from an +/// instantiation of an unresolved using declaration. We treat +/// the lookup differently for these declarations. NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, SourceLocation IdentLoc, DeclarationName Name, AttributeList *AttrList, - bool IsTypeName) { + bool IsInstantiation, + bool IsTypeName, + SourceLocation TypenameLoc) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -2895,9 +2905,16 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, DeclContext *LookupContext = computeDeclContext(SS); if (!LookupContext) { - return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc, - SS.getRange(), NNS, - IdentLoc, Name, IsTypeName); + if (IsTypeName) { + return UnresolvedUsingTypenameDecl::Create(Context, CurContext, + UsingLoc, TypenameLoc, + SS.getRange(), NNS, + IdentLoc, Name); + } else { + return UnresolvedUsingValueDecl::Create(Context, CurContext, + UsingLoc, SS.getRange(), NNS, + IdentLoc, Name); + } } if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { @@ -2929,7 +2946,12 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, // 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); + + // We don't hide tags behind ordinary decls if we're in a + // non-dependent context, but in a dependent context, this is + // important for the stability of two-phase lookup. + if (!IsInstantiation) + R.setHideTags(false); LookupQualifiedName(R, LookupContext); @@ -2942,11 +2964,27 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (R.isAmbiguous()) return 0; - if (IsTypeName && - (R.getResultKind() != LookupResult::Found - || !isa<TypeDecl>(R.getFoundDecl()))) { - Diag(IdentLoc, diag::err_using_typename_non_type); - return 0; + if (IsTypeName) { + // If we asked for a typename and got a non-type decl, error out. + if (R.getResultKind() != LookupResult::Found + || !isa<TypeDecl>(R.getFoundDecl())) { + Diag(IdentLoc, diag::err_using_typename_non_type); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + Diag((*I)->getUnderlyingDecl()->getLocation(), + diag::note_using_decl_target); + return 0; + } + } else { + // If we asked for a non-typename and we got a type, error out, + // but only if this is an instantiation of an unresolved using + // decl. Otherwise just silently find the type name. + if (IsInstantiation && + R.getResultKind() == LookupResult::Found && + isa<TypeDecl>(R.getFoundDecl())) { + Diag(IdentLoc, diag::err_using_dependent_value_is_type); + Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target); + return 0; + } } // C++0x N2914 [namespace.udecl]p6: |