]> granicus.if.org Git - clang/commitdiff
Retain source information for the "type-name ::" in a
authorDouglas Gregor <dgregor@apple.com>
Wed, 24 Feb 2010 21:52:20 +0000 (21:52 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 24 Feb 2010 21:52:20 +0000 (21:52 +0000)
pseudo-destructor expression such as

  p->T::~T()

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97060 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/ExprCXX.h
lib/Sema/SemaExpr.cpp
lib/Sema/SemaExprCXX.cpp

index 0861ff1b76424aa39164ad4c894872f381ea8793..ccec7ef3301928caf6efe18f4bc38cb4a703ab1c 100644 (file)
@@ -999,19 +999,28 @@ public:
 
 /// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]).
 ///
-/// Example:
+/// A pseudo-destructor is an expression that looks like a member access to a
+/// destructor of a scalar type, except that scalar types don't have 
+/// destructors. For example:
+///
+/// \code
+/// typedef int T;
+/// void f(int *p) {
+///   p->T::~T();
+/// }
+/// \endcode
 ///
+/// Pseudo-destructors typically occur when instantiating templates such as:
+/// 
 /// \code
 /// template<typename T>
 /// void destroy(T* ptr) {
-///   ptr->~T();
+///   ptr->T::~T();
 /// }
 /// \endcode
 ///
-/// When the template is parsed, the expression \c ptr->~T will be stored as
-/// a member reference expression. If it then instantiated with a scalar type
-/// as a template argument for T, the resulting expression will be a
-/// pseudo-destructor expression.
+/// for scalar types. A pseudo-destructor expression has no run-time semantics
+/// beyond evaluating the base expression.
 class CXXPseudoDestructorExpr : public Expr {
   /// \brief The base expression (that is being destroyed).
   Stmt *Base;
@@ -1030,6 +1039,14 @@ class CXXPseudoDestructorExpr : public Expr {
   /// present.
   SourceRange QualifierRange;
 
+  /// \brief The type that precedes the '::' in a qualified pseudo-destructor
+  /// expression.
+  TypeSourceInfo *ScopeType;
+  
+  /// \brief The location of the '::' in a qualified pseudo-destructor 
+  /// expression.
+  SourceLocation ColonColonLoc;
+  
   /// \brief The type being destroyed.
   QualType DestroyedType;
 
@@ -1041,6 +1058,8 @@ public:
                           Expr *Base, bool isArrow, SourceLocation OperatorLoc,
                           NestedNameSpecifier *Qualifier,
                           SourceRange QualifierRange,
+                          TypeSourceInfo *ScopeType,
+                          SourceLocation ColonColonLoc,
                           QualType DestroyedType,
                           SourceLocation DestroyedTypeLoc)
     : Expr(CXXPseudoDestructorExprClass,
@@ -1052,8 +1071,9 @@ public:
            /*isValueDependent=*/Base->isValueDependent()),
       Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
       OperatorLoc(OperatorLoc), Qualifier(Qualifier),
-      QualifierRange(QualifierRange), DestroyedType(DestroyedType),
-      DestroyedTypeLoc(DestroyedTypeLoc) { }
+      QualifierRange(QualifierRange), 
+      ScopeType(ScopeType), ColonColonLoc(ColonColonLoc),
+      DestroyedType(DestroyedType), DestroyedTypeLoc(DestroyedTypeLoc) { }
 
   void setBase(Expr *E) { Base = E; }
   Expr *getBase() const { return cast<Expr>(Base); }
@@ -1081,6 +1101,21 @@ public:
   /// \brief Retrieve the location of the '.' or '->' operator.
   SourceLocation getOperatorLoc() const { return OperatorLoc; }
 
+  /// \brief Retrieve the scope type in a qualified pseudo-destructor 
+  /// expression.
+  ///
+  /// Pseudo-destructor expressions can have extra qualification within them
+  /// that is not part of the nested-name-specifier, e.g., \c p->T::~T().
+  /// Here, if the object type of the expression is (or may be) a scalar type,
+  /// \p T may also be a scalar type and, therefore, cannot be part of a 
+  /// nested-name-specifier. It is stored as the "scope type" of the pseudo-
+  /// destructor expression.
+  TypeSourceInfo *getScopeTypeLoc() const { return ScopeType; }
+  
+  /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
+  /// expression.
+  SourceLocation getColonColonLoc() const { return ColonColonLoc; }
+  
   /// \brief Retrieve the type that is being destroyed.
   QualType getDestroyedType() const { return DestroyedType; }
 
index c3116a3885ebe6f754338b9a210301993df00ff8..5ced625f61ca1161a5b013c246ff61709b9212ce 100644 (file)
@@ -2936,6 +2936,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
                                                        IsArrow, OpLoc,
                                (NestedNameSpecifier *) SS.getScopeRep(),
                                                        SS.getRange(),
+                                                       0, SourceLocation(),
                                                    MemberName.getCXXNameType(),
                                                        MemberLoc));
   }
index 9172956b515300ac31aa9070decf059c647ab859..53b3ab070fe40a3f52a4b541062509ec5f8f170b 100644 (file)
@@ -2664,7 +2664,8 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
   //
   //     ::[opt] nested-name-specifier[opt] type-name :: ~ type-name 
   //
-  //   shall designate the same scalar type.  
+  //   shall designate the same scalar type.
+  TypeSourceInfo *ScopeTypeLoc;
   QualType ScopeType;
   if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId || 
       FirstTypeName.Identifier) {
@@ -2680,7 +2681,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
           return ExprError();        
       } else {
         // FIXME: Drops source-location information.
-        ScopeType = GetTypeFromParser(T);
+        ScopeType = GetTypeFromParser(T, &ScopeTypeLoc);
         
         if (!ScopeType->isDependentType() &&
             !Context.hasSameUnqualifiedType(DestructedType, ScopeType)) {
@@ -2690,6 +2691,7 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
             << ObjectType << ScopeType << BaseE->getSourceRange();
           
           ScopeType = QualType();
+          ScopeTypeLoc = 0;
         }
       }
     } else {
@@ -2707,7 +2709,6 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
     }
   }
   
-  // FIXME: Drops the scope type.
   OwningExprResult Result
     = Owned(new (Context) CXXPseudoDestructorExpr(Context, 
                                                   Base.takeAs<Expr>(),
@@ -2715,6 +2716,8 @@ Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
                                                   OpLoc,
                                        (NestedNameSpecifier *) SS.getScopeRep(),
                                                   SS.getRange(),
+                                                  ScopeTypeLoc,
+                                                  CCLoc,
                                                   DestructedType,
                                                  SecondTypeName.StartLocation));
   if (HasTrailingLParen)