[cfe-commits] r90614 - in /cfe/trunk: include/clang/AST/ include/clang/Frontend/ lib/AST/ lib/CodeGen/ lib/Frontend/ lib/Sema/ test/CXX/dcl.dcl/basic.namespace/namespace.udecl/ test/SemaCXX/

John McCall rjmccall at apple.com
Fri Dec 4 14:46:56 PST 2009


Author: rjmccall
Date: Fri Dec  4 16:46:56 2009
New Revision: 90614

URL: http://llvm.org/viewvc/llvm-project?rev=90614&view=rev
Log:
Fix "using typename" and the instantiation of non-dependent using declarations.


Added:
    cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/AST/TypeLocBuilder.h
    cfe/trunk/include/clang/AST/TypeNodes.def
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/TypeLoc.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/CodeGen/Mangle.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaCXX/using-decl-templates.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Dec  4 16:46:56 2009
@@ -57,6 +57,7 @@
   class TypeDecl;
   class TypedefDecl;
   class UsingDecl;
+  class UsingShadowDecl;
 
   namespace Builtin { class Context; }
 
@@ -183,8 +184,10 @@
   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 @@
   ///
   /// 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 @@
   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);
-
-  /// \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);
+  NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst);
 
+  /// \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);
 

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Dec  4 16:46:56 2009
@@ -76,6 +76,7 @@
   class ObjCInterfaceDecl;
   class ObjCProtocolDecl;
   class ObjCMethodDecl;
+  class UnresolvedUsingTypenameDecl;
   class Expr;
   class Stmt;
   class SourceLocation;
@@ -1863,6 +1864,38 @@
 };
 
 
+/// \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:

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Fri Dec  4 16:46:56 2009
@@ -340,16 +340,20 @@
   }
 };
 
+
 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 @@
   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 @@
   }
 };
 
-// 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> {
-};
-
-class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc,
-                                                    FixedWidthIntType> {
-};
-
-class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc,
-                                              ComplexType> {
+    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                     DependentSizedExtVectorTypeLoc,
+                                     DependentSizedExtVectorType> {
 };
 
-class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc,
-                                                 TypeOfExprType> {
+// FIXME: I'm not sure how you actually specify these;  with attributes?
+class FixedWidthIntTypeLoc :
+    public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                     FixedWidthIntTypeLoc,
+                                     FixedWidthIntType> {
 };
 
-class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> {
+// FIXME: location of the '_Complex' keyword.
+class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                                        ComplexTypeLoc,
+                                                        ComplexType> {
 };
 
-class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> {
+// FIXME: location of the 'typeof' and parens (the expression is
+// carried by the type).
+class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
+                                                           TypeOfExprTypeLoc,
+                                                           TypeOfExprType> {
 };
 
-class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> {
+// 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 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> {
 };
 
 }

Modified: cfe/trunk/include/clang/AST/TypeLocBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLocBuilder.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TypeLocBuilder.h (original)
+++ cfe/trunk/include/clang/AST/TypeLocBuilder.h Fri Dec  4 16:46:56 2009
@@ -59,9 +59,35 @@
       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 @@
     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 @@
 
     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);

Modified: cfe/trunk/include/clang/AST/TypeNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeNodes.def?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TypeNodes.def (original)
+++ cfe/trunk/include/clang/AST/TypeNodes.def Fri Dec  4 16:46:56 2009
@@ -71,6 +71,7 @@
 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)

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Fri Dec  4 16:46:56 2009
@@ -404,7 +404,9 @@
       /// \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

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Dec  4 16:46:56 2009
@@ -260,24 +260,40 @@
 }
 
 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 @@
       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?");
 

Modified: cfe/trunk/lib/AST/TypeLoc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TypeLoc.cpp (original)
+++ cfe/trunk/lib/AST/TypeLoc.cpp Fri Dec  4 16:46:56 2009
@@ -94,3 +94,32 @@
     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);
+}

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Fri Dec  4 16:46:56 2009
@@ -303,6 +303,15 @@
   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;

Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Fri Dec  4 16:46:56 2009
@@ -843,6 +843,12 @@
 
 // <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));
 }

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Dec  4 16:46:56 2009
@@ -1880,6 +1880,10 @@
                                     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::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++]));
 }

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Dec  4 16:46:56 2009
@@ -166,6 +166,14 @@
   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::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);
 }

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Dec  4 16:46:56 2009
@@ -1729,6 +1729,10 @@
                                            SourceLocation IdentLoc,
                                            IdentifierInfo *Ident);
 
+  bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                               const CXXScopeSpec &SS,
+                               SourceLocation NameLoc);
+
   NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
                                    SourceLocation UsingLoc,
                                    const CXXScopeSpec &SS,

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Fri Dec  4 16:46:56 2009
@@ -2900,10 +2900,8 @@
                                         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 @@
   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 @@
       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 @@
     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 @@
   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.  Otherwise just silently find the type name.
-    if (IsInstantiation &&
-        R.getResultKind() == LookupResult::Found &&
-        isa<TypeDecl>(R.getFoundDecl())) {
+    if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
       Diag(IdentLoc, diag::err_using_dependent_value_is_type);
       Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
-      return 0;
+      UD->setInvalidDecl();
+      return UD;
     }
   }
 
   // C++0x N2914 [namespace.udecl]p6:
   // A using-declaration shall not name a namespace.
-  if (R.getResultKind() == LookupResult::Found
-      && isa<NamespaceDecl>(R.getFoundDecl())) {
+  if (R.getAsSingle<NamespaceDecl>()) {
     Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
       << SS.getRange();
-    return 0;
+    UD->setInvalidDecl();
+    return UD;
   }
 
-  UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc,
-                                    SS.getRange(), UsingLoc, NNS, Name,
-                                    IsTypeName);
-
   for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
     BuildUsingShadowDecl(*this, S, AS, UD, *I);
 
   return UD;
 }
 
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope.  If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc) {
+  // FIXME: implement
+
+  return false;
+}
+
 Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
                                              SourceLocation NamespaceLoc,
                                              SourceLocation AliasLoc,

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Dec  4 16:46:56 2009
@@ -2361,6 +2361,7 @@
   case Type::Enum:
   case Type::ObjCInterface:
   case Type::ObjCObjectPointer:
+  case Type::UnresolvedUsing:
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
 #define DEPENDENT_TYPE(Class, Base)

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Dec  4 16:46:56 2009
@@ -1064,8 +1064,6 @@
         Invalid = true;
       } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
         Fields.push_back(DeclPtrTy::make(Field));
-      else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember))
-        Instantiation->addDecl(UD);
     } else {
       // FIXME: Eventually, a NULL return will mean that one of the
       // instantiations was a semantic disaster, and we'll want to set Invalid =

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Dec  4 16:46:56 2009
@@ -66,6 +66,8 @@
     Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
     Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+    Decl *VisitUsingDecl(UsingDecl *D);
+    Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
     Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
     Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
 
@@ -1034,6 +1036,56 @@
   return Inst;
 }
 
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+  // The nested name specifier is non-dependent, so no transformation
+  // is required.
+
+  UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+                                       D->getLocation(),
+                                       D->getNestedNameRange(),
+                                       D->getUsingLocation(),
+                                       D->getTargetNestedNameDecl(),
+                                       D->getDeclName(),
+                                       D->isTypeName());
+
+  CXXScopeSpec SS;
+  SS.setScopeRep(D->getTargetNestedNameDecl());
+  SS.setRange(D->getNestedNameRange());
+  if (SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+                                      D->getLocation()))
+    NewUD->setInvalidDecl();
+  SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+  NewUD->setAccess(D->getAccess());
+  Owner->addDecl(NewUD);
+
+  // We'll transform the UsingShadowDecls as we reach them.
+
+  return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+  UsingDecl *InstUsing =
+    cast<UsingDecl>(SemaRef.FindInstantiatedDecl(D->getUsingDecl(),
+                                                 TemplateArgs));
+  NamedDecl *InstTarget =
+    cast<NamedDecl>(SemaRef.FindInstantiatedDecl(D->getTargetDecl(),
+                                                 TemplateArgs));
+
+  UsingShadowDecl *InstD = UsingShadowDecl::Create(SemaRef.Context, Owner,
+                                                   InstUsing->getLocation(),
+                                                   InstUsing, InstTarget);
+  InstUsing->addShadowDecl(InstD);
+
+  if (InstTarget->isInvalidDecl() || InstUsing->isInvalidDecl())
+    InstD->setInvalidDecl();
+
+  SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstD, D);
+  InstD->setAccess(D->getAccess());
+  Owner->addDecl(InstD);
+
+  return InstD;
+}
+
 Decl * TemplateDeclInstantiator
     ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
   NestedNameSpecifier *NNS =
@@ -1054,8 +1106,8 @@
                                   /*instantiation*/ true,
                                   /*typename*/ true, D->getTypenameLoc());
   if (UD)
-    SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
-                                                           D);
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
   return UD;
 }
 
@@ -1079,8 +1131,8 @@
                                   /*instantiation*/ true,
                                   /*typename*/ false, SourceLocation());
   if (UD)
-    SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
-                                                           D);
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
   return UD;
 }
 
@@ -1753,16 +1805,28 @@
   return false;
 }
 
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+                              UsingShadowDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
 static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
                               UsingDecl *Instance,
                               ASTContext &C) {
-  return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
 }
 
 static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
                               UsingDecl *Instance,
                               ASTContext &C) {
-  return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
 }
 
 static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
@@ -1780,6 +1844,8 @@
   return false;
 }
 
+// Other is the prospective instantiation
+// D is the prospective pattern
 static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
   if (D->getKind() != Other->getKind()) {
     if (UnresolvedUsingTypenameDecl *UUD
@@ -1831,6 +1897,12 @@
     }
   }
 
+  if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+    return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+  if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+    return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
   return D->getDeclName() && isa<NamedDecl>(Other) &&
     D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
 }

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Dec  4 16:46:56 2009
@@ -461,6 +461,10 @@
   /// \brief Build a new unprototyped function type.
   QualType RebuildFunctionNoProtoType(QualType ResultType);
 
+  /// \brief Rebuild an unresolved typename type, given the decl that
+  /// the UnresolvedUsingTypenameDecl was transformed to.
+  QualType RebuildUnresolvedUsingType(Decl *D);
+
   /// \brief Build a new typedef type.
   QualType RebuildTypedefType(TypedefDecl *Typedef) {
     return SemaRef.Context.getTypeDeclType(Typedef);
@@ -2578,6 +2582,29 @@
   return Result;
 }
 
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+                                                 UnresolvedUsingTypeLoc TL) {
+  UnresolvedUsingType *T = TL.getTypePtr();
+  Decl *D = getDerived().TransformDecl(T->getDecl());
+  if (!D)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+    Result = getDerived().RebuildUnresolvedUsingType(D);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // We might get an arbitrary type spec type back.  We should at
+  // least always get a type spec type, though.
+  TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
                                                       TypedefTypeLoc TL) {
@@ -5318,6 +5345,30 @@
 }
 
 template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+  assert(D && "no decl found");
+  if (D->isInvalidDecl()) return QualType();
+
+  TypeDecl *Ty;
+  if (isa<UsingDecl>(D)) {
+    UsingDecl *Using = cast<UsingDecl>(D);
+    assert(Using->isTypeName() &&
+           "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+    // A valid resolved using typename decl points to exactly one type decl.
+    assert(++Using->shadow_begin() == Using->shadow_end());
+    Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+    
+  } else {
+    assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+           "UnresolvedUsingTypenameDecl transformed to non-using decl");
+    Ty = cast<UnresolvedUsingTypenameDecl>(D);
+  }
+
+  return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
 QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
   return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
 }

Added: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp?rev=90614&view=auto

==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p4.cpp Fri Dec  4 16:46:56 2009
@@ -0,0 +1,183 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+// C++03 [namespace.udecl]p4:
+//   A using-declaration used as a member-declaration shall refer to a
+//   member of a base class of the class being defined, shall refer to
+//   a member of an anonymous union that is a member of a base class
+//   of the class being defined, or shall refer to an enumerator for
+//   an enumeration type that is a member of a base class of the class
+//   being defined.
+
+// There is no directly analogous paragraph in C++0x, and the feature
+// works sufficiently differently there that it needs a separate test.
+
+namespace test0 {
+  namespace NonClass {
+    typedef int type;
+    struct hiding {};
+    int hiding;
+    static union { double union_member; };
+    enum tagname { enumerator };
+  }
+
+  class Test0 {
+    using NonClass::type; // expected-error {{not a base class}}
+    using NonClass::hiding; // expected-error {{not a base class}}
+    using NonClass::union_member; // expected-error {{not a base class}}
+    using NonClass::enumerator; // expected-error {{not a base class}}
+  };
+}
+
+struct Opaque0 {};
+
+namespace test1 {
+  struct A {
+    typedef int type;
+    struct hiding {}; // expected-note {{previous use is here}}
+    Opaque0 hiding;
+    union { double union_member; };
+    enum tagname { enumerator };
+  };
+
+  struct B : A {
+    using A::type;
+    using A::hiding;
+    using A::union_member;
+    using A::enumerator;
+    using A::tagname;
+
+    void test0() {
+      type t = 0;
+    }
+
+    void test1() {
+      typedef struct A::hiding local;
+      struct hiding _ = local();
+    }
+
+    void test2() {
+      union hiding _; // expected-error {{tag type that does not match previous}}
+    }
+
+    void test3() {
+      char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+    }
+
+    void test4() {
+      enum tagname _ = enumerator;
+    }
+
+    void test5() {
+      Opaque0 _ = hiding;
+    }
+  };
+}
+
+namespace test2 {
+  struct A {
+    typedef int type;
+    struct hiding {}; // expected-note {{previous use is here}}
+    int hiding;
+    union { double union_member; };
+    enum tagname { enumerator };
+  };
+
+  template <class T> struct B : A {
+    using A::type;
+    using A::hiding;
+    using A::union_member;
+    using A::enumerator;
+    using A::tagname;
+
+    void test0() {
+      type t = 0;
+    }
+
+    void test1() {
+      typedef struct A::hiding local;
+      struct hiding _ = local();
+    }
+
+    void test2() {
+      union hiding _; // expected-error {{tag type that does not match previous}}
+    }
+
+    void test3() {
+      char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+    }
+
+    void test4() {
+      enum tagname _ = enumerator;
+    }
+
+    void test5() {
+      Opaque0 _ = hiding;
+    }
+  };
+}
+
+namespace test3 {
+  struct hiding {};
+
+  template <class T> struct A {
+    typedef int type; // expected-note {{target of using declaration}}
+    struct hiding {};
+    Opaque0 hiding; // expected-note {{target of using declaration}}
+    union { double union_member; }; // expected-note {{target of using declaration}}
+    enum tagname { enumerator }; // expected-note 2 {{target of using declaration}}
+  };
+
+  template <class T> struct B : A<T> {
+    using A<T>::type; // expected-error {{dependent using declaration resolved to type without 'typename'}}
+    using A<T>::hiding;
+    using A<T>::union_member;
+    using A<T>::enumerator;
+    using A<T>::tagname; // expected-error {{dependent using declaration resolved to type without 'typename'}}
+
+    // FIXME: re-enable these when the various bugs involving tags are fixed
+#if 0
+    void test1() {
+      typedef struct A<T>::hiding local;
+      struct hiding _ = local();
+    }
+
+    void test2() {
+      typedef struct A<T>::hiding local;
+      union hiding _ = local();
+    }
+#endif
+
+    void test3() {
+      char array[sizeof(union_member) == sizeof(double) ? 1 : -1];
+    }
+
+#if 0
+    void test4() {
+      enum tagname _ = enumerator;
+    }
+#endif
+
+    void test5() {
+      Opaque0 _ = hiding;
+    }
+  };
+
+  template struct B<int>; // expected-note {{in instantiation}}
+
+  template <class T> struct C : A<T> {
+    using typename A<T>::type;
+    using typename A<T>::hiding; // expected-error {{'typename' keyword used on a non-type}}
+    using typename A<T>::union_member; // expected-error {{'typename' keyword used on a non-type}}
+    using typename A<T>::enumerator; // expected-error {{'typename' keyword used on a non-type}}
+
+    void test6() {
+      type t = 0;
+    }
+
+    void test7() {
+      Opaque0 _ = hiding; // expected-error {{expected '(' for function-style cast or type construction}}
+    }
+  };
+
+  template struct C<int>; // expected-note {{in instantiation}}
+}

Modified: cfe/trunk/test/SemaCXX/using-decl-templates.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-decl-templates.cpp?rev=90614&r1=90613&r2=90614&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/using-decl-templates.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-decl-templates.cpp Fri Dec  4 16:46:56 2009
@@ -34,3 +34,14 @@
 
   void g() { f(); }
 };
+
+namespace test0 {
+  struct Base {
+    int foo;
+  };
+  template<typename T> struct E : Base {
+    using Base::foo;
+  };
+
+  template struct E<int>;
+}





More information about the cfe-commits mailing list