diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-01-14 17:47:39 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-01-14 17:47:39 +0000 |
| commit | d2e6a457229ccf2478cbd7de5fe763b871a482d8 (patch) | |
| tree | ecb0845d6180610cd78c298314fb8a99b0b09741 /clang/lib | |
| parent | fc59ce1ea47cd9ea8f887dc5e5ae8191ef762957 (diff) | |
| download | bcm5719-llvm-d2e6a457229ccf2478cbd7de5fe763b871a482d8.tar.gz bcm5719-llvm-d2e6a457229ccf2478cbd7de5fe763b871a482d8.zip | |
When qualified lookup into the current instantiation fails (because it
finds nothing), and the current instantiation has dependent base
classes, treat the qualified lookup as if it referred to an unknown
specialization. Fixes PR6031.
llvm-svn: 93433
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/Sema/Sema.h | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 22 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 18 |
5 files changed, 62 insertions, 4 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index b30d335918a..1cce35c0b39 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -144,6 +144,19 @@ CXXRecordDecl::setBases(ASTContext &C, } } +/// Callback function for CXXRecordDecl::forallBases that acknowledges +/// that it saw a base class. +static bool SawBase(const CXXRecordDecl *, void *) { + return true; +} + +bool CXXRecordDecl::hasAnyDependentBases() const { + if (!isDependentContext()) + return false; + + return !forallBases(SawBase, 0); +} + bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const { return getCopyConstructor(Context, Qualifiers::Const) != 0; } diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 8fc34880c11..44bf48915ea 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -2032,6 +2032,7 @@ public: bool isDependentScopeSpecifier(const CXXScopeSpec &SS); CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); bool isUnknownSpecialization(const CXXScopeSpec &SS); + bool isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS); /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the /// global scope ('::'). diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index a8f118ebdd6..8594583ec3e 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -210,6 +210,28 @@ bool Sema::isUnknownSpecialization(const CXXScopeSpec &SS) { return getCurrentInstantiationOf(NNS) == 0; } +/// \brief Determine whether the given scope specifier refers to a +/// current instantiation that has any dependent base clases. +/// +/// This check is typically used when we've performed lookup into the +/// current instantiation of a template, but that lookup failed. When +/// there are dependent bases present, however, the lookup needs to be +/// delayed until template instantiation time. +bool Sema::isCurrentInstantiationWithDependentBases(const CXXScopeSpec &SS) { + if (!SS.isSet()) + return false; + + NestedNameSpecifier *NNS = (NestedNameSpecifier*)SS.getScopeRep(); + if (!NNS->isDependent()) + return false; + + CXXRecordDecl *CurrentInstantiation = getCurrentInstantiationOf(NNS); + if (!CurrentInstantiation) + return false; + + return CurrentInstantiation->hasAnyDependentBases(); +} + /// \brief If the given nested name specifier refers to the current /// instantiation, return the declaration that corresponds to that /// current instantiation (C++0x [temp.dep.type]p1). diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 75fe7fd00fc..c54745f552e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4785,8 +4785,18 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Previous.isAmbiguous()) return DeclPtrTy(); - // A tag 'foo::bar' must already exist. if (Previous.empty()) { + // Name lookup did not find anything. However, if the + // nested-name-specifier refers to the current instantiation, + // and that current instantiation has any dependent base + // classes, we might find something at instantiation time: treat + // this as a dependent elaborated-type-specifier. + if (isCurrentInstantiationWithDependentBases(SS)) { + IsDependent = true; + return DeclPtrTy(); + } + + // A tag 'foo::bar' must already exist. Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange(); Name = 0; Invalid = true; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e75277e823e..d2e70cf9ad6 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1608,15 +1608,19 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, TemplateTy Template; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, EnteringContext, Template); - if (TNK == TNK_Non_template) { + if (TNK == TNK_Non_template && + isCurrentInstantiationWithDependentBases(SS)) { + // This is a dependent template. + } else if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), diag::err_template_kw_refers_to_non_template) << GetNameFromUnqualifiedId(Name) << Name.getSourceRange(); return TemplateTy(); + } else { + // We found something; return it. + return Template; } - - return Template; } NestedNameSpecifier *Qualifier @@ -4765,6 +4769,14 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, Decl *Referenced = 0; switch (Result.getResultKind()) { case LookupResult::NotFound: + if (CurrentInstantiation && CurrentInstantiation->hasAnyDependentBases()) { + // We performed a lookup in the current instantiation and didn't + // find anything. However, this current instantiation has + // dependent bases, so we might be able to find something at + // instantiation time: just build a TypenameType and move on. + return Context.getTypenameType(NNS, &II); + } + DiagID = diag::err_typename_nested_not_found; break; |

