diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-03-31 20:19:30 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-03-31 20:19:30 +0000 |
commit | 4a2023f5014e82389d5980d307b89c545dbbac81 (patch) | |
tree | f5d79eebce14b9afda74569cc0d97a6360c17b58 | |
parent | 0798df70753a5feee0e79f2b51f3d4f50127325d (diff) |
Extend DependentNameType with a keyword enum that specifies whether
this was parsed as a typename-specifier, elaborated-type-specifier
(including the kind), or just a dependent qualified type name.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@100039 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 14 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 64 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 38 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 20 |
9 files changed, 115 insertions, 58 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 0bf9642863..c41857ec02 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -630,12 +630,14 @@ public: QualType getQualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType); - QualType getDependentNameType(NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - QualType Canon = QualType()); - QualType getDependentNameType(NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon = QualType()); + QualType getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + QualType Canon = QualType()); + QualType getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const TemplateSpecializationType *TemplateId, + QualType Canon = QualType()); QualType getElaboratedType(QualType UnderlyingType, ElaboratedType::TagKind Tag); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 53346569d3..578382a130 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2550,6 +2550,24 @@ public: static bool classof(const InjectedClassNameType *T) { return true; } }; +/// \brief The elaboration keyword that precedes a qualified type name or +/// introduces an elaborated-type-specifier. +enum ElaboratedTypeKeyword { + /// \brief No keyword precedes the qualified type name. + ETK_None, + /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// \c typename T::type. + ETK_Typename, + /// \brief The "class" keyword introduces the elaborated-type-specifier. + ETK_Class, + /// \brief The "struct" keyword introduces the elaborated-type-specifier. + ETK_Struct, + /// \brief The "union" keyword introduces the elaborated-type-specifier. + ETK_Union, + /// \brief The "enum" keyword introduces the elaborated-type-specifier. + ETK_Enum +}; + /// \brief Represents a type that was referred to via a qualified /// name, e.g., N::M::type. /// @@ -2600,19 +2618,19 @@ public: static bool classof(const QualifiedNameType *T) { return true; } }; -/// \brief Represents a 'typename' specifier that names a type within -/// a dependent type, e.g., "typename T::type". +/// \brief Represents a qualified type name for which the type name is +/// dependent. /// -/// DependentNameType has a very similar structure to QualifiedNameType, -/// which also involves a nested-name-specifier following by a type, -/// and (FIXME!) both can even be prefixed by the 'typename' -/// keyword. However, the two types serve very different roles: -/// QualifiedNameType is a non-semantic type that serves only as sugar -/// to show how a particular type was written in the source -/// code. DependentNameType, on the other hand, only occurs when the -/// nested-name-specifier is dependent, such that we cannot resolve -/// the actual type until after instantiation. +/// DependentNameType represents a class of dependent types that involve a +/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent) +/// name of a type. The DependentNameType may start with a "typename" (for a +/// typename-specifier), "class", "struct", "union", or "enum" (for a +/// dependent elaborated-type-specifier), or nothing (in contexts where we +/// know that we must be referring to a type, e.g., in a base class specifier). class DependentNameType : public Type, public llvm::FoldingSetNode { + /// \brief The keyword used to elaborate this type. + ElaboratedTypeKeyword Keyword; + /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -2622,16 +2640,18 @@ class DependentNameType : public Type, public llvm::FoldingSetNode { /// \brief The type that this typename specifier refers to. NameType Name; - DependentNameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name, - QualType CanonType) - : Type(DependentName, CanonType, true), NNS(NNS), Name(Name) { + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const IdentifierInfo *Name, QualType CanonType) + : Type(DependentName, CanonType, true), + Keyword(Keyword), NNS(NNS), Name(Name) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); } - DependentNameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty, - QualType CanonType) - : Type(DependentName, CanonType, true), NNS(NNS), Name(Ty) { + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const TemplateSpecializationType *Ty, QualType CanonType) + : Type(DependentName, CanonType, true), + Keyword(Keyword), NNS(NNS), Name(Ty) { assert(NNS->isDependent() && "DependentNameType requires a dependent nested-name-specifier"); } @@ -2639,6 +2659,9 @@ class DependentNameType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: + /// \brief Retrieve the keyword used to elaborate this type. + ElaboratedTypeKeyword getKeyword() const { return Keyword; } + /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2662,11 +2685,12 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, NNS, Name); + Profile(ID, Keyword, NNS, Name); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - NameType Name) { + static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, NameType Name) { + ID.AddInteger(Keyword); ID.AddPointer(NNS); ID.AddPointer(Name.getOpaqueValue()); } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7fce55b9df..31c4370ad3 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1962,19 +1962,24 @@ ASTContext::getQualifiedNameType(NestedNameSpecifier *NNS, return QualType(T, 0); } -QualType ASTContext::getDependentNameType(NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - QualType Canon) { +QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + QualType Canon) { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); if (Canon.isNull()) { NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); - if (CanonNNS != NNS) - Canon = getDependentNameType(CanonNNS, Name); + ElaboratedTypeKeyword CanonKeyword = Keyword; + if (Keyword == ETK_None) + CanonKeyword = ETK_Typename; + + if (CanonNNS != NNS || CanonKeyword != Keyword) + Canon = getDependentNameType(CanonKeyword, CanonNNS, Name); } llvm::FoldingSetNodeID ID; - DependentNameType::Profile(ID, NNS, Name); + DependentNameType::Profile(ID, Keyword, NNS, Name); void *InsertPos = 0; DependentNameType *T @@ -1982,20 +1987,21 @@ QualType ASTContext::getDependentNameType(NestedNameSpecifier *NNS, if (T) return QualType(T, 0); - T = new (*this) DependentNameType(NNS, Name, Canon); + T = new (*this) DependentNameType(Keyword, NNS, Name, Canon); Types.push_back(T); DependentNameTypes.InsertNode(T, InsertPos); return QualType(T, 0); } QualType -ASTContext::getDependentNameType(NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon) { +ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const TemplateSpecializationType *TemplateId, + QualType Canon) { assert(NNS->isDependent() && "nested-name-specifier must be dependent"); llvm::FoldingSetNodeID ID; - DependentNameType::Profile(ID, NNS, TemplateId); + DependentNameType::Profile(ID, Keyword, NNS, TemplateId); void *InsertPos = 0; DependentNameType *T @@ -2006,12 +2012,16 @@ ASTContext::getDependentNameType(NestedNameSpecifier *NNS, if (Canon.isNull()) { NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); QualType CanonType = getCanonicalType(QualType(TemplateId, 0)); - if (CanonNNS != NNS || CanonType != QualType(TemplateId, 0)) { + ElaboratedTypeKeyword CanonKeyword = Keyword; + if (Keyword == ETK_None) + CanonKeyword = ETK_Typename; + if (CanonNNS != NNS || CanonKeyword != Keyword || + CanonType != QualType(TemplateId, 0)) { const TemplateSpecializationType *CanonTemplateId = CanonType->getAs<TemplateSpecializationType>(); assert(CanonTemplateId && "Canonical type must also be a template specialization type"); - Canon = getDependentNameType(CanonNNS, CanonTemplateId); + Canon = getDependentNameType(CanonKeyword, CanonNNS, CanonTemplateId); } DependentNameType *CheckT @@ -2019,7 +2029,7 @@ ASTContext::getDependentNameType(NestedNameSpecifier *NNS, assert(!CheckT && "Typename canonical type is broken"); (void)CheckT; } - T = new (*this) DependentNameType(NNS, TemplateId, Canon); + T = new (*this) DependentNameType(Keyword, NNS, TemplateId, Canon); Types.push_back(T); DependentNameTypes.InsertNode(T, InsertPos); return QualType(T, 0); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index da0ac3f5ae..4cf0922ee3 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -572,7 +572,15 @@ void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) { llvm::raw_string_ostream OS(MyString); - OS << "typename "; + switch (T->getKeyword()) { + case ETK_None: break; + case ETK_Typename: OS << "typename "; break; + case ETK_Class: OS << "class "; break; + case ETK_Struct: OS << "struct "; break; + case ETK_Union: OS << "union "; break; + case ETK_Enum: OS << "enum "; break; + } + T->getQualifier()->print(OS, Policy); if (const IdentifierInfo *Ident = T->getIdentifier()) diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index af5e5d3c78..077db7c268 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -1456,8 +1456,9 @@ void CXXNameMangler::mangleExpression(const Expr *E) { // It isn't clear that we ever actually want to have such a // nested-name-specifier; why not just represent it as a typename type? if (!QTy && NNS->getAsIdentifier() && NNS->getPrefix()) { - QTy = getASTContext().getDependentNameType(NNS->getPrefix(), - NNS->getAsIdentifier()) + QTy = getASTContext().getDependentNameType(ETK_Typename, + NNS->getPrefix(), + NNS->getAsIdentifier()) .getTypePtr(); } assert(QTy && "Qualifier was not type!"); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 4898387357..eef73d8d7f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -198,7 +198,9 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc, } else if (UnresolvedUsingTypenameDecl *UUDecl = dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) { // FIXME: preserve source structure information. - T = Context.getDependentNameType(UUDecl->getTargetNestedNameSpecifier(), &II); + T = Context.getDependentNameType(ETK_None, + UUDecl->getTargetNestedNameSpecifier(), + &II); } else { // If it's not plausibly a type, suppress diagnostics. Result.suppressDiagnostics(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5933659f6d..e3533905fd 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4958,7 +4958,8 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); } - return Context.getDependentNameType(NNS, TemplateId).getAsOpaquePtr(); + return Context.getDependentNameType(ETK_Typename, NNS, TemplateId) + .getAsOpaquePtr(); } /// \brief Build the type that describes a C++ typename specifier, @@ -4973,7 +4974,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, // If the nested-name-specifier does not refer to the current // instantiation, then build a typename type. if (!CurrentInstantiation) - return Context.getDependentNameType(NNS, &II); + return Context.getDependentNameType(ETK_Typename, NNS, &II); // The nested-name-specifier refers to the current instantiation, so the // "typename" keyword itself is superfluous. In C++03, the program is @@ -5009,7 +5010,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, case LookupResult::NotFoundInCurrentInstantiation: // Okay, it's a member of an unknown instantiation. - return Context.getDependentNameType(NNS, &II); + return Context.getDependentNameType(ETK_Typename, NNS, &II); case LookupResult::Found: if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { @@ -5135,10 +5136,12 @@ CurrentInstantiationRebuilder::TransformDependentNameType(TypeLocBuilder &TLB, NewTemplateId == QualType(TemplateId, 0)) Result = QualType(T, 0); else - Result = getDerived().RebuildDependentNameType(NNS, NewTemplateId); + Result = getDerived().RebuildDependentNameType(T->getKeyword(), + NNS, NewTemplateId); } else - Result = getDerived().RebuildDependentNameType(NNS, T->getIdentifier(), - SourceRange(TL.getNameLoc())); + Result = getDerived().RebuildDependentNameType(T->getKeyword(), + NNS, T->getIdentifier(), + SourceRange(TL.getNameLoc())); if (Result.isNull()) return QualType(); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 24197adb11..8278691a4a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1261,7 +1261,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, NestedNameSpecifier *NNSPrefix = NNS->getPrefix(); switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: - ClsType = Context.getDependentNameType(NNSPrefix, NNS->getAsIdentifier()); + ClsType = Context.getDependentNameType(ETK_None, NNSPrefix, + NNS->getAsIdentifier()); break; case NestedNameSpecifier::Namespace: diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 361ab2e78c..a2ace07576 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -540,15 +540,17 @@ public: /// By default, builds a new DependentNameType type from the nested-name-specifier /// and the given type. Subclasses may override this routine to provide /// different behavior. - QualType RebuildDependentNameType(NestedNameSpecifier *NNS, QualType T) { + QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, QualType T) { if (NNS->isDependent()) { CXXScopeSpec SS; SS.setScopeRep(NNS); if (!SemaRef.computeDeclContext(SS)) - return SemaRef.Context.getDependentNameType(NNS, + return SemaRef.Context.getDependentNameType(Keyword, NNS, cast<TemplateSpecializationType>(T)); } + // FIXME: Handle elaborated-type-specifiers separately. return SemaRef.Context.getQualifiedNameType(NNS, T); } @@ -557,9 +559,11 @@ public: /// By default, performs semantic analysis when building the typename type /// (or qualified name type). Subclasses may override this routine to provide /// different behavior. - QualType RebuildDependentNameType(NestedNameSpecifier *NNS, - const IdentifierInfo *Id, - SourceRange SR) { + QualType RebuildDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Id, + SourceRange SR) { + // FIXME: Handle elaborated-type-specifiers separately. return SemaRef.CheckTypenameType(NNS, *Id, SR); } @@ -3023,9 +3027,11 @@ QualType TreeTransform<Derived>::TransformDependentNameType(TypeLocBuilder &TLB, NewTemplateId == QualType(TemplateId, 0)) return QualType(T, 0); - Result = getDerived().RebuildDependentNameType(NNS, NewTemplateId); + Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, + NewTemplateId); } else { - Result = getDerived().RebuildDependentNameType(NNS, T->getIdentifier(), SR); + Result = getDerived().RebuildDependentNameType(T->getKeyword(), NNS, + T->getIdentifier(), SR); } if (Result.isNull()) return QualType(); |