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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67799 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 9e11961..ca864a2 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -24,24 +24,41 @@
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 @@
/// 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,19 +110,37 @@
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);
- // FIXME: Template parameters and dependent types.
- // FIXME: C++0x scoped enums
+ 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());
+ }
// Fall through to produce an error: we found something that isn't
// a class or a namespace.
@@ -137,8 +172,10 @@
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 @@
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 @@
while (!S->getEntity() && S->getParent())
S = S->getParent();
CurContext = static_cast<DeclContext*>(S->getEntity());
+ assert(CurContext && "No context?");
}