aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-19 00:18:19 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-19 00:18:19 +0000
commite4e5b054b4917f0ee493bb2fda5b1ec749bfb9a1 (patch)
treede98baadcf679cb6d084a3efd3ffd6b8e30f2009 /lib/Sema
parent72374594c5d9ade02451bc85cf9dfa5b0ea106e7 (diff)
Introduce a representation for types that we referred to via a
qualified name, e.g., foo::x so that we retain the nested-name-specifier as written in the source code and can reproduce that qualified name when printing the types back (e.g., in diagnostics). This is PR3493, which won't be complete until finished the other tasks mentioned near the end of this commit. The parser's representation of nested-name-specifiers, CXXScopeSpec, is now a bit fatter, because it needs to contain the scopes that precede each '::' and keep track of whether the global scoping operator '::' was at the beginning. For example, we need to keep track of the leading '::', 'foo', and 'bar' in ::foo::bar::x The Action's CXXScopeTy * is no longer a DeclContext *. It's now the opaque version of the new NestedNameSpecifier, which contains a single component of a nested-name-specifier (either a DeclContext * or a Type *, bitmangled). The new sugar type QualifiedNameType composes a sequence of NestedNameSpecifiers with a representation of the type we're actually referring to. At present, we only build QualifiedNameType nodes within Sema::getTypeName. This will be extended to other type-constructing actions (e.g., ActOnClassTemplateId). Also on the way: QualifiedDeclRefExprs will also store a sequence of NestedNameSpecifiers, so that we can print out the property nested-name-specifier. I expect to also use this for handling dependent names like Fibonacci<I - 1>::value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67265 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h17
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp64
-rw-r--r--lib/Sema/SemaDecl.cpp26
-rw-r--r--lib/Sema/SemaDeclCXX.cpp4
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaLookup.cpp5
-rw-r--r--lib/Sema/SemaTemplate.cpp2
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp8
-rw-r--r--lib/Sema/SemaType.cpp5
9 files changed, 55 insertions, 80 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index d84829a0c7..5106a54f95 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1451,21 +1451,8 @@ public:
SourceLocation RParen);
bool RequireCompleteDeclContext(const CXXScopeSpec &SS);
-
- /// \brief Build a scope representation from a declaration context.
- CXXScopeTy *createScopeRep(DeclContext *DC) {
- return static_cast<CXXScopeTy *>(DC);
- }
-
- /// \brief Build a scope representation from a type.
- CXXScopeTy *createScopeRep(QualType T);
-
- DeclContext *getScopeRepAsDeclContext(const CXXScopeSpec &SS);
- QualType getScopeRepAsType(const CXXScopeSpec &SS);
-
- /// \brief Determines whether this scope specifier is represented as
- /// a type.
- bool isScopeRepType(const CXXScopeSpec &SS);
+
+ DeclContext *computeDeclContext(const CXXScopeSpec &SS);
/// ActOnCXXGlobalScopeSpecifier - Return the object that represents the
/// global scope ('::').
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index e30ec2adcf..156f3a12fb 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -13,51 +13,20 @@
#include "Sema.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/NestedNameSpecifier.h"
#include "clang/Parse/DeclSpec.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
-/// \brief Retrieve the scope represented by this scope specifier as a
-/// DeclContext.
-DeclContext *Sema::getScopeRepAsDeclContext(const CXXScopeSpec &SS) {
- if (SS.isInvalid() || !SS.getScopeRep())
- return 0;
- uintptr_t Rep = reinterpret_cast<uintptr_t>(SS.getScopeRep());
- if ((Rep & 0x01) == 0)
- return reinterpret_cast<DeclContext *>(Rep);
-
- // Retrieve the DeclContext associated with this type.
- QualType T = QualType(reinterpret_cast<Type *>(Rep & ~0x01), 0);
- const TagType *TagT = T->getAsTagType();
- assert(TagT && "No DeclContext from a non-tag type");
- return TagT->getDecl();
-}
-
-/// \brief Retrieve the scope represented by this scope specifier as a
-/// type.
-QualType Sema::getScopeRepAsType(const CXXScopeSpec &SS) {
- if (SS.isInvalid() || !SS.getScopeRep())
- return QualType();
-
- uintptr_t Rep = reinterpret_cast<uintptr_t>(SS.getScopeRep());
- if ((Rep & 0x01) == 0)
- return QualType();
- return QualType(reinterpret_cast<Type *>(Rep & ~0x01), 0);
-}
-
-Action::CXXScopeTy *Sema::createScopeRep(QualType T) {
- assert(((reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()) & 0x01) == 0) &&
- "Scope type with cv-qualifiers");
- if (T.isNull())
+/// \brief Compute the DeclContext that is associated with the given
+/// scope specifier.
+DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS) {
+ if (!SS.isSet() || SS.isInvalid())
return 0;
-
- return reinterpret_cast<CXXScopeTy *>(
- reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()) | 0x01);
-}
-bool Sema::isScopeRepType(const CXXScopeSpec &SS) {
- uintptr_t Rep = reinterpret_cast<uintptr_t>(SS.getScopeRep());
- return Rep & 0x01;
+ NestedNameSpecifier NNS
+ = NestedNameSpecifier::getFromOpaquePtr(SS.getCurrentScopeRep());
+ return NNS.computeDeclContext(Context);
}
/// \brief Require that the context specified by SS be complete.
@@ -73,7 +42,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
if (!SS.isSet() || SS.isInvalid())
return false;
- DeclContext *DC = getScopeRepAsDeclContext(SS);
+ DeclContext *DC = computeDeclContext(SS);
if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {
// If we're currently defining this type, then lookup into the
// type is okay: don't complain that it isn't complete yet.
@@ -95,7 +64,7 @@ bool Sema::RequireCompleteDeclContext(const CXXScopeSpec &SS) {
/// global scope ('::').
Sema::CXXScopeTy *Sema::ActOnCXXGlobalScopeSpecifier(Scope *S,
SourceLocation CCLoc) {
- return createScopeRep(Context.getTranslationUnitDecl());
+ return NestedNameSpecifier(Context.getTranslationUnitDecl()).getAsOpaquePtr();
}
/// ActOnCXXNestedNameSpecifier - Called during parsing of a
@@ -114,9 +83,10 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
if (SD) {
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
if (TD->getUnderlyingType()->isRecordType())
- return createScopeRep(Context.getTypeDeclType(TD));
+ return NestedNameSpecifier(Context.getTypeDeclType(TD).getTypePtr())
+ .getAsOpaquePtr();
} else if (isa<NamespaceDecl>(SD) || isa<RecordDecl>(SD)) {
- return createScopeRep(cast<DeclContext>(SD));
+ return NestedNameSpecifier(cast<DeclContext>(SD)).getAsOpaquePtr();
}
// FIXME: Template parameters and dependent types.
@@ -152,7 +122,8 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
TypeTy *Ty,
SourceRange TypeRange,
SourceLocation CCLoc) {
- return createScopeRep(QualType::getFromOpaquePtr(Ty));
+ return NestedNameSpecifier(QualType::getFromOpaquePtr(Ty).getTypePtr())
+ .getAsOpaquePtr();
}
/// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global
@@ -165,7 +136,7 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
assert(PreDeclaratorDC == 0 && "Previous declarator context not popped?");
PreDeclaratorDC = static_cast<DeclContext*>(S->getEntity());
- CurContext = getScopeRepAsDeclContext(SS);
+ CurContext = computeDeclContext(SS);
S->setEntity(CurContext);
}
@@ -176,8 +147,7 @@ void Sema::ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
/// defining scope.
void Sema::ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) {
assert(SS.isSet() && "Parser passed invalid CXXScopeSpec.");
- assert(S->getEntity() == getScopeRepAsDeclContext(SS) &&
- "Context imbalance!");
+ assert(S->getEntity() == computeDeclContext(SS) && "Context imbalance!");
S->setEntity(PreDeclaratorDC);
PreDeclaratorDC = 0;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index c3dfd19be4..63d446f70c 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -72,22 +72,32 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
}
if (IIDecl) {
+ QualType T;
+
if (TypeDecl *TD = dyn_cast<TypeDecl>(IIDecl)) {
// Check whether we can use this type
(void)DiagnoseUseOfDecl(IIDecl, NameLoc);
- return Context.getTypeDeclType(TD).getAsOpaquePtr();
- }
-
- if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
+ T = Context.getTypeDeclType(TD);
+ } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
// Check whether we can use this interface.
(void)DiagnoseUseOfDecl(IIDecl, NameLoc);
- return Context.getObjCInterfaceType(IDecl).getAsOpaquePtr();
+ T = Context.getObjCInterfaceType(IDecl);
+ } else
+ return 0;
+
+ if (SS && SS->isNotEmpty() && SS->isSet()) {
+ llvm::SmallVector<NestedNameSpecifier, 4> TNNs;
+ for (CXXScopeSpec::iterator TNN = SS->begin(), TNNEnd = SS->end();
+ TNN != TNNEnd; ++TNN)
+ TNNs.push_back(NestedNameSpecifier::getFromOpaquePtr(*TNN));
+ T = Context.getQualifiedNameType(&TNNs[0], TNNs.size(), T);
}
- // Otherwise, could be a variable, function etc.
+ return T.getAsOpaquePtr();
}
+
return 0;
}
@@ -1257,7 +1267,7 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
DeclSpec::SCS_static,
D.getIdentifierLoc());
} else { // Something like "int foo::x;"
- DC = getScopeRepAsDeclContext(D.getCXXScopeSpec());
+ DC = computeDeclContext(D.getCXXScopeSpec());
// FIXME: RequireCompleteDeclContext(D.getCXXScopeSpec()); ?
PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName, true);
@@ -3020,7 +3030,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
}
// FIXME: RequireCompleteDeclContext(SS)?
- DC = getScopeRepAsDeclContext(SS);
+ DC = computeDeclContext(SS);
SearchDC = DC;
// Look-up name inside 'foo::'.
PrevDecl = dyn_cast_or_null<TagDecl>(
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 3307dd0cc4..10e7bd4c97 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -299,8 +299,8 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
bool Sema::isCurrentClassName(const IdentifierInfo &II, Scope *,
const CXXScopeSpec *SS) {
CXXRecordDecl *CurDecl;
- if (SS) {
- DeclContext *DC = getScopeRepAsDeclContext(*SS);
+ if (SS && SS->isSet() && !SS->isInvalid()) {
+ DeclContext *DC = computeDeclContext(*SS);
CurDecl = dyn_cast_or_null<CXXRecordDecl>(DC);
} else
CurDecl = dyn_cast_or_null<CXXRecordDecl>(CurContext);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 1e184d0349..cec94cfdf0 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -727,7 +727,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// implicit member ref, because we want a pointer to the member in general,
// not any specific instance's member.
if (isAddressOfOperand && SS && !SS->isEmpty() && !HasTrailingLParen) {
- DeclContext *DC = getScopeRepAsDeclContext(*SS);
+ DeclContext *DC = computeDeclContext(*SS);
if (D && isa<CXXRecordDecl>(DC)) {
QualType DType;
if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
@@ -942,7 +942,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// - a nested-name-specifier that contains a class-name that
// names a dependent type.
else if (SS && !SS->isEmpty()) {
- for (DeclContext *DC = getScopeRepAsDeclContext(*SS);
+ for (DeclContext *DC = computeDeclContext(*SS);
DC; DC = DC->getParent()) {
// FIXME: could stop early at namespace scope.
if (DC->isRecord()) {
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index d6c36d44a9..616ee3dd93 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1038,9 +1038,10 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
if (SS->isInvalid() || RequireCompleteDeclContext(*SS))
return LookupResult::CreateLookupResult(Context, 0);
- if (SS->isSet())
- return LookupQualifiedName(getScopeRepAsDeclContext(*SS),
+ if (SS->isSet()) {
+ return LookupQualifiedName(computeDeclContext(*SS),
Name, NameKind, RedeclarationOnly);
+ }
}
return LookupName(S, Name, NameKind, RedeclarationOnly,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 6277d9e512..f5317787ba 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -399,7 +399,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK,
DeclContext *SemanticContext = CurContext;
if (SS.isNotEmpty() && !SS.isInvalid()) {
- SemanticContext = getScopeRepAsDeclContext(SS);
+ SemanticContext = computeDeclContext(SS);
// FIXME: need to match up several levels of template parameter
// lists here.
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 4341fc94f9..7df9941aa5 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -492,6 +492,14 @@ InstantiateClassTemplateSpecializationType(
QualType
TemplateTypeInstantiator::
+InstantiateQualifiedNameType(const QualifiedNameType *T,
+ unsigned Quals) const {
+ assert(false && "Cannot have dependent qualified name types (yet)");
+ return QualType();
+}
+
+QualType
+TemplateTypeInstantiator::
InstantiateObjCInterfaceType(const ObjCInterfaceType *T,
unsigned Quals) const {
assert(false && "Objective-C types cannot be dependent");
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index c52f64055b..a8be924fc8 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -742,7 +742,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
}
case DeclaratorChunk::MemberPointer:
// The scope spec must refer to a class, or be dependent.
- DeclContext *DC = getScopeRepAsDeclContext(DeclType.Mem.Scope());
+ DeclContext *DC = computeDeclContext(DeclType.Mem.Scope());
QualType ClsType;
// FIXME: Extend for dependent types when it's actually supported.
// See ActOnCXXNestedNameSpecifier.
@@ -810,8 +810,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
((D.getContext() != Declarator::MemberContext &&
(!D.getCXXScopeSpec().isSet() ||
- !static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep())
- ->isRecord())) ||
+ !computeDeclContext(D.getCXXScopeSpec())->isRecord())) ||
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
if (D.isFunctionDeclarator())
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);