diff options
| -rw-r--r-- | clang/include/clang/AST/ExprCXX.h | 51 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 1 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 9 | 
3 files changed, 50 insertions, 11 deletions
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 0861ff1b764..ccec7ef3301 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -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; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c3116a3885e..5ced625f61c 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2936,6 +2936,7 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,                                                         IsArrow, OpLoc,                                 (NestedNameSpecifier *) SS.getScopeRep(),                                                         SS.getRange(), +                                                       0, SourceLocation(),                                                     MemberName.getCXXNameType(),                                                         MemberLoc));    } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 9172956b515..53b3ab070fe 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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)  | 

