[cfe-commits] r97070 - in /cfe/trunk/lib/Sema: Sema.h SemaExprCXX.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 24 14:38:50 PST 2010


Author: dgregor
Date: Wed Feb 24 16:38:50 2010
New Revision: 97070

URL: http://llvm.org/viewvc/llvm-project?rev=97070&view=rev
Log:
Split ActOnPseudoDestructorExpr into the part that interprets the
parser's data structures and the part that performs semantic analysis
and AST building, in preparation for improved template instantiation
of pseudo-destructor expressions.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=97070&r1=97069&r2=97070&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Feb 24 16:38:50 2010
@@ -2181,6 +2181,15 @@
   OwningExprResult DiagnoseDtorReference(SourceLocation NameLoc,
                                          ExprArg MemExpr);
   
+  OwningExprResult BuildPseudoDestructorExpr(ExprArg Base,
+                                             SourceLocation OpLoc,
+                                             tok::TokenKind OpKind,
+                                             const CXXScopeSpec &SS,
+                                             TypeSourceInfo *ScopeType,
+                                             SourceLocation CCLoc,
+                                             TypeSourceInfo *DestroyedType,
+                                             bool HasTrailingLParen);
+  
   OwningExprResult ActOnDependentPseudoDestructorExpr(Scope *S, 
                                                       ExprArg Base,
                                                       SourceLocation OpLoc,

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=97070&r1=97069&r2=97070&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb 24 16:38:50 2010
@@ -17,6 +17,7 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
@@ -2426,6 +2427,102 @@
                        /*RPLoc*/ ExpectedLParenLoc);
 }
 
+Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
+                                                       SourceLocation OpLoc,
+                                                       tok::TokenKind OpKind,
+                                                       const CXXScopeSpec &SS,
+                                                   TypeSourceInfo *ScopeTypeInfo,
+                                                       SourceLocation CCLoc,
+                                               TypeSourceInfo *DestructedTypeLoc,
+                                                       bool HasTrailingLParen) {
+  assert(DestructedTypeLoc && "No destructed type in pseudo-destructor expr?");
+  
+  // C++ [expr.pseudo]p2:
+  //   The left-hand side of the dot operator shall be of scalar type. The 
+  //   left-hand side of the arrow operator shall be of pointer to scalar type.
+  //   This scalar type is the object type. 
+  Expr *BaseE = (Expr *)Base.get();
+  QualType ObjectType = BaseE->getType();
+  if (OpKind == tok::arrow) {
+    if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
+      ObjectType = Ptr->getPointeeType();
+    } else if (!BaseE->isTypeDependent()) {
+      // The user wrote "p->" when she probably meant "p."; fix it.
+      Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
+        << ObjectType << true
+        << CodeModificationHint::CreateReplacement(OpLoc, ".");
+      if (isSFINAEContext())
+        return ExprError();
+      
+      OpKind = tok::period;
+    }
+  }
+  
+  if (!ObjectType->isDependentType() && !ObjectType->isScalarType()) {
+    Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
+      << ObjectType << BaseE->getSourceRange();
+    return ExprError();
+  }
+
+  // C++ [expr.pseudo]p2:
+  //   [...] The cv-unqualified versions of the object type and of the type 
+  //   designated by the pseudo-destructor-name shall be the same type.
+  QualType DestructedType = DestructedTypeLoc->getType();
+  SourceLocation DestructedTypeStart
+    = DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin();
+  if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
+      !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
+    Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
+      << ObjectType << DestructedType << BaseE->getSourceRange()
+      << DestructedTypeLoc->getTypeLoc().getSourceRange();
+    
+    // Recover by 
+    DestructedType = ObjectType;
+    DestructedTypeLoc = Context.getTrivialTypeSourceInfo(ObjectType,
+                                                         DestructedTypeStart);
+  }
+   
+  // C++ [expr.pseudo]p2:
+  //   [...] Furthermore, the two type-names in a pseudo-destructor-name of the
+  //   form
+  //
+  //     ::[opt] nested-name-specifier[opt] type-name :: ~ type-name 
+  //
+  //   shall designate the same scalar type.
+  if (ScopeTypeInfo) {
+    QualType ScopeType = ScopeTypeInfo->getType();
+    if (!ScopeType->isDependentType() && !ObjectType->isDependentType() &&
+        !Context.hasSameType(ScopeType, ObjectType)) {
+      
+      Diag(ScopeTypeInfo->getTypeLoc().getSourceRange().getBegin(),
+           diag::err_pseudo_dtor_type_mismatch)
+        << ObjectType << ScopeType << BaseE->getSourceRange()
+        << ScopeTypeInfo->getTypeLoc().getSourceRange();
+  
+      ScopeType = QualType();
+      ScopeTypeInfo = 0;
+    }
+  }
+  
+  OwningExprResult Result
+    = Owned(new (Context) CXXPseudoDestructorExpr(Context, 
+                                                  Base.takeAs<Expr>(),
+                                                  OpKind == tok::arrow,
+                                                  OpLoc,
+                                       (NestedNameSpecifier *) SS.getScopeRep(),
+                                                  SS.getRange(),
+                                                  ScopeTypeInfo,
+                                                  CCLoc,
+                                                  DestructedType,
+                                                  DestructedTypeStart));
+  if (HasTrailingLParen)
+    return move(Result);
+  
+  return DiagnoseDtorReference(
+                  DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin(),
+                               move(Result));  
+}
+
 Sema::OwningExprResult 
 Sema::ActOnDependentPseudoDestructorExpr(Scope *S, 
                                          ExprArg Base,
@@ -2592,29 +2689,20 @@
   if (OpKind == tok::arrow) {
     if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
       ObjectType = Ptr->getPointeeType();
-    } else {
+    } else if (!BaseE->isTypeDependent()) {
       // The user wrote "p->" when she probably meant "p."; fix it.
       Diag(OpLoc, diag::err_typecheck_member_reference_suggestion)
-        << ObjectType << true
-        << CodeModificationHint::CreateReplacement(OpLoc, ".");
+      << ObjectType << true
+      << CodeModificationHint::CreateReplacement(OpLoc, ".");
       if (isSFINAEContext())
         return ExprError();
       
       OpKind = tok::period;
     }
   }
-
-  if (!ObjectType->isScalarType()) {
-    Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
-      << ObjectType << BaseE->getSourceRange();
-    return ExprError();
-  }
-
-  // 
   
-  // C++ [expr.pseudo]p2:
-  //   [...] The cv-unqualified versions of the object type and of the type 
-  //   designated by the pseudo-destructor-name shall be the same type.
+  // Convert the name of the type being destructed (following the ~) into a 
+  // type (with source-location information).
   QualType DestructedType;
   TypeSourceInfo *DestructedTypeInfo = 0;
   if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
@@ -2630,42 +2718,34 @@
       
       // Recover by assuming we had the right type all along.
       DestructedType = ObjectType;
-    } else {
+    } else
       DestructedType = GetTypeFromParser(T, &DestructedTypeInfo);
-      
-      if (!DestructedType->isDependentType() &&
-          !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
-        // The types mismatch. Recover by assuming we had the right type
-        // all along.
-        Diag(SecondTypeName.StartLocation, diag::err_pseudo_dtor_type_mismatch)
-          << ObjectType << DestructedType << BaseE->getSourceRange();
-        
-        DestructedType = ObjectType;
-        DestructedTypeInfo = 0;
-      }
-    }
   } else {
-    // FIXME: C++0x template aliases would allow a template-id here. For now,
-    // just diagnose this as an error.
+    // Resolve the template-id to a type.
     TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
-    Diag(TemplateId->TemplateNameLoc, diag::err_pseudo_dtor_template)
-      << TemplateId->Name << ObjectType
-      << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc);
-    if (isSFINAEContext())
-      return ExprError();
-    
-    // Recover by assuming we had the right type all along.
-    DestructedType = ObjectType;
+    ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                       TemplateId->getTemplateArgs(),
+                                       TemplateId->NumArgs);
+    TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+                                       TemplateId->TemplateNameLoc,
+                                       TemplateId->LAngleLoc,
+                                       TemplateArgsPtr,
+                                       TemplateId->RAngleLoc);
+    if (T.isInvalid() || !T.get()) {
+      // Recover by assuming we had the right type all along.
+      DestructedType = ObjectType;
+    } else
+      DestructedType = GetTypeFromParser(T.get(), &DestructedTypeInfo);
   }
   
-  // C++ [expr.pseudo]p2:
-  //   [...] Furthermore, the two type-names in a pseudo-destructor-name of the
-  //   form
-  //
-  //     ::[opt] nested-name-specifier[opt] type-name :: ~ type-name 
-  //
-  //   shall designate the same scalar type.
-  TypeSourceInfo *ScopeTypeLoc;
+  // If we've performed some kind of recovery, (re-)build the type source 
+  // information.
+  if (!DestructedTypeInfo)
+    DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
+                                                  SecondTypeName.StartLocation);
+  
+  // Convert the name of the scope type (the type prior to '::') into a type.
+  TypeSourceInfo *ScopeTypeInfo = 0;
   QualType ScopeType;
   if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || 
       FirstTypeName.Identifier) {
@@ -2677,53 +2757,36 @@
         Diag(FirstTypeName.StartLocation, 
              diag::err_pseudo_dtor_destructor_non_type)
           << FirstTypeName.Identifier << ObjectType;
+        
         if (isSFINAEContext())
-          return ExprError();        
-      } else {
-        // FIXME: Drops source-location information.
-        ScopeType = GetTypeFromParser(T, &ScopeTypeLoc);
+          return ExprError();
         
-        if (!ScopeType->isDependentType() &&
-            !Context.hasSameUnqualifiedType(DestructedType, ScopeType)) {
-          // The types mismatch. Recover by assuming we don't have a scoping 
-          // type.
-          Diag(FirstTypeName.StartLocation, diag::err_pseudo_dtor_type_mismatch)
-            << ObjectType << ScopeType << BaseE->getSourceRange();
-          
-          ScopeType = QualType();
-          ScopeTypeLoc = 0;
-        }
-      }
+        // Just drop this type. It's unnecessary anyway.
+        ScopeType = QualType();
+      } else
+        ScopeType = GetTypeFromParser(T, &ScopeTypeInfo);
     } else {
-      // FIXME: C++0x template aliases would allow a template-id here. For now,
-      // just diagnose this as an error.
+      // Resolve the template-id to a type.
       TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
-      Diag(TemplateId->TemplateNameLoc, diag::err_pseudo_dtor_template)
-        << TemplateId->Name << ObjectType
-        << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc);
-      if (isSFINAEContext())
-        return ExprError();
-      
-      // Recover by assuming we have no scoping type.
-      DestructedType = ObjectType;
+      ASTTemplateArgsPtr TemplateArgsPtr(*this,
+                                         TemplateId->getTemplateArgs(),
+                                         TemplateId->NumArgs);
+      TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
+                                         TemplateId->TemplateNameLoc,
+                                         TemplateId->LAngleLoc,
+                                         TemplateArgsPtr,
+                                         TemplateId->RAngleLoc);
+      if (T.isInvalid() || !T.get()) {
+        // Recover by dropping this type.
+        ScopeType = QualType();
+      } else
+        ScopeType = GetTypeFromParser(T.get(), &ScopeTypeInfo);      
     }
   }
-  
-  OwningExprResult Result
-    = Owned(new (Context) CXXPseudoDestructorExpr(Context, 
-                                                  Base.takeAs<Expr>(),
-                                                  OpKind == tok::arrow,
-                                                  OpLoc,
-                                       (NestedNameSpecifier *) SS.getScopeRep(),
-                                                  SS.getRange(),
-                                                  ScopeTypeLoc,
-                                                  CCLoc,
-                                                  DestructedType,
-                                                 SecondTypeName.StartLocation));
-  if (HasTrailingLParen)
-    return move(Result);
-  
-  return DiagnoseDtorReference(SecondTypeName.StartLocation, move(Result));
+            
+  return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS,
+                                   ScopeTypeInfo, CCLoc, DestructedTypeInfo,
+                                   HasTrailingLParen);
 }
 
 CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp, 





More information about the cfe-commits mailing list