[cfe-commits] r80856 - in /cfe/trunk: include/clang/AST/NestedNameSpecifier.h lib/AST/NestedNameSpecifier.cpp lib/Sema/SemaCXXScopeSpec.cpp test/SemaTemplate/member-access-expr.cpp

Douglas Gregor dgregor at apple.com
Wed Sep 2 16:58:39 PDT 2009


Author: dgregor
Date: Wed Sep  2 18:58:38 2009
New Revision: 80856

URL: http://llvm.org/viewvc/llvm-project?rev=80856&view=rev
Log:
Add a wicked little test-case that illustrates what we have to deal
with to properly support member access expressions in templates. This
test is XFAIL'd, because we get it completely wrong, but I've made the
minimal changes to the representation to at least avoid a crash.


Added:
    cfe/trunk/test/SemaTemplate/member-access-expr.cpp
Modified:
    cfe/trunk/include/clang/AST/NestedNameSpecifier.h
    cfe/trunk/lib/AST/NestedNameSpecifier.cpp
    cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/NestedNameSpecifier.h (original)
+++ cfe/trunk/include/clang/AST/NestedNameSpecifier.h Wed Sep  2 18:58:38 2009
@@ -113,6 +113,14 @@
                                      NestedNameSpecifier *Prefix, 
                                      bool Template, Type *T);
 
+  /// \brief Builds a specifier that consists of just an identifier.
+  ///
+  /// The nested-name-specifier is assumed to be dependent, but has no
+  /// prefix because the prefix is implied by something outside of the
+  /// nested name specifier, e.g., in "x->Base::f", the "x" has a dependent
+  /// type.
+  static NestedNameSpecifier *Create(ASTContext &Context, IdentifierInfo *II);
+  
   /// \brief Returns the nested name specifier representing the global
   /// scope.
   static NestedNameSpecifier *GlobalSpecifier(ASTContext &Context);

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

==============================================================================
--- cfe/trunk/lib/AST/NestedNameSpecifier.cpp (original)
+++ cfe/trunk/lib/AST/NestedNameSpecifier.cpp Wed Sep  2 18:58:38 2009
@@ -75,7 +75,17 @@
   Mockup.Specifier = T;
   return FindOrInsert(Context, Mockup);
 }
-  
+
+NestedNameSpecifier *
+NestedNameSpecifier::Create(ASTContext &Context, IdentifierInfo *II) {
+  assert(II && "Identifier cannot be NULL");
+  NestedNameSpecifier Mockup;
+  Mockup.Prefix.setPointer(0);
+  Mockup.Prefix.setInt(Identifier);
+  Mockup.Specifier = II;
+  return FindOrInsert(Context, Mockup);
+}
+
 NestedNameSpecifier *NestedNameSpecifier::GlobalSpecifier(ASTContext &Context) {
   if (!Context.GlobalNestedNameSpecifier)
     Context.GlobalNestedNameSpecifier = new (Context, 4) NestedNameSpecifier();

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Wed Sep  2 18:58:38 2009
@@ -357,7 +357,8 @@
       // unqualified name lookup in the given scope.
       
       // FIXME: When we're instantiating a template, do we actually have to
-      // look in the scope of the template? Seems fishy...
+      // look in the scope of the template? Both EDG and GCC do it; GCC 
+      // requires the lookup to be successful, EDG doesn't.
       Found = LookupName(S, &II, LookupNestedNameSpecifierName);
       ObjectTypeSearchedInScope = true;
     }
@@ -366,6 +367,9 @@
     // base object type or prior nested-name-specifier, so this 
     // nested-name-specifier refers to an unknown specialization. Just build
     // a dependent nested-name-specifier.
+    if (!Prefix)
+      return NestedNameSpecifier::Create(Context, &II);
+    
     return NestedNameSpecifier::Create(Context, Prefix, &II);
   } else {
     // Perform unqualified name lookup in the current scope.

Added: cfe/trunk/test/SemaTemplate/member-access-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/member-access-expr.cpp?rev=80856&view=auto

==============================================================================
--- cfe/trunk/test/SemaTemplate/member-access-expr.cpp (added)
+++ cfe/trunk/test/SemaTemplate/member-access-expr.cpp Wed Sep  2 18:58:38 2009
@@ -0,0 +1,48 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+// XFAIL
+template<typename T>
+void call_f0(T x) {
+  x.Base::f0();
+}
+
+struct Base {
+  void f0();
+};
+
+struct X0 : Base { 
+  typedef Base CrazyBase;
+};
+
+void test_f0(X0 x0) {
+  call_f0(x0);
+}
+
+template<typename TheBase, typename T>
+void call_f0_through_typedef(T x) {
+  typedef TheBase Base2;
+  x.Base2::f0();
+}
+
+void test_f0_through_typedef(X0 x0) {
+  call_f0_through_typedef<Base>(x0);
+}
+
+template<typename TheBase, typename T>
+void call_f0_through_typedef2(T x) {
+  typedef TheBase CrazyBase; // expected-note{{current scope}}
+  x.CrazyBase::f0(); // expected-error{{ambiguous}}
+}
+
+struct OtherBase { };
+
+struct X1 : Base, OtherBase { 
+  typedef OtherBase CrazyBase; // expected-note{{object type}}
+};
+
+void test_f0_through_typedef2(X0 x0, X1 x1) {
+  call_f0_through_typedef2<Base>(x0);
+  call_f0_through_typedef2<OtherBase>(x1);
+  call_f0_through_typedef2<Base>(x1); // expected-note{{here}}
+}
+
+





More information about the cfe-commits mailing list