[cfe-commits] r96836 - in /cfe/trunk: lib/Sema/SemaExprCXX.cpp test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp test/SemaCXX/pseudo-destructors.cpp

Douglas Gregor dgregor at apple.com
Mon Feb 22 16:15:22 PST 2010


Author: dgregor
Date: Mon Feb 22 18:15:22 2010
New Revision: 96836

URL: http://llvm.org/viewvc/llvm-project?rev=96836&view=rev
Log:
Implement crazy destructor name lookup semantics differently in
C++98/03 and C++0x, since the '0x semantics break valid C++98/03
code. This new mess is tracked by core issue 399, which is still
unresolved.

Fixes PR6358 and PR6359.

Added:
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp
    cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp
Modified:
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/pseudo-destructors.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=96836&r1=96835&r2=96836&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Feb 22 18:15:22 2010
@@ -49,7 +49,7 @@
   //     s->N::S<int>::~S();
   //   }
   //
-  // 
+  // See also PR6358 and PR6359.
   QualType SearchType;
   DeclContext *LookupCtx = 0;
   bool isDependent = false;
@@ -62,7 +62,39 @@
     SearchType = GetTypeFromParser(ObjectTypePtr);
 
   if (SS.isSet()) {
-    // C++ [basic.lookup.qual]p6:
+    NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
+    
+    bool AlreadySearched = false;
+    bool LookAtPrefix = true;
+    if (!getLangOptions().CPlusPlus0x) {
+      // C++ [basic.lookup.qual]p6:
+      //   If a pseudo-destructor-name (5.2.4) contains a nested-name-specifier, 
+      //   the type-names are looked up as types in the scope designated by the
+      //   nested-name-specifier. In a qualified-id of the form:
+      // 
+      //     ::[opt] nested-name-specifier  ̃ class-name 
+      //
+      //   where the nested-name-specifier designates a namespace scope, and in
+      //   a qualified-id of the form:
+      //
+      //     ::opt nested-name-specifier class-name ::  ̃ class-name 
+      //
+      //   the class-names are looked up as types in the scope designated by 
+      //   the nested-name-specifier.
+      //
+      // Here, we check the first case (completely) and determine whether the
+      // code below is permitted to look at the prefix of the 
+      // nested-name-specifier (as we do in C++0x).
+      DeclContext *DC = computeDeclContext(SS, EnteringContext);
+      if (DC && DC->isFileContext()) {
+        AlreadySearched = true;
+        LookupCtx = DC;
+        isDependent = false;
+      } else if (DC && isa<CXXRecordDecl>(DC))
+        LookAtPrefix = false;
+    }
+    
+    // C++0x [basic.lookup.qual]p6:
     //   If a pseudo-destructor-name (5.2.4) contains a
     //   nested-name-specifier, the type-names are looked up as types
     //   in the scope designated by the nested-name-specifier. Similarly, in 
@@ -72,23 +104,33 @@
     //
     //   the second class-name is looked up in the same scope as the first.
     //
-    // FIXME: We don't implement this, because it breaks lots of
-    // perfectly reasonable code that no other compilers diagnose. The
-    // issue is that the first class-name is looked up as a
-    // nested-name-specifier, so we ignore value declarations, but the
-    // second lookup is presumably an ordinary name lookup. Hence, we
-    // end up finding values (say, a function) and complain. See PRs
-    // 6358 and 6359 for examples of such code. DPG to investigate
-    // further.
-    if (ObjectTypePtr) {
+    // To implement this, we look at the prefix of the
+    // nested-name-specifier we were given, and determine the lookup
+    // context from that.
+    //
+    // We also fold in the second case from the C++03 rules quoted further 
+    // above.
+    NestedNameSpecifier *Prefix = 0;
+    if (AlreadySearched) {
+      // Nothing left to do.
+    } else if (LookAtPrefix && (Prefix = NNS->getPrefix())) {
+      CXXScopeSpec PrefixSS;
+      PrefixSS.setScopeRep(Prefix);
+      LookupCtx = computeDeclContext(PrefixSS, EnteringContext);
+      isDependent = isDependentScopeSpecifier(PrefixSS);
+    } else if (getLangOptions().CPlusPlus0x &&
+               (LookupCtx = computeDeclContext(SS, EnteringContext))) {
+      if (!LookupCtx->isTranslationUnit())
+        LookupCtx = LookupCtx->getParent();
+      isDependent = LookupCtx && LookupCtx->isDependentContext();
+    } else if (ObjectTypePtr) {
       LookupCtx = computeDeclContext(SearchType);
       isDependent = SearchType->isDependentType();
     } else {
       LookupCtx = computeDeclContext(SS, EnteringContext);
-      if (LookupCtx)
-        isDependent = LookupCtx->isDependentContext();
+      isDependent = LookupCtx && LookupCtx->isDependentContext();
     }
-
+    
     LookInScope = (LookupCtx == 0) && !isDependent;
   } else if (ObjectTypePtr) {
     // C++ [basic.lookup.classref]p3:

Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp?rev=96836&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.classref/p3.cpp Mon Feb 22 18:15:22 2010
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// C++0x [basic.lookup.classref]p3:
+//   If the unqualified-id is ∼type-name, the type-name is looked up in the 
+//   context of the entire postfix-expression. If the type T of the object 
+//   expression is of a class type C, the type-name is also looked up in the 
+//   scope of class C. At least one of the lookups shall find a name that 
+//   refers to (possibly cv-qualified) T.
+
+// From core issue 305
+struct A {
+};
+
+struct C {
+  struct A {};
+  void f ();
+};
+
+void C::f () {
+  ::A *a;
+  a->~A ();
+}
+
+// From core issue 414
+struct X {};
+void f() {
+  X x;
+  struct X {};
+  x.~X();
+}

Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp?rev=96836&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6-0x.cpp Mon Feb 22 18:15:22 2010
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+struct C { 
+  typedef int I;
+}; 
+
+typedef int I1, I2; 
+extern int* p; 
+extern int* q; 
+
+void f() {
+  p->C::I::~I(); 
+  q->I1::~I2();
+}
+
+struct A { 
+  ~A();
+}; 
+
+typedef A AB; 
+int main() {
+  AB *p; 
+  p->AB::~AB();
+}

Added: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp?rev=96836&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.qual/p6.cpp Mon Feb 22 18:15:22 2010
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct C { 
+  typedef int I;
+}; 
+
+typedef int I1, I2; 
+extern int* p; 
+extern int* q; 
+
+void f() {
+  p->C::I::~I(); 
+  q->I1::~I2();
+}
+
+struct A { 
+  ~A();
+}; 
+
+typedef A AB; 
+int main() {
+  AB *p; 
+  p->AB::~AB(); // expected-error{{identifier 'AB' in pseudo-destructor expression does not name a type}}
+}

Modified: cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pseudo-destructors.cpp?rev=96836&r1=96835&r2=96836&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/pseudo-destructors.cpp (original)
+++ cfe/trunk/test/SemaCXX/pseudo-destructors.cpp Mon Feb 22 18:15:22 2010
@@ -29,7 +29,7 @@
   g().~Bar(); // expected-error{{non-scalar}}
   
   f->::~Bar();
-  f->N::~Wibble(); // FIXME: Cannot use typedef name in destructor id.
+  f->N::~Wibble(); // FIXME: technically, Wibble isn't a class-name
   
   f->::~Bar(17, 42); // expected-error{{cannot have any arguments}}
 





More information about the cfe-commits mailing list