/// \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;
/// 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;
Expr *Base, bool isArrow, SourceLocation OperatorLoc,
NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
+ TypeSourceInfo *ScopeType,
+ SourceLocation ColonColonLoc,
QualType DestroyedType,
SourceLocation DestroyedTypeLoc)
: Expr(CXXPseudoDestructorExprClass,
/*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); }
/// \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; }
//
// ::[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) {
return ExprError();
} else {
// FIXME: Drops source-location information.
- ScopeType = GetTypeFromParser(T);
+ ScopeType = GetTypeFromParser(T, &ScopeTypeLoc);
if (!ScopeType->isDependentType() &&
!Context.hasSameUnqualifiedType(DestructedType, ScopeType)) {
<< ObjectType << ScopeType << BaseE->getSourceRange();
ScopeType = QualType();
+ ScopeTypeLoc = 0;
}
}
} else {
}
}
- // FIXME: Drops the scope type.
OwningExprResult Result
= Owned(new (Context) CXXPseudoDestructorExpr(Context,
Base.takeAs<Expr>(),
OpLoc,
(NestedNameSpecifier *) SS.getScopeRep(),
SS.getRange(),
+ ScopeTypeLoc,
+ CCLoc,
DestructedType,
SecondTypeName.StartLocation));
if (HasTrailingLParen)