diff options
author | Reid Kleckner <reid@kleckner.net> | 2014-07-08 20:05:48 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2014-07-08 20:05:48 +0000 |
commit | 1ba38f887929c42f7b20e691cc370c8c857352f8 (patch) | |
tree | 40a40f9b58997d243682f7d60dcbbebc70b57d9c /clang/lib/Sema/SemaDecl.cpp | |
parent | 3f5ad1a98e211216be9612a60ca30644e0f4073d (diff) | |
download | bcm5719-llvm-1ba38f887929c42f7b20e691cc370c8c857352f8.tar.gz bcm5719-llvm-1ba38f887929c42f7b20e691cc370c8c857352f8.zip |
Allow more lookup of types in dependent base classes
MSVC appears to perform name lookup into dependent base classes when the
dependent base class has a known primary template. This allows them to
know whether some unqualified ids are types or not, which allows them to
parse more class templates without typename keywords.
We can do the same thing when type name lookup fails, and if we find a
single type decl in one of our dependent base classes, recover as though
the user wrote 'typename MyClass::TypeFromBase'.
This allows us to parse some COM smart pointer classes in wrl/client.h
from the Windows 8 SDK.
Reviewers: rsmith
Differential Revision: http://reviews.llvm.org/D4237
llvm-svn: 212561
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 791b4daf01e..49612b0592f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -128,6 +128,56 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const { return false; } +static ParsedType recoverFromTypeInKnownDependentBase(Sema &S, + const IdentifierInfo &II, + SourceLocation NameLoc) { + auto *RD = dyn_cast<CXXRecordDecl>(S.CurContext); + if (!RD || !RD->getDescribedClassTemplate()) + return ParsedType(); + + // Look for type decls in dependent base classes that have known primary + // templates. + bool FoundTypeDecl = false; + for (const auto &Base : RD->bases()) { + auto *TST = Base.getType()->getAs<TemplateSpecializationType>(); + if (!TST || !TST->isDependentType()) + continue; + auto *TD = TST->getTemplateName().getAsTemplateDecl(); + if (!TD) + continue; + auto *BasePrimaryTemplate = cast<CXXRecordDecl>(TD->getTemplatedDecl()); + for (NamedDecl *ND : BasePrimaryTemplate->lookup(&II)) { + if (FoundTypeDecl) + return ParsedType(); + FoundTypeDecl = isa<TypeDecl>(ND); + if (!FoundTypeDecl) + return ParsedType(); + } + } + if (!FoundTypeDecl) + return ParsedType(); + + // We found some types in dependent base classes. Recover as if the user + // wrote 'typename MyClass::II' instead of 'II'. We'll fully resolve the + // lookup during template instantiation. + S.Diag(NameLoc, diag::ext_found_via_dependent_bases_lookup) << &II; + + ASTContext &Context = S.Context; + auto *NNS = NestedNameSpecifier::Create(Context, nullptr, false, + cast<Type>(Context.getRecordType(RD))); + QualType T = Context.getDependentNameType(ETK_Typename, NNS, &II); + + CXXScopeSpec SS; + SS.MakeTrivial(Context, NNS, SourceRange(NameLoc)); + + TypeLocBuilder Builder; + DependentNameTypeLoc DepTL = Builder.push<DependentNameTypeLoc>(T); + DepTL.setNameLoc(NameLoc); + DepTL.setElaboratedKeywordLoc(SourceLocation()); + DepTL.setQualifierLoc(SS.getWithLocInContext(Context)); + return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T)); +} + /// \brief If the identifier refers to a type name within this scope, /// return the declaration of that type. /// @@ -209,6 +259,14 @@ ParsedType Sema::getTypeName(const IdentifierInfo &II, SourceLocation NameLoc, } else { // Perform unqualified name lookup. LookupName(Result, S); + + // For unqualified lookup in a class template in MSVC mode, look into + // dependent base classes where the primary class template is known. + if (Result.empty() && getLangOpts().MSVCCompat && (!SS || SS->isEmpty())) { + if (ParsedType TypeInBase = + recoverFromTypeInKnownDependentBase(*this, II, NameLoc)) + return TypeInBase; + } } NamedDecl *IIDecl = nullptr; @@ -630,6 +688,14 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName); LookupParsedName(Result, S, &SS, !CurMethod); + // For unqualified lookup in a class template in MSVC mode, look into + // dependent base classes where the primary class template is known. + if (Result.empty() && SS.isEmpty() && getLangOpts().MSVCCompat) { + if (ParsedType TypeInBase = + recoverFromTypeInKnownDependentBase(*this, *Name, NameLoc)) + return TypeInBase; + } + // Perform lookup for Objective-C instance variables (including automatically // synthesized instance variables), if we're in an Objective-C method. // FIXME: This lookup really, really needs to be folded in to the normal |