[cfe-commits] r89493 - in /cfe/trunk: include/clang/Parse/Action.h lib/Parse/MinimalAction.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/SemaCXX/pseudo-destructors.cpp

Douglas Gregor dgregor at apple.com
Fri Nov 20 14:03:39 PST 2009


Author: dgregor
Date: Fri Nov 20 16:03:38 2009
New Revision: 89493

URL: http://llvm.org/viewvc/llvm-project?rev=89493&view=rev
Log:
Implement C++ [basic.lookup.classref]p3, which states how the type
name 'T' is looked up in the expression

  t.~T()

Previously, we weren't looking into the type of "t", and therefore
would fail when T actually referred to an injected-class-name. Fixes
PR5530.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Parse/MinimalAction.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/pseudo-destructors.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri Nov 20 16:03:38 2009
@@ -203,11 +203,15 @@
   /// this occurs when deriving from "std::vector<T>::allocator_type", where T
   /// is a template parameter.
   ///
+  /// \param ObjectType if we're checking whether an identifier is a type
+  /// within a C++ member access expression, this will be the type of the 
+  /// 
   /// \returns the type referred to by this identifier, or NULL if the type
   /// does not name an identifier.
   virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
                               Scope *S, const CXXScopeSpec *SS = 0,
-                              bool isClassName = false) = 0;
+                              bool isClassName = false,
+                              TypeTy *ObjectType = 0) = 0;
 
   /// isTagName() - This method is called *for error recovery purposes only*
   /// to determine if the specified name is a valid tag name ("struct foo").  If
@@ -2518,7 +2522,8 @@
   /// does not name an identifier.
   virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
                               Scope *S, const CXXScopeSpec *SS,
-                              bool isClassName = false);
+                              bool isClassName = false,
+                              TypeTy *ObjectType = 0);
 
   /// isCurrentClassName - Always returns false, because MinimalAction
   /// does not support C++ classes with constructors.

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

==============================================================================
--- cfe/trunk/lib/Parse/MinimalAction.cpp (original)
+++ cfe/trunk/lib/Parse/MinimalAction.cpp Fri Nov 20 16:03:38 2009
@@ -144,7 +144,7 @@
 Action::TypeTy *
 MinimalAction::getTypeName(IdentifierInfo &II, SourceLocation Loc,
                            Scope *S, const CXXScopeSpec *SS,
-                           bool isClassName) {
+                           bool isClassName, TypeTy *ObjectType) {
   if (TypeNameInfo *TI = II.getFETokenInfo<TypeNameInfo>())
     if (TI->isTypeName)
       return TI;

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Fri Nov 20 16:03:38 2009
@@ -1010,7 +1010,7 @@
   
   // Parse the type-specifier-seq.
   DeclSpec DS;
-  if (ParseCXXTypeSpecifierSeq(DS))
+  if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
     return true;
   
   // Parse the conversion-declarator, which is merely a sequence of
@@ -1152,7 +1152,7 @@
     
     // Note that this is a destructor name.
     Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
-                                             CurScope, &SS);
+                                             CurScope, &SS, false, ObjectType);
     if (!Ty) {
       if (ObjectType)
         Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Nov 20 16:03:38 2009
@@ -533,7 +533,8 @@
 
   virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
                               Scope *S, const CXXScopeSpec *SS,
-                              bool isClassName = false);
+                              bool isClassName = false,
+                              TypeTy *ObjectType = 0);
   virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S);
   virtual bool DiagnoseUnknownTypeName(const IdentifierInfo &II, 
                                        SourceLocation IILoc,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Nov 20 16:03:38 2009
@@ -66,31 +66,68 @@
 /// and then return NULL.
 Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, SourceLocation NameLoc,
                                 Scope *S, const CXXScopeSpec *SS,
-                                bool isClassName) {
-  // C++ [temp.res]p3:
-  //   A qualified-id that refers to a type and in which the
-  //   nested-name-specifier depends on a template-parameter (14.6.2)
-  //   shall be prefixed by the keyword typename to indicate that the
-  //   qualified-id denotes a type, forming an
-  //   elaborated-type-specifier (7.1.5.3).
-  //
-  // We therefore do not perform any name lookup if the result would
-  // refer to a member of an unknown specialization.
-  if (SS && isUnknownSpecialization(*SS)) {
-    if (!isClassName)
+                                bool isClassName,
+                                TypeTy *ObjectTypePtr) {
+  // Determine where we will perform name lookup.
+  DeclContext *LookupCtx = 0;
+  if (ObjectTypePtr) {
+    QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
+    if (ObjectType->isRecordType())
+      LookupCtx = computeDeclContext(ObjectType);
+  } else if (SS && SS->isSet()) {
+    LookupCtx = computeDeclContext(*SS, false);
+
+    if (!LookupCtx) {
+      if (isDependentScopeSpecifier(*SS)) {
+        // C++ [temp.res]p3:
+        //   A qualified-id that refers to a type and in which the
+        //   nested-name-specifier depends on a template-parameter (14.6.2)
+        //   shall be prefixed by the keyword typename to indicate that the
+        //   qualified-id denotes a type, forming an
+        //   elaborated-type-specifier (7.1.5.3).
+        //
+        // We therefore do not perform any name lookup if the result would
+        // refer to a member of an unknown specialization.
+        if (!isClassName)
+          return 0;
+        
+        // We know from the grammar that this name refers to a type, so build a
+        // TypenameType node to describe the type.
+        // FIXME: Record somewhere that this TypenameType node has no "typename"
+        // keyword associated with it.
+        return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
+                                 II, SS->getRange()).getAsOpaquePtr();
+      }
+      
+      return 0;
+    }
+    
+    if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS))
       return 0;
-
-    // We know from the grammar that this name refers to a type, so build a
-    // TypenameType node to describe the type.
-    // FIXME: Record somewhere that this TypenameType node has no "typename"
-    // keyword associated with it.
-    return CheckTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
-                             II, SS->getRange()).getAsOpaquePtr();
   }
-
+      
   LookupResult Result(*this, &II, NameLoc, LookupOrdinaryName);
-  LookupParsedName(Result, S, SS, false);
-
+  if (LookupCtx) {
+    // Perform "qualified" name lookup into the declaration context we
+    // computed, which is either the type of the base of a member access
+    // expression or the declaration context associated with a prior
+    // nested-name-specifier.
+    LookupQualifiedName(Result, LookupCtx);
+
+    if (ObjectTypePtr && Result.empty()) {
+      // C++ [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.
+      LookupName(Result, S);
+    }
+  } else {
+    // Perform unqualified name lookup.
+    LookupName(Result, S);
+  }
+  
   NamedDecl *IIDecl = 0;
   switch (Result.getResultKind()) {
   case LookupResult::NotFound:

Modified: cfe/trunk/test/SemaCXX/pseudo-destructors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/pseudo-destructors.cpp?rev=89493&r1=89492&r2=89493&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/pseudo-destructors.cpp (original)
+++ cfe/trunk/test/SemaCXX/pseudo-destructors.cpp Fri Nov 20 16:03:38 2009
@@ -38,3 +38,12 @@
 void destroy_without_call(int *ip) {
   ip->~Integer; // expected-error{{called immediately}}
 }
+
+// PR5530
+namespace N1 {
+  class X0 { };
+}
+
+void test_X0(N1::X0 &x0) {
+  x0.~X0();
+}





More information about the cfe-commits mailing list