aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-11-18 02:36:19 +0000
committerJohn McCall <rjmccall@apple.com>2009-11-18 02:36:19 +0000
commit7ba107a1863ddfa1664555854f0d7bdb3c491c92 (patch)
treef0d6842fdd852e98703fce9d62f092d4802dbbec /lib/Sema/SemaDeclCXX.cpp
parent1d5fdf3d3b5ea2640ebe8673814a0b6ab7cf5eb2 (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.cpp62
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: