diff options
author | John McCall <rjmccall@apple.com> | 2009-12-04 22:46:56 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2009-12-04 22:46:56 +0000 |
commit | ed97649e9574b9d854fa4d6109c9333ae0993554 (patch) | |
tree | 799328f967a0d6af2b9dbdd5c2df4a8392275680 | |
parent | cce9fde82ad99cb96c820084d636c9bfdfcff30a (diff) |
Fix "using typename" and the instantiation of non-dependent using declarations.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90614 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 27 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 33 | ||||
-rw-r--r-- | include/clang/AST/TypeLoc.h | 155 | ||||
-rw-r--r-- | include/clang/AST/TypeLocBuilder.h | 45 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 1 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 4 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 41 | ||||
-rw-r--r-- | lib/AST/TypeLoc.cpp | 29 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 6 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 11 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 83 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 84 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 51 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp | 183 | ||||
-rw-r--r-- | test/SemaCXX/using-decl-templates.cpp | 11 |
20 files changed, 670 insertions, 117 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 6efb634a8c..78ead42007 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -57,6 +57,7 @@ namespace clang { class TypeDecl; class TypedefDecl; class UsingDecl; + class UsingShadowDecl; namespace Builtin { class Context; } @@ -183,8 +184,10 @@ class ASTContext { llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *> InstantiatedFromStaticDataMember; - /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls - /// where created during instantiation. + /// \brief Keeps track of the declaration from which a UsingDecl was + /// created during instantiation. The source declaration is always + /// a UsingDecl, an UnresolvedUsingValueDecl, or an + /// UnresolvedUsingTypenameDecl. /// /// For example: /// \code @@ -203,8 +206,10 @@ class ASTContext { /// /// This mapping will contain an entry that maps from the UsingDecl in /// B<int> to the UnresolvedUsingDecl in B<T>. - llvm::DenseMap<UsingDecl *, NamedDecl *> - InstantiatedFromUnresolvedUsingDecl; + llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl; + + llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*> + InstantiatedFromUsingShadowDecl; llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; @@ -282,14 +287,18 @@ public: void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, TemplateSpecializationKind TSK); - /// \brief If this using decl is instantiated from an unresolved using decl, + /// \brief If the given using decl is an instantiation of a + /// (possibly unresolved) using decl from a template instantiation, /// return it. - NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); + NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst); - /// \brief Note that the using decl \p Inst is an instantiation of - /// the unresolved using decl \p Tmpl of a class template. - void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl); + /// \brief Remember that the using decl \p Inst is an instantiation + /// of the using decl \p Pattern of a class template. + void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern); + void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, + UsingShadowDecl *Pattern); + UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst); FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 16b6dd7215..7b5598c460 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -76,6 +76,7 @@ namespace clang { class ObjCInterfaceDecl; class ObjCProtocolDecl; class ObjCMethodDecl; + class UnresolvedUsingTypenameDecl; class Expr; class Stmt; class SourceLocation; @@ -1863,6 +1864,38 @@ public: }; +/// \brief Represents the dependent type named by a dependently-scoped +/// typename using declaration, e.g. +/// using typename Base<T>::foo; +/// Template instantiation turns these into the underlying type. +class UnresolvedUsingType : public Type { + UnresolvedUsingTypenameDecl *Decl; + + UnresolvedUsingType(UnresolvedUsingTypenameDecl *D) + : Type(UnresolvedUsing, QualType(), true), Decl(D) {} + friend class ASTContext; // ASTContext creates these. +public: + + UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == UnresolvedUsing; + } + static bool classof(const UnresolvedUsingType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + return Profile(ID, Decl); + } + static void Profile(llvm::FoldingSetNodeID &ID, + UnresolvedUsingTypenameDecl *D) { + ID.AddPointer(D); + } +}; + + class TypedefType : public Type { TypedefDecl *Decl; protected: diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index f08ca6bf46..47274450b1 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -340,16 +340,20 @@ public: } }; + struct TypeSpecLocInfo { SourceLocation NameLoc; }; /// \brief A reasonable base class for TypeLocs that correspond to /// types that are written as a type-specifier. -template <class Derived, class TypeClass, class LocalData = TypeSpecLocInfo> -class TypeSpecTypeLoc - : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { +class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + TypeSpecTypeLoc, + Type, + TypeSpecLocInfo> { public: + enum { LocalDataSize = sizeof(TypeSpecLocInfo) }; + SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } @@ -362,31 +366,79 @@ public: void initializeLocal(SourceLocation Loc) { setNameLoc(Loc); } + + static bool classof(const TypeLoc *TL); + static bool classof(const TypeSpecTypeLoc *TL) { return true; } }; + /// \brief Wrapper for source info for typedefs. -class TypedefTypeLoc : public TypeSpecTypeLoc<TypedefTypeLoc,TypedefType> { +class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypedefTypeLoc, + TypedefType> { public: TypedefDecl *getTypedefDecl() const { return getTypePtr()->getDecl(); } }; +/// \brief Wrapper for source info for unresolved typename using decls. +class UnresolvedUsingTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + UnresolvedUsingTypeLoc, + UnresolvedUsingType> { +public: + UnresolvedUsingTypenameDecl *getDecl() const { + return getTypePtr()->getDecl(); + } +}; + +/// \brief Wrapper for source info for tag types. Note that this only +/// records source info for the name itself; a type written 'struct foo' +/// should be represented as an ElaboratedTypeLoc. We currently +/// only do that when C++ is enabled because of the expense of +/// creating an ElaboratedType node for so many type references in C. +class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TagTypeLoc, + TagType> { +public: + TagDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for source info for record types. +class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + RecordTypeLoc, + RecordType> { +public: + RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for source info for enum types. +class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + EnumTypeLoc, + EnumType> { +public: + EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; /// \brief Wrapper for source info for builtin types. -class BuiltinTypeLoc : public TypeSpecTypeLoc<BuiltinTypeLoc, - BuiltinType> { +class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + BuiltinTypeLoc, + BuiltinType> { }; /// \brief Wrapper for template type parameters. -class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc, - TemplateTypeParmType> { +class TemplateTypeParmTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TemplateTypeParmTypeLoc, + TemplateTypeParmType> { }; /// \brief Wrapper for substituted template type parameters. class SubstTemplateTypeParmTypeLoc : - public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc, - SubstTemplateTypeParmType> { + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + SubstTemplateTypeParmTypeLoc, + SubstTemplateTypeParmType> { }; @@ -944,63 +996,84 @@ private: } }; -// None of these types have proper implementations yet. +//===----------------------------------------------------------------------===// +// +// All of these need proper implementations. +// +//===----------------------------------------------------------------------===// -class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> { +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + VectorTypeLoc, + VectorType> { }; +// FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc, ExtVectorType> { }; +// FIXME: attribute locations. // For some reason, this isn't a subtype of VectorType. class DependentSizedExtVectorTypeLoc : - public TypeSpecTypeLoc<DependentSizedExtVectorTypeLoc, - DependentSizedExtVectorType> { + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DependentSizedExtVectorTypeLoc, + DependentSizedExtVectorType> { }; -class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc, - FixedWidthIntType> { +// FIXME: I'm not sure how you actually specify these; with attributes? +class FixedWidthIntTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + FixedWidthIntTypeLoc, + FixedWidthIntType> { }; -class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc, - ComplexType> { +// FIXME: location of the '_Complex' keyword. +class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + ComplexTypeLoc, + ComplexType> { }; -class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc, - TypeOfExprType> { +// FIXME: location of the 'typeof' and parens (the expression is +// carried by the type). +class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypeOfExprTypeLoc, + TypeOfExprType> { }; -class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> { +// FIXME: location of the 'typeof' and parens; also the DeclaratorInfo +// for the inner type, or (maybe) just express that inline to the TypeLoc. +class TypeOfTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypeOfTypeLoc, + TypeOfType> { }; -class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> { -}; - -class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> { -}; - -class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, - RecordTypeLoc, - RecordType> { -}; - -class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, - EnumTypeLoc, - EnumType> { +// FIXME: location of the 'decltype' and parens. +class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DecltypeTypeLoc, + DecltypeType> { }; -class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc, - ElaboratedType> { +// FIXME: location of the tag keyword. +class ElaboratedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + ElaboratedTypeLoc, + ElaboratedType> { }; -class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc, - QualifiedNameType> { +// FIXME: locations for the nested name specifier; at the very least, +// a SourceRange. +class QualifiedNameTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + QualifiedNameTypeLoc, + QualifiedNameType> { }; -class TypenameTypeLoc : public TypeSpecTypeLoc<TypenameTypeLoc, - TypenameType> { +// FIXME: locations for the typename keyword and nested name specifier. +class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypenameTypeLoc, + TypenameType> { }; } diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index 00e2b7f832..f4263c3de3 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -59,9 +59,35 @@ class TypeLocBuilder { grow(Requested); } - /// Pushes space for a new TypeLoc onto the given type. Invalidates + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs + /// previously retrieved from this builder. + TypeSpecTypeLoc pushTypeSpec(QualType T) { + size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; + return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); + } + + + /// Pushes space for a new TypeLoc of the given type. Invalidates /// any TypeLocs previously retrieved from this builder. template <class TyLocType> TyLocType push(QualType T) { + size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + return cast<TyLocType>(pushImpl(T, LocalSize)); + } + + /// Creates a DeclaratorInfo for the given type. + DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize); + memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); + return DI; + } + +private: + TypeLoc pushImpl(QualType T, size_t LocalSize) { #ifndef NDEBUG QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); assert(TLast == LastTy && @@ -69,8 +95,6 @@ class TypeLocBuilder { LastTy = T; #endif - size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); - // If we need to grow, grow by a factor of 2. if (LocalSize > Index) { size_t RequiredCapacity = Capacity + (LocalSize - Index); @@ -82,22 +106,9 @@ class TypeLocBuilder { Index -= LocalSize; - return cast<TyLocType>(TypeLoc(T, &Buffer[Index])); - } - - /// Creates a DeclaratorInfo for the given type. - DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) { -#ifndef NDEBUG - assert(T == LastTy && "type doesn't match last type pushed!"); -#endif - - size_t FullDataSize = Capacity - Index; - DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize); - memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); - return DI; + return TypeLoc(T, &Buffer[Index]); } - private: /// Grow to the given capacity. void grow(size_t NewCapacity) { assert(NewCapacity > Capacity); diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index c2721236af..b9d37992a6 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -71,6 +71,7 @@ TYPE(ExtVector, VectorType) ABSTRACT_TYPE(Function, Type) TYPE(FunctionProto, FunctionType) TYPE(FunctionNoProto, FunctionType) +DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Typedef, Type) NON_CANONICAL_TYPE(TypeOfExpr, Type) NON_CANONICAL_TYPE(TypeOf, Type) diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 98463c308e..c8c49c83f9 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -404,7 +404,9 @@ namespace clang { /// \brief An ElaboratedType record. TYPE_ELABORATED = 24, /// \brief A SubstTemplateTypeParmType record. - TYPE_SUBST_TEMPLATE_TYPE_PARM = 25 + TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, + /// \brief An UnresolvedUsingType record. + TYPE_UNRESOLVED_USING = 26 }; /// \brief The type IDs for special types constructed by semantic diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a63db14a0f..94f2fdcff9 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -260,24 +260,40 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, } NamedDecl * -ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) { +ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos - = InstantiatedFromUnresolvedUsingDecl.find(UUD); - if (Pos == InstantiatedFromUnresolvedUsingDecl.end()) + = InstantiatedFromUsingDecl.find(UUD); + if (Pos == InstantiatedFromUsingDecl.end()) return 0; return Pos->second; } void -ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD, - NamedDecl *UUD) { - assert((isa<UnresolvedUsingValueDecl>(UUD) || - isa<UnresolvedUsingTypenameDecl>(UUD)) && - "original declaration is not an unresolved using decl"); - assert(!InstantiatedFromUnresolvedUsingDecl[UD] && - "Already noted what using decl what instantiated from"); - InstantiatedFromUnresolvedUsingDecl[UD] = UUD; +ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) { + assert((isa<UsingDecl>(Pattern) || + isa<UnresolvedUsingValueDecl>(Pattern) || + isa<UnresolvedUsingTypenameDecl>(Pattern)) && + "pattern decl is not a using decl"); + assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists"); + InstantiatedFromUsingDecl[Inst] = Pattern; +} + +UsingShadowDecl * +ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) { + llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos + = InstantiatedFromUsingShadowDecl.find(Inst); + if (Pos == InstantiatedFromUsingShadowDecl.end()) + return 0; + + return Pos->second; +} + +void +ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, + UsingShadowDecl *Pattern) { + assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists"); + InstantiatedFromUsingShadowDecl[Inst] = Pattern; } FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { @@ -1766,6 +1782,9 @@ QualType ASTContext::getTypeDeclType(TypeDecl *Decl, TypeDecl* PrevDecl) { Decl->TypeForDecl = PrevDecl->TypeForDecl; else Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum); + } else if (UnresolvedUsingTypenameDecl *Using = + dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { + Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using); } else assert(false && "TypeDecl without a type?"); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 50a512028e..3ccb7a9cc6 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -94,3 +94,32 @@ void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) { TypeLocInitializer(Loc).Visit(TL); } while ((TL = TL.getNextTypeLoc())); } + +namespace { + struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> { + // Overload resolution does the real work for us. + static bool isTypeSpec(TypeSpecTypeLoc _) { return true; } + static bool isTypeSpec(TypeLoc _) { return false; } + +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ + return isTypeSpec(TyLoc); \ + } +#include "clang/AST/TypeLocNodes.def" + }; +} + + +/// \brief Determines if the given type loc corresponds to a +/// TypeSpecTypeLoc. Since there is not actually a TypeSpecType in +/// the type hierarchy, this is made somewhat complicated. +/// +/// There are a lot of types that currently use TypeSpecTypeLoc +/// because it's a convenient base class. Ideally we would not accept +/// those here, but ideally we would have better implementations for +/// them. +bool TypeSpecTypeLoc::classof(const TypeLoc *TL) { + if (TL->getType().hasLocalQualifiers()) return false; + return TSTChecker().Visit(*TL); +} diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 3d7a5376d7..2f58ebed4b 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -303,6 +303,15 @@ void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, Print(T->getResultType(), S); } +void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, + std::string &S) { + IdentifierInfo *II = T->getDecl()->getIdentifier(); + if (S.empty()) + S = II->getName().str(); + else + S = II->getName().str() + ' ' + S; +} + void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. S = ' ' + S; diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 4d021e8964..df708eda9c 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -843,6 +843,12 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, // <type> ::= <class-enum-type> // <class-enum-type> ::= <name> +void CXXNameMangler::mangleType(const UnresolvedUsingType *T) { + mangleName(T->getDecl()); +} + +// <type> ::= <class-enum-type> +// <class-enum-type> ::= <name> void CXXNameMangler::mangleType(const EnumType *T) { mangleType(static_cast<const TagType*>(T)); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 40eb9ca536..811f9ed4af 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1880,6 +1880,10 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { Exceptions.data()); } + case pch::TYPE_UNRESOLVED_USING: + return Context->getTypeDeclType( + cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0]))); + case pch::TYPE_TYPEDEF: assert(Record.size() == 1 && "incorrect encoding of typedef type"); return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0]))); @@ -2044,6 +2048,9 @@ void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { VisitFunctionTypeLoc(TL); } +void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { + TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index e79f9c9dac..0e6d1d2f66 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -166,6 +166,14 @@ void PCHTypeWriter::VisitFunctionProtoType(const FunctionProtoType *T) { Code = pch::TYPE_FUNCTION_PROTO; } +#if 0 +// For when we want it.... +void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) { + Writer.AddDeclRef(T->getDecl(), Record); + Code = pch::TYPE_UNRESOLVED_USING; +} +#endif + void PCHTypeWriter::VisitTypedefType(const TypedefType *T) { Writer.AddDeclRef(T->getDecl(), Record); Code = pch::TYPE_TYPEDEF; @@ -337,6 +345,9 @@ void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { VisitFunctionTypeLoc(TL); } +void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { + Writer.AddSourceLocation(TL.getNameLoc(), Record); +} void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 616151efea..9606821f78 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1729,6 +1729,10 @@ public: SourceLocation IdentLoc, IdentifierInfo *Ident); + bool CheckUsingDeclQualifier(SourceLocation UsingLoc, + const CXXScopeSpec &SS, + SourceLocation NameLoc); + NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, const CXXScopeSpec &SS, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 58b5633afa..992bb80189 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -2900,10 +2900,8 @@ Sema::DeclPtrTy Sema::ActOnUsingDeclaration(Scope *S, TargetName, AttrList, /* IsInstantiation */ false, IsTypeName, TypenameLoc); - if (UD) { - PushOnScopeChains(UD, S); - UD->setAccess(AS); - } + if (UD) + PushOnScopeChains(UD, S, /*AddToContext*/ false); return DeclPtrTy::make(UD); } @@ -2962,19 +2960,33 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc)) + return 0; + DeclContext *LookupContext = computeDeclContext(SS); + NamedDecl *D; if (!LookupContext) { if (IsTypeName) { - return UnresolvedUsingTypenameDecl::Create(Context, CurContext, - UsingLoc, TypenameLoc, - SS.getRange(), NNS, - IdentLoc, Name); - } else { - return UnresolvedUsingValueDecl::Create(Context, CurContext, - UsingLoc, SS.getRange(), NNS, + // FIXME: not all declaration name kinds are legal here + D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, + UsingLoc, TypenameLoc, + SS.getRange(), NNS, IdentLoc, Name); + } else { + D = UnresolvedUsingValueDecl::Create(Context, CurContext, + UsingLoc, SS.getRange(), NNS, + IdentLoc, Name); } + } else { + D = UsingDecl::Create(Context, CurContext, IdentLoc, + SS.getRange(), UsingLoc, NNS, Name, + IsTypeName); } + D->setAccess(AS); + CurContext->addDecl(D); + + if (!LookupContext) return D; + UsingDecl *UD = cast<UsingDecl>(D); if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) { // C++0x N2914 [namespace.udecl]p3: @@ -2989,7 +3001,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, Diag(SS.getRange().getBegin(), diag::err_using_decl_nested_name_specifier_is_not_a_base_class) << NNS << RD->getDeclName(); - return 0; + UD->setInvalidDecl(); + return UD; } } else { // C++0x N2914 [namespace.udecl]p8: @@ -2997,7 +3010,8 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (isa<CXXRecordDecl>(LookupContext)) { Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member) << SS.getRange(); - return 0; + UD->setInvalidDecl(); + return UD; } } @@ -3017,54 +3031,63 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, if (R.empty()) { Diag(IdentLoc, diag::err_no_member) << Name << LookupContext << SS.getRange(); - return 0; + UD->setInvalidDecl(); + return UD; } - if (R.isAmbiguous()) - return 0; + if (R.isAmbiguous()) { + UD->setInvalidDecl(); + return UD; + } if (IsTypeName) { // If we asked for a typename and got a non-type decl, error out. - if (R.getResultKind() != LookupResult::Found - || !isa<TypeDecl>(R.getFoundDecl())) { + if (!R.getAsSingle<TypeDecl>()) { Diag(IdentLoc, diag::err_using_typename_non_type); for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) Diag((*I)->getUnderlyingDecl()->getLocation(), diag::note_using_decl_target); - return 0; + UD->setInvalidDecl(); + return UD; } } else { // If we asked for a non-typename and we got a type, error out, // but only if this is an instantiation of an unresolved using // decl. Otherwi |