diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-03-26 23:50:42 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-03-26 23:50:42 +0000 |
commit | f21eb49a0404949c481c671965149e9cbdbc376d (patch) | |
tree | 23fbe9fba1983929ee3ba4883042a907a695e3d5 /clang/lib/Sema/SemaCXXScopeSpec.cpp | |
parent | fe7c0492a066a2bb5e91ef1a6b2ed413678abbcd (diff) | |
download | bcm5719-llvm-f21eb49a0404949c481c671965149e9cbdbc376d.tar.gz bcm5719-llvm-f21eb49a0404949c481c671965149e9cbdbc376d.zip |
Revamp our representation of C++ nested-name-specifiers. We now have a
uniqued representation that should both save some memory and make it
far easier to properly build canonical types for types involving
dependent nested-name-specifiers, e.g., "typename T::Nested::type".
This approach will greatly simplify the representation of
CXXScopeSpec. That'll be next.
llvm-svn: 67799
Diffstat (limited to 'clang/lib/Sema/SemaCXXScopeSpec.cpp')
-rw-r--r-- | clang/lib/Sema/SemaCXXScopeSpec.cpp | 87 |
1 files changed, 63 insertions, 24 deletions
diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index 9e1196143b6..ca864a2a2ef 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -24,24 +24,41 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return 0; - NestedNameSpecifier NNS - = NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep()); - return NNS.computeDeclContext(Context); + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep()); + if (NNS->isDependent()) + return 0; + + switch (NNS->getKind()) { + case NestedNameSpecifier::Identifier: + assert(false && "Dependent nested-name-specifier has no DeclContext"); + break; + + case NestedNameSpecifier::Namespace: + return NNS->getAsNamespace(); + + case NestedNameSpecifier::TypeSpec: + case NestedNameSpecifier::TypeSpecWithTemplate: { + const TagType *Tag = NNS->getAsType()->getAsTagType(); + assert(Tag && "Non-tag type in nested-name-specifier"); + return Tag->getDecl(); + } break; + + case NestedNameSpecifier::Global: + return Context.getTranslationUnitDecl(); + } + + // Required to silence a GCC warning. + return 0; } bool Sema::isDependentScopeSpecifier(const CXXScopeSpec &SS) { if (!SS.isSet() || SS.isInvalid()) return false; - NestedNameSpecifier NNS - = NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep()); - - if (Type *T = NNS.getAsType()) - return T->isDependentType(); - - // FIXME: What about the injected-class-name of a class template? It - // is dependent, but we represent it as a declaration. - return false; + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep()); + return NNS->isDependent(); } /// \brief Require that the context specified by SS be complete. @@ -79,7 +96,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) { /// global scope ('::'). Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc) { - return NestedNameSpecifier(Context.getTranslationUnitDecl()).getAsOpaquePtr(); + return NestedNameSpecifier::GlobalSpecifier(Context); } /// ActOnCXXNestedNameSpecifier - Called during parsing of a @@ -93,20 +110,38 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, SourceLocation IdLoc, SourceLocation CCLoc, IdentifierInfo &II) { + NestedNameSpecifier *Prefix + = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep()); + + // If the prefix is already dependent, there is no name lookup to + // perform. Just build the resulting nested-name-specifier. + if (Prefix && Prefix->isDependent()) + return NestedNameSpecifier::Create(Context, Prefix, &II); + NamedDecl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName); if (SD) { - if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { - if (TD->getUnderlyingType()->isRecordType()) - return NestedNameSpecifier(Context.getTypeDeclType(TD).getTypePtr()) - .getAsOpaquePtr(); - } else if (isa<NamespaceDecl>(SD) || isa<RecordDecl>(SD)) { - return NestedNameSpecifier(cast<DeclContext>(SD)).getAsOpaquePtr(); + if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(SD)) + return NestedNameSpecifier::Create(Context, Prefix, Namespace); + + if (TypeDecl *Type = dyn_cast<TypeDecl>(SD)) { + // Determine whether we have a class (or, in C++0x, an enum) or + // a typedef thereof. If so, build the nested-name-specifier. + QualType T; + if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { + if (TD->getUnderlyingType()->isRecordType() || + (getLangOptions().CPlusPlus0x && + TD->getUnderlyingType()->isEnumeralType())) + T = Context.getTypeDeclType(TD); + } else if (isa<RecordDecl>(Type) || + (getLangOptions().CPlusPlus0x && isa<EnumDecl>(Type))) + T = Context.getTypeDeclType(Type); + + if (!T.isNull()) + return NestedNameSpecifier::Create(Context, Prefix, false, + T.getTypePtr()); } - // FIXME: Template parameters and dependent types. - // FIXME: C++0x scoped enums - // Fall through to produce an error: we found something that isn't // a class or a namespace. } @@ -137,8 +172,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S, TypeTy *Ty, SourceRange TypeRange, SourceLocation CCLoc) { - return NestedNameSpecifier(QualType::getFromOpaquePtr(Ty).getTypePtr()) - .getAsOpaquePtr(); + NestedNameSpecifier *Prefix + = static_cast<NestedNameSpecifier *>(SS.getCurrentScopeRep()); + return NestedNameSpecifier::Create(Context, Prefix, /*FIXME:*/false, + QualType::getFromOpaquePtr(Ty).getTypePtr()); } /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global @@ -152,6 +189,7 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?"); PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity()); CurContext = computeDeclContext(SS); + assert(CurContext && "No context?"); S->setEntity(CurContext); } @@ -170,4 +208,5 @@ void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { while (!S->getEntity() && S->getParent()) S = S->getParent(); CurContext = static_cast<DeclContext*>(S->getEntity()); + assert(CurContext && "No context?"); } |