[cfe-commits] r89184 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Parse/ lib/Sema/ test/CXX/dcl.dcl/basic.namespace/namespace.udecl/ test/SemaCXX/

John McCall rjmccall at apple.com
Tue Nov 17 18:36:19 PST 2009


Author: rjmccall
Date: Tue Nov 17 20:36:19 2009
New Revision: 89184

URL: http://llvm.org/viewvc/llvm-project?rev=89184&view=rev
Log:
Incremental progress on using declarations.  Split UnresolvedUsingDecl into
two classes, one for typenames and one for values;  this seems to have some
support from Doug if not necessarily from the extremely-vague-on-this-point
standard.  Track the location of the 'typename' keyword in a using-typename
decl.  Make a new lookup result for unresolved values and deal with it in
most places.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/DeclNodes.def
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/DeclPrinter.cpp
    cfe/trunk/lib/Parse/MinimalAction.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
    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=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Nov 17 20:36:19 2009
@@ -56,7 +56,6 @@
   class TranslationUnitDecl;
   class TypeDecl;
   class TypedefDecl;
-  class UnresolvedUsingDecl;
   class UsingDecl;
 
   namespace Builtin { class Context; }
@@ -205,7 +204,7 @@
   ///
   /// This mapping will contain an entry that maps from the UsingDecl in
   /// B<int> to the UnresolvedUsingDecl in B<T>.
-  llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>
+  llvm::DenseMap<UsingDecl *, NamedDecl *>
     InstantiatedFromUnresolvedUsingDecl;
 
   llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl;
@@ -285,12 +284,11 @@
 
   /// \brief If this using decl is instantiated from an unresolved using decl,
   /// return it.
-  UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD);
+  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,
-                                              UnresolvedUsingDecl *Tmpl);
+  void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl);
 
 
   FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field);

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Tue Nov 17 20:36:19 2009
@@ -1766,31 +1766,88 @@
   static bool classof(const UsingDecl *D) { return true; }
 };
 
-/// UnresolvedUsingDecl - Represents a using declaration whose name can not
-/// yet be resolved.
-class UnresolvedUsingDecl : public NamedDecl {
+/// UnresolvedUsingValueDecl - Represents a dependent using
+/// declaration which was not marked with 'typename'.  Unlike
+/// non-dependent using declarations, these *only* bring through
+/// non-types; otherwise they would break two-phase lookup.
+///
+/// template <class T> class A : public Base<T> {
+///   using Base<T>::foo;
+/// };
+class UnresolvedUsingValueDecl : public ValueDecl {
   /// \brief The source range that covers the nested-name-specifier
   /// preceding the declaration name.
   SourceRange TargetNestedNameRange;
 
-  /// \brief The source location of the target declaration name.
-  SourceLocation TargetNameLocation;
+  /// \brief The source location of the 'using' keyword
+  SourceLocation UsingLocation;
 
   NestedNameSpecifier *TargetNestedNameSpecifier;
 
-  DeclarationName TargetName;
+  UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty,
+                           SourceLocation UsingLoc, SourceRange TargetNNR,
+                           NestedNameSpecifier *TargetNNS,
+                           SourceLocation TargetNameLoc,
+                           DeclarationName TargetName)
+    : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty),
+    TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+    TargetNestedNameSpecifier(TargetNNS)
+  { }
 
-  // \brief Has 'typename' keyword.
-  bool IsTypeName;
+public:
+  /// \brief Returns the source range that covers the nested-name-specifier
+  /// preceding the namespace name.
+  SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; }
+
+  /// \brief Get target nested name declaration.
+  NestedNameSpecifier* getTargetNestedNameSpecifier() {
+    return TargetNestedNameSpecifier;
+  }
+
+  /// \brief Returns the source location of the 'using' keyword.
+  SourceLocation getUsingLoc() const { return UsingLocation; }
+
+  static UnresolvedUsingValueDecl *
+    Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+           SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+           SourceLocation TargetNameLoc, DeclarationName TargetName);
+
+  static bool classof(const Decl *D) {
+    return D->getKind() == Decl::UnresolvedUsingValue;
+  }
+  static bool classof(const UnresolvedUsingValueDecl *D) { return true; }
+};
+
+/// UnresolvedUsingTypenameDecl - Represents a dependent using
+/// declaration which was marked with 'typename'.
+///
+/// template <class T> class A : public Base<T> {
+///   using typename Base<T>::foo;
+/// };
+///
+/// The type associated with a unresolved using typename decl is
+/// currently always a typename type.
+class UnresolvedUsingTypenameDecl : public TypeDecl {
+  /// \brief The source range that covers the nested-name-specifier
+  /// preceding the declaration name.
+  SourceRange TargetNestedNameRange;
+
+  /// \brief The source location of the 'using' keyword
+  SourceLocation UsingLocation;
+
+  /// \brief The source location of the 'typename' keyword
+  SourceLocation TypenameLocation;
 
-  UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc,
-                      SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
-                      SourceLocation TargetNameLoc, DeclarationName TargetName,
-                      bool IsTypeNameArg)
-  : NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName),
-    TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc),
-    TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName),
-    IsTypeName(IsTypeNameArg) { }
+  NestedNameSpecifier *TargetNestedNameSpecifier;
+
+  UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc,
+                    SourceLocation TypenameLoc,
+                    SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+                    SourceLocation TargetNameLoc, IdentifierInfo *TargetName)
+  : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName),
+    TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc),
+    TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS)
+  { }
 
 public:
   /// \brief Returns the source range that covers the nested-name-specifier
@@ -1802,26 +1859,22 @@
     return TargetNestedNameSpecifier;
   }
 
-  /// \brief Returns the source location of the target declaration name.
-  SourceLocation getTargetNameLocation() const { return TargetNameLocation; }
-
-  /// \brief Returns the source location of the target declaration name.
-  DeclarationName getTargetName() const { return TargetName; }
+  /// \brief Returns the source location of the 'using' keyword.
+  SourceLocation getUsingLoc() const { return UsingLocation; }
 
-  bool isTypeName() const { return IsTypeName; }
+  /// \brief Returns the source location of the 'typename' keyword.
+  SourceLocation getTypenameLoc() const { return TypenameLocation; }
 
-  static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC,
-                                     SourceLocation UsingLoc,
-                                     SourceRange TargetNNR,
-                                     NestedNameSpecifier *TargetNNS,
-                                     SourceLocation TargetNameLoc,
-                                     DeclarationName TargetName,
-                                     bool IsTypeNameArg);
+  static UnresolvedUsingTypenameDecl *
+    Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc,
+           SourceLocation TypenameLoc,
+           SourceRange TargetNNR, NestedNameSpecifier *TargetNNS,
+           SourceLocation TargetNameLoc, DeclarationName TargetName);
 
   static bool classof(const Decl *D) {
-    return D->getKind() == Decl::UnresolvedUsing;
+    return D->getKind() == Decl::UnresolvedUsingTypename;
   }
-  static bool classof(const UnresolvedUsingDecl *D) { return true; }
+  static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; }
 };
 
 /// StaticAssertDecl - Represents a C++0x static_assert declaration.

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclNodes.def (original)
+++ cfe/trunk/include/clang/AST/DeclNodes.def Tue Nov 17 20:36:19 2009
@@ -81,6 +81,7 @@
   DECL(NamespaceAlias, NamedDecl)
   ABSTRACT_DECL(Type, NamedDecl)
     DECL(Typedef, TypeDecl)
+    DECL(UnresolvedUsingTypename, TypeDecl)
     ABSTRACT_DECL(Tag, TypeDecl)
       DECL(Enum, TagDecl)
       DECL(Record, TagDecl)
@@ -91,6 +92,7 @@
     DECL(TemplateTypeParm, TypeDecl)
   ABSTRACT_DECL(Value, NamedDecl)
     DECL(EnumConstant, ValueDecl)
+    DECL(UnresolvedUsingValue, ValueDecl)
     ABSTRACT_DECL(Declarator, ValueDecl)
       DECL(Function, DeclaratorDecl)
         DECL(CXXMethod, FunctionDecl)
@@ -109,7 +111,6 @@
     DECL(ClassTemplate, TemplateDecl)
     DECL(TemplateTemplateParm, TemplateDecl)
   DECL(Using, NamedDecl)
-  DECL(UnresolvedUsing, NamedDecl)
   DECL(UsingShadow, NamedDecl)
   DECL(ObjCMethod, NamedDecl)
   DECL(ObjCContainer, NamedDecl)

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Nov 17 20:36:19 2009
@@ -103,6 +103,8 @@
   "using declaration requires a qualified name">;
 def err_using_typename_non_type : Error<
   "'typename' keyword used on a non-type">;
+def err_using_dependent_value_is_type : Error<
+  "dependent using declaration resolved to type without 'typename'">;
 def err_using_decl_nested_name_specifier_is_not_a_base_class : Error<
   "using declaration refers into '%0', which is not a base class of %1">;
 def err_using_decl_can_not_refer_to_class_member : Error<
@@ -115,6 +117,8 @@
   "using declaration can not refer to a destructor">;
 def err_using_decl_template_id : Error<
   "using declaration can not refer to a template specialization">;
+def note_using_decl_target : Note<
+  "target of using declaration">;
 
 def err_invalid_thread : Error<
   "'__thread' is only allowed on variable declarations">;

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Nov 17 20:36:19 2009
@@ -1203,6 +1203,8 @@
   /// 'typename' keyword. FIXME: This will eventually be split into a 
   /// separate action.
   ///
+  /// \param TypenameLoc the location of the 'typename' keyword, if present
+  ///
   /// \returns a representation of the using declaration.
   virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
                                           AccessSpecifier AS,
@@ -1210,7 +1212,8 @@
                                           const CXXScopeSpec &SS,
                                           UnqualifiedId &Name,
                                           AttributeList *AttrList,
-                                          bool IsTypeName);
+                                          bool IsTypeName,
+                                          SourceLocation TypenameLoc);
 
   /// ActOnParamDefaultArgument - Parse default argument for function parameter
   virtual void ActOnParamDefaultArgument(DeclPtrTy param,

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

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 17 20:36:19 2009
@@ -256,9 +256,9 @@
     = new (*this) MemberSpecializationInfo(Tmpl, TSK);
 }
 
-UnresolvedUsingDecl *
+NamedDecl *
 ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
-  llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *>::const_iterator Pos
+  llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
     = InstantiatedFromUnresolvedUsingDecl.find(UUD);
   if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
     return 0;
@@ -268,7 +268,10 @@
 
 void
 ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
-                                                   UnresolvedUsingDecl *UUD) {
+                                                   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;

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

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Nov 17 20:36:19 2009
@@ -212,8 +212,9 @@
     case UsingShadow:
       return 0; // we'll actually overwrite this later
 
-    case UnresolvedUsing:
-      return IDNS_Tag | IDNS_Ordinary | IDNS_Using;
+    case UnresolvedUsingValue:
+    case UnresolvedUsingTypename:
+      return IDNS_Ordinary | IDNS_Using;
 
     case Using:
       return IDNS_Using;

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

==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Nov 17 20:36:19 2009
@@ -920,15 +920,30 @@
   return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg);
 }
 
-UnresolvedUsingDecl *UnresolvedUsingDecl::Create(ASTContext &C, DeclContext *DC,
-                                                 SourceLocation UsingLoc,
-                                                 SourceRange TargetNNR,
-                                                 NestedNameSpecifier *TargetNNS,
-                                                 SourceLocation TargetNameLoc,
-                                                 DeclarationName TargetName,
-                                                 bool IsTypeNameArg) {
-  return new (C) UnresolvedUsingDecl(DC, UsingLoc, TargetNNR, TargetNNS,
-                                     TargetNameLoc, TargetName, IsTypeNameArg);
+UnresolvedUsingValueDecl *
+UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC,
+                                 SourceLocation UsingLoc,
+                                 SourceRange TargetNNR,
+                                 NestedNameSpecifier *TargetNNS,
+                                 SourceLocation TargetNameLoc,
+                                 DeclarationName TargetName) {
+  return new (C) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc,
+                                          TargetNNR, TargetNNS,
+                                          TargetNameLoc, TargetName);
+}
+
+UnresolvedUsingTypenameDecl *
+UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC,
+                                    SourceLocation UsingLoc,
+                                    SourceLocation TypenameLoc,
+                                    SourceRange TargetNNR,
+                                    NestedNameSpecifier *TargetNNS,
+                                    SourceLocation TargetNameLoc,
+                                    DeclarationName TargetName) {
+  return new (C) UnresolvedUsingTypenameDecl(DC, UsingLoc, TypenameLoc,
+                                             TargetNNR, TargetNNS,
+                                             TargetNameLoc,
+                                             TargetName.getAsIdentifierInfo());
 }
 
 StaticAssertDecl *StaticAssertDecl::Create(ASTContext &C, DeclContext *DC,

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

==============================================================================
--- cfe/trunk/lib/AST/DeclPrinter.cpp (original)
+++ cfe/trunk/lib/AST/DeclPrinter.cpp Tue Nov 17 20:36:19 2009
@@ -71,7 +71,8 @@
     void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D);
     void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
-    void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
+    void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
+    void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
     void VisitUsingDecl(UsingDecl *D);
     void VisitUsingShadowDecl(UsingShadowDecl *D);
   };
@@ -829,10 +830,17 @@
   Out << D->getNameAsString();
 }
 
-void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
+void
+DeclPrinter::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+  Out << "using typename ";
+  D->getTargetNestedNameSpecifier()->print(Out, Policy);
+  Out << D->getDeclName().getAsString();
+}
+
+void DeclPrinter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
   Out << "using ";
   D->getTargetNestedNameSpecifier()->print(Out, Policy);
-  Out << D->getTargetName().getAsString();
+  Out << D->getDeclName().getAsString();
 }
 
 void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {

Modified: cfe/trunk/lib/Parse/MinimalAction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/MinimalAction.cpp?rev=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/lib/Parse/MinimalAction.cpp Tue Nov 17 20:36:19 2009
@@ -49,7 +49,8 @@
                                                 const CXXScopeSpec &SS,
                                                 UnqualifiedId &Name,
                                                 AttributeList *AttrList,
-                                                bool IsTypeName) {
+                                                bool IsTypeName,
+                                                SourceLocation TypenameLoc) {
 
   // FIXME: Parser seems to assume that Action::ActOn* takes ownership over
   // passed AttributeList, however other actions don't free it, is it

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Tue Nov 17 20:36:19 2009
@@ -283,11 +283,13 @@
                                                 SourceLocation &DeclEnd,
                                                 AccessSpecifier AS) {
   CXXScopeSpec SS;
+  SourceLocation TypenameLoc;
   bool IsTypeName;
 
   // Ignore optional 'typename'.
   // FIXME: This is wrong; we should parse this as a typename-specifier.
   if (Tok.is(tok::kw_typename)) {
+    TypenameLoc = Tok.getLocation();
     ConsumeToken();
     IsTypeName = true;
   }
@@ -330,7 +332,7 @@
                    tok::semi);
 
   return Actions.ActOnUsingDeclaration(CurScope, AS, UsingLoc, SS, Name,
-                                       AttrList, IsTypeName);
+                                       AttrList, IsTypeName, TypenameLoc);
 }
 
 /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Nov 17 20:36:19 2009
@@ -1110,6 +1110,11 @@
       /// functions into an OverloadedFunctionDecl.
       FoundOverloaded,
 
+      /// @brief Name lookup found an unresolvable value declaration
+      /// and cannot yet complete.  This only happens in C++ dependent
+      /// contexts with dependent using declarations.
+      FoundUnresolvedValue,
+
       /// @brief Name lookup results in an ambiguity; use
       /// getAmbiguityKind to figure out what kind of ambiguity
       /// we have.
@@ -1417,6 +1422,7 @@
       assert(ResultKind != NotFound || Decls.size() == 0);
       assert(ResultKind != Found || Decls.size() == 1);
       assert(ResultKind == NotFound || ResultKind == Found ||
+             ResultKind == FoundUnresolvedValue ||
              (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
              || Decls.size() > 1);
       assert((Paths != NULL) == (ResultKind == Ambiguous &&
@@ -2017,7 +2023,9 @@
                                    SourceLocation IdentLoc,
                                    DeclarationName Name,
                                    AttributeList *AttrList,
-                                   bool IsTypeName);
+                                   bool IsInstantiation,
+                                   bool IsTypeName,
+                                   SourceLocation TypenameLoc);
 
   virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
                                           AccessSpecifier AS,
@@ -2025,7 +2033,8 @@
                                           const CXXScopeSpec &SS,
                                           UnqualifiedId &Name,
                                           AttributeList *AttrList,
-                                          bool IsTypeName);
+                                          bool IsTypeName,
+                                          SourceLocation TypenameLoc);
 
   /// AddCXXDirectInitializerToDecl - This action is called immediately after
   /// ActOnDeclarator, when a C++ direct initializer is present.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Nov 17 20:36:19 2009
@@ -94,6 +94,7 @@
   switch (Result.getResultKind()) {
   case LookupResult::NotFound:
   case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
     return 0;
 
   case LookupResult::Ambiguous:
@@ -166,6 +167,10 @@
     
   } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
     T = Context.getObjCInterfaceType(IDecl);
+  } else if (UnresolvedUsingTypenameDecl *UUDecl =
+               dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) {
+    // FIXME: preserve source structure information.
+    T = Context.getTypenameType(UUDecl->getTargetNestedNameSpecifier(), &II);
   } else {
     // If it's not plausibly a type, suppress diagnostics.
     Result.suppressDiagnostics();
@@ -2446,7 +2451,9 @@
 }
 
 static bool isUsingDecl(Decl *D) {
-  return isa<UsingDecl>(D) || isa<UnresolvedUsingDecl>(D);
+  return isa<UsingDecl>(D) ||
+         isa<UnresolvedUsingTypenameDecl>(D) ||
+         isa<UnresolvedUsingValueDecl>(D);
 }
 
 /// \brief Data used with FindOverriddenMethod

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Nov 17 20:36:19 2009
@@ -2809,7 +2809,8 @@
                                             const CXXScopeSpec &SS,
                                             UnqualifiedId &Name,
                                             AttributeList *AttrList,
-                                            bool IsTypeName) {
+                                            bool IsTypeName,
+                                            SourceLocation TypenameLoc) {
   assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
 
   switch (Name.getKind()) {
@@ -2837,7 +2838,9 @@
   DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
   NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
                                         Name.getSourceRange().getBegin(),
-                                        TargetName, AttrList, IsTypeName);
+                                        TargetName, AttrList,
+                                        /* IsInstantiation */ false,
+                                        IsTypeName, TypenameLoc);
   if (UD) {
     PushOnScopeChains(UD, S);
     UD->setAccess(AS);
@@ -2872,13 +2875,20 @@
   return Shadow;
 }
 
+/// Builds a using declaration.
+///
+/// \param IsInstantiation - Whether this call arises from an
+///   instantiation of an unresolved using declaration.  We treat
+///   the lookup differently for these declarations.
 NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
                                        SourceLocation UsingLoc,
                                        const CXXScopeSpec &SS,
                                        SourceLocation IdentLoc,
                                        DeclarationName Name,
                                        AttributeList *AttrList,
-                                       bool IsTypeName) {
+                                       bool IsInstantiation,
+                                       bool IsTypeName,
+                                       SourceLocation TypenameLoc) {
   assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
   assert(IdentLoc.isValid() && "Invalid TargetName location.");
 
@@ -2895,9 +2905,16 @@
 
   DeclContext *LookupContext = computeDeclContext(SS);
   if (!LookupContext) {
-    return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc,
-                                       SS.getRange(), NNS,
-                                       IdentLoc, Name, IsTypeName);
+    if (IsTypeName) {
+      return UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+                                                 UsingLoc, TypenameLoc,
+                                                 SS.getRange(), NNS,
+                                                 IdentLoc, Name);
+    } else {
+      return UnresolvedUsingValueDecl::Create(Context, CurContext,
+                                              UsingLoc, SS.getRange(), NNS,
+                                              IdentLoc, Name);
+    }
   }
 
   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
@@ -2929,7 +2946,12 @@
   // hide tag declarations: tag names are visible through the using
   // declaration even if hidden by ordinary names.
   LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName);
-  R.setHideTags(false);
+
+  // We don't hide tags behind ordinary decls if we're in a
+  // non-dependent context, but in a dependent context, this is
+  // important for the stability of two-phase lookup.
+  if (!IsInstantiation)
+    R.setHideTags(false);
 
   LookupQualifiedName(R, LookupContext);
 
@@ -2942,11 +2964,27 @@
   if (R.isAmbiguous())
     return 0;
 
-  if (IsTypeName &&
-      (R.getResultKind() != LookupResult::Found
-       || !isa<TypeDecl>(R.getFoundDecl()))) {
-    Diag(IdentLoc, diag::err_using_typename_non_type);
-    return 0;
+  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())) {
+      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;
+    }
+  } 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())) {
+      Diag(IdentLoc, diag::err_using_dependent_value_is_type);
+      Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
+      return 0;
+    }
   }
 
   // C++0x N2914 [namespace.udecl]p6:

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Nov 17 20:36:19 2009
@@ -977,7 +977,7 @@
   else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
     return BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
                             false, false, SS);
-  else if (UnresolvedUsingDecl *UD = dyn_cast<UnresolvedUsingDecl>(D))
+  else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D))
     return BuildDeclRefExpr(UD, Context.DependentTy, Loc,
                             /*TypeDependent=*/true,
                             /*ValueDependent=*/true, SS);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Nov 17 20:36:19 2009
@@ -245,7 +245,12 @@
   unsigned N = Decls.size();
 
   // Fast case: no possible ambiguity.
-  if (N <= 1) return;
+  if (N == 0) return;
+  if (N == 1) {
+    if (isa<UnresolvedUsingValueDecl>(Decls[0]))
+      ResultKind = FoundUnresolvedValue;
+    return;
+  }
 
   // Don't do any extra resolution if we've already resolved as ambiguous.
   if (ResultKind == Ambiguous) return;
@@ -254,6 +259,7 @@
 
   bool Ambiguous = false;
   bool HasTag = false, HasFunction = false, HasNonFunction = false;
+  bool HasUnresolved = false;
 
   unsigned UniqueTagIndex = 0;
   
@@ -266,12 +272,15 @@
       // If it's not unique, pull something off the back (and
       // continue at this index).
       Decls[I] = Decls[--N];
-    } else if (isa<UnresolvedUsingDecl>(D)) {
-      // FIXME: support unresolved using decls
+    } else if (isa<UnresolvedUsingValueDecl>(D)) {
+      // FIXME: support unresolved using value declarations
       Decls[I] = Decls[--N];
     } else {
       // Otherwise, do some decl type analysis and then continue.
-      if (isa<TagDecl>(D)) {
+
+      if (isa<UnresolvedUsingValueDecl>(D)) {
+        HasUnresolved = true;
+      } else if (isa<TagDecl>(D)) {
         if (HasTag)
           Ambiguous = true;
         UniqueTagIndex = I;
@@ -296,7 +305,8 @@
   //   wherever the object, function, or enumerator name is visible.
   // But it's still an error if there are distinct tag types found,
   // even if they're not visible. (ref?)
-  if (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction))
+  if (HideTags && HasTag && !Ambiguous && !HasUnresolved &&
+      (HasFunction || HasNonFunction))
     Decls[UniqueTagIndex] = Decls[--N];
 
   Decls.set_size(N);
@@ -306,6 +316,8 @@
 
   if (Ambiguous)
     setAmbiguous(LookupResult::AmbiguousReference);
+  else if (HasUnresolved)
+    ResultKind = LookupResult::FoundUnresolvedValue;
   else if (N > 1)
     ResultKind = LookupResult::FoundOverloaded;
   else

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov 17 20:36:19 2009
@@ -4501,6 +4501,10 @@
     Referenced = Result.getFoundDecl();
     break;
 
+  case LookupResult::FoundUnresolvedValue:
+    llvm::llvm_unreachable("unresolved using decl in non-dependent context");
+    return QualType();
+
   case LookupResult::FoundOverloaded:
     DiagID = diag::err_typename_nested_not_type;
     Referenced = *Result.begin();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Nov 17 20:36:19 2009
@@ -66,7 +66,8 @@
     Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
     Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
-    Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
+    Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+    Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
 
     // Base case. FIXME: Remove once we can instantiate everything.
     Decl *VisitDecl(Decl *D) {
@@ -1025,8 +1026,33 @@
   return Inst;
 }
 
-Decl *
-TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
+  NestedNameSpecifier *NNS =
+    SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+                                     D->getTargetNestedNameRange(),
+                                     TemplateArgs);
+  if (!NNS)
+    return 0;
+
+  CXXScopeSpec SS;
+  SS.setRange(D->getTargetNestedNameRange());
+  SS.setScopeRep(NNS);
+
+  NamedDecl *UD =
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getUsingLoc(), SS, D->getLocation(),
+                                  D->getDeclName(), 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ true, D->getTypenameLoc());
+  if (UD)
+    SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
+                                                           D);
+  return UD;
+}
+
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
   NestedNameSpecifier *NNS =
     SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
                                      D->getTargetNestedNameRange(),
@@ -1040,8 +1066,10 @@
 
   NamedDecl *UD =
     SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
-                                  D->getLocation(), SS, D->getTargetNameLocation(),
-                                  D->getDeclName(), 0, D->isTypeName());
+                                  D->getUsingLoc(), SS, D->getLocation(),
+                                  D->getDeclName(), 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ false, SourceLocation());
   if (UD)
     SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
                                                            D);
@@ -1724,7 +1752,13 @@
   return false;
 }
 
-static bool isInstantiationOf(UnresolvedUsingDecl *Pattern,
+static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
                               UsingDecl *Instance,
                               ASTContext &C) {
   return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
@@ -1747,7 +1781,15 @@
 
 static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
   if (D->getKind() != Other->getKind()) {
-    if (UnresolvedUsingDecl *UUD = dyn_cast<UnresolvedUsingDecl>(D)) {
+    if (UnresolvedUsingTypenameDecl *UUD
+          = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+        return isInstantiationOf(UUD, UD, Ctx);
+      }
+    }
+
+    if (UnresolvedUsingValueDecl *UUD
+          = dyn_cast<UnresolvedUsingValueDecl>(D)) {
       if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
         return isInstantiationOf(UUD, UD, Ctx);
       }

Modified: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp?rev=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p1.cpp Tue Nov 17 20:36:19 2009
@@ -7,11 +7,11 @@
 class foo {};
 test<0> foo(foo); // expected-note {{candidate}}
 
-namespace A {
+namespace Test0 {
   class foo { int x; };
   test<1> foo(class foo);
 
-  namespace B {
+  namespace A {
     test<2> foo(class ::foo); // expected-note {{candidate}}
 
     void test0() {
@@ -22,7 +22,7 @@
     }
 
     void test1() {
-      using A::foo;
+      using Test0::foo;
 
       class foo a;
       test<1> _ = (foo)(a);
@@ -37,8 +37,31 @@
       // But basic unqualified lookup is not.
       test<2> _1 = (foo)(a);
 
-      class A::foo b;
+      class Test0::foo b;
       test<2> _2 = (foo)(b); // expected-error {{incompatible type passing}}
     }
   }
 }
+
+namespace Test1 {
+  namespace A {
+    class a {};
+  }
+
+  namespace B {
+    typedef class {} b;
+  }
+
+  namespace C {
+    int c(); // expected-note {{target of using declaration}}
+  }
+
+  namespace D {
+    using typename A::a;
+    using typename B::b;
+    using typename C::c; // expected-error {{'typename' keyword used on a non-type}}
+
+    a _1 = A::a();
+    b _2 = B::b();
+  }
+}

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=89184&r1=89183&r2=89184&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/using-decl-templates.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-decl-templates.cpp Tue Nov 17 20:36:19 2009
@@ -2,12 +2,12 @@
 
 template<typename T> struct A {
   void f() { }
-  struct N { };
+  struct N { }; // expected-note{{target of using declaration}}
 };
 
 template<typename T> struct B : A<T> {
   using A<T>::f;
-  using A<T>::N;
+  using A<T>::N; // expected-error{{dependent using declaration resolved to type without 'typename'}}
   
   using A<T>::foo; // expected-error{{no member named 'foo'}}
   using A<double>::f; // expected-error{{using declaration refers into 'A<double>::', which is not a base class of 'B'}}





More information about the cfe-commits mailing list