forked from OSchip/llvm-project
Retain complete source information for the type after the '~' in a
CXXPseudoDestructorExpr. Update template instantiation for pseudo-destructor expressions to use this source information and to make use of Sema::BuildPseudoDestructorExpr when the base expression is dependent or refers to a scalar type. llvm-svn: 97079
This commit is contained in:
parent
88fdcd323d
commit
651fe5ec20
|
@ -1048,10 +1048,7 @@ class CXXPseudoDestructorExpr : public Expr {
|
||||||
SourceLocation ColonColonLoc;
|
SourceLocation ColonColonLoc;
|
||||||
|
|
||||||
/// \brief The type being destroyed.
|
/// \brief The type being destroyed.
|
||||||
QualType DestroyedType;
|
TypeSourceInfo *DestroyedType;
|
||||||
|
|
||||||
/// \brief The location of the type after the '~'.
|
|
||||||
SourceLocation DestroyedTypeLoc;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CXXPseudoDestructorExpr(ASTContext &Context,
|
CXXPseudoDestructorExpr(ASTContext &Context,
|
||||||
|
@ -1060,20 +1057,20 @@ public:
|
||||||
SourceRange QualifierRange,
|
SourceRange QualifierRange,
|
||||||
TypeSourceInfo *ScopeType,
|
TypeSourceInfo *ScopeType,
|
||||||
SourceLocation ColonColonLoc,
|
SourceLocation ColonColonLoc,
|
||||||
QualType DestroyedType,
|
TypeSourceInfo *DestroyedType)
|
||||||
SourceLocation DestroyedTypeLoc)
|
|
||||||
: Expr(CXXPseudoDestructorExprClass,
|
: Expr(CXXPseudoDestructorExprClass,
|
||||||
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
|
Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,
|
||||||
false, 0, false,
|
false, 0, false,
|
||||||
false, 0, 0, false,
|
false, 0, 0, false,
|
||||||
CC_Default)),
|
CC_Default)),
|
||||||
/*isTypeDependent=*/false,
|
/*isTypeDependent=*/(Base->isTypeDependent() ||
|
||||||
|
DestroyedType->getType()->isDependentType()),
|
||||||
/*isValueDependent=*/Base->isValueDependent()),
|
/*isValueDependent=*/Base->isValueDependent()),
|
||||||
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
|
Base(static_cast<Stmt *>(Base)), IsArrow(isArrow),
|
||||||
OperatorLoc(OperatorLoc), Qualifier(Qualifier),
|
OperatorLoc(OperatorLoc), Qualifier(Qualifier),
|
||||||
QualifierRange(QualifierRange),
|
QualifierRange(QualifierRange),
|
||||||
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc),
|
ScopeType(ScopeType), ColonColonLoc(ColonColonLoc),
|
||||||
DestroyedType(DestroyedType), DestroyedTypeLoc(DestroyedTypeLoc) { }
|
DestroyedType(DestroyedType) { }
|
||||||
|
|
||||||
void setBase(Expr *E) { Base = E; }
|
void setBase(Expr *E) { Base = E; }
|
||||||
Expr *getBase() const { return cast<Expr>(Base); }
|
Expr *getBase() const { return cast<Expr>(Base); }
|
||||||
|
@ -1110,21 +1107,20 @@ public:
|
||||||
/// \p T may also be a scalar type and, therefore, cannot be part of a
|
/// \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-
|
/// nested-name-specifier. It is stored as the "scope type" of the pseudo-
|
||||||
/// destructor expression.
|
/// destructor expression.
|
||||||
TypeSourceInfo *getScopeTypeLoc() const { return ScopeType; }
|
TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; }
|
||||||
|
|
||||||
/// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
|
/// \brief Retrieve the location of the '::' in a qualified pseudo-destructor
|
||||||
/// expression.
|
/// expression.
|
||||||
SourceLocation getColonColonLoc() const { return ColonColonLoc; }
|
SourceLocation getColonColonLoc() const { return ColonColonLoc; }
|
||||||
|
|
||||||
/// \brief Retrieve the type that is being destroyed.
|
/// \brief Retrieve the type that is being destroyed.
|
||||||
QualType getDestroyedType() const { return DestroyedType; }
|
QualType getDestroyedType() const { return DestroyedType->getType(); }
|
||||||
|
|
||||||
/// \brief Retrieve the location of the type being destroyed.
|
/// \brief Retrieve the source location information for the type
|
||||||
SourceLocation getDestroyedTypeLoc() const { return DestroyedTypeLoc; }
|
/// being destroyed.
|
||||||
|
TypeSourceInfo *getDestroyedTypeInfo() const { return DestroyedType; }
|
||||||
|
|
||||||
virtual SourceRange getSourceRange() const {
|
virtual SourceRange getSourceRange() const;
|
||||||
return SourceRange(Base->getLocStart(), DestroyedTypeLoc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool classof(const Stmt *T) {
|
static bool classof(const Stmt *T) {
|
||||||
return T->getStmtClass() == CXXPseudoDestructorExprClass;
|
return T->getStmtClass() == CXXPseudoDestructorExprClass;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "clang/AST/DeclCXX.h"
|
#include "clang/AST/DeclCXX.h"
|
||||||
#include "clang/AST/DeclTemplate.h"
|
#include "clang/AST/DeclTemplate.h"
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
|
#include "clang/AST/TypeLoc.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
@ -121,6 +122,12 @@ Stmt::child_iterator CXXPseudoDestructorExpr::child_end() {
|
||||||
return &Base + 1;
|
return &Base + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
|
||||||
|
return SourceRange(Base->getLocStart(),
|
||||||
|
DestroyedType->getTypeLoc().getSourceRange().getEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// UnresolvedLookupExpr
|
// UnresolvedLookupExpr
|
||||||
UnresolvedLookupExpr *
|
UnresolvedLookupExpr *
|
||||||
UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
|
UnresolvedLookupExpr::Create(ASTContext &C, bool Dependent,
|
||||||
|
|
|
@ -2932,13 +2932,15 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr,
|
||||||
|
|
||||||
// FIXME: We've lost the precise spelling of the type by going through
|
// FIXME: We've lost the precise spelling of the type by going through
|
||||||
// DeclarationName. Can we do better?
|
// DeclarationName. Can we do better?
|
||||||
|
TypeSourceInfo *DestroyedTypeInfo
|
||||||
|
= Context.getTrivialTypeSourceInfo(MemberName.getCXXNameType(),
|
||||||
|
MemberLoc);
|
||||||
return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
|
return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
|
||||||
IsArrow, OpLoc,
|
IsArrow, OpLoc,
|
||||||
(NestedNameSpecifier *) SS.getScopeRep(),
|
(NestedNameSpecifier *) SS.getScopeRep(),
|
||||||
SS.getRange(),
|
SS.getRange(),
|
||||||
0, SourceLocation(),
|
0, SourceLocation(),
|
||||||
MemberName.getCXXNameType(),
|
DestroyedTypeInfo));
|
||||||
MemberLoc));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
|
// Handle access to Objective-C instance variables, such as "Obj->ivar" and
|
||||||
|
|
|
@ -2431,11 +2431,11 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
|
||||||
SourceLocation OpLoc,
|
SourceLocation OpLoc,
|
||||||
tok::TokenKind OpKind,
|
tok::TokenKind OpKind,
|
||||||
const CXXScopeSpec &SS,
|
const CXXScopeSpec &SS,
|
||||||
TypeSourceInfo *ScopeTypeInfo,
|
TypeSourceInfo *ScopeTypeInfo,
|
||||||
SourceLocation CCLoc,
|
SourceLocation CCLoc,
|
||||||
TypeSourceInfo *DestructedTypeLoc,
|
TypeSourceInfo *DestructedTypeInfo,
|
||||||
bool HasTrailingLParen) {
|
bool HasTrailingLParen) {
|
||||||
assert(DestructedTypeLoc && "No destructed type in pseudo-destructor expr?");
|
assert(DestructedTypeInfo && "No destructed type in pseudo-destructor expr?");
|
||||||
|
|
||||||
// C++ [expr.pseudo]p2:
|
// C++ [expr.pseudo]p2:
|
||||||
// The left-hand side of the dot operator shall be of scalar type. The
|
// The left-hand side of the dot operator shall be of scalar type. The
|
||||||
|
@ -2467,18 +2467,18 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
|
||||||
// C++ [expr.pseudo]p2:
|
// C++ [expr.pseudo]p2:
|
||||||
// [...] The cv-unqualified versions of the object type and of the type
|
// [...] The cv-unqualified versions of the object type and of the type
|
||||||
// designated by the pseudo-destructor-name shall be the same type.
|
// designated by the pseudo-destructor-name shall be the same type.
|
||||||
QualType DestructedType = DestructedTypeLoc->getType();
|
QualType DestructedType = DestructedTypeInfo->getType();
|
||||||
SourceLocation DestructedTypeStart
|
SourceLocation DestructedTypeStart
|
||||||
= DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin();
|
= DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
|
||||||
if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
|
if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
|
||||||
!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
|
!Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
|
||||||
Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
|
Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
|
||||||
<< ObjectType << DestructedType << BaseE->getSourceRange()
|
<< ObjectType << DestructedType << BaseE->getSourceRange()
|
||||||
<< DestructedTypeLoc->getTypeLoc().getSourceRange();
|
<< DestructedTypeInfo->getTypeLoc().getSourceRange();
|
||||||
|
|
||||||
// Recover by
|
// Recover by
|
||||||
DestructedType = ObjectType;
|
DestructedType = ObjectType;
|
||||||
DestructedTypeLoc = Context.getTrivialTypeSourceInfo(ObjectType,
|
DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
|
||||||
DestructedTypeStart);
|
DestructedTypeStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2513,13 +2513,12 @@ Sema::OwningExprResult Sema::BuildPseudoDestructorExpr(ExprArg Base,
|
||||||
SS.getRange(),
|
SS.getRange(),
|
||||||
ScopeTypeInfo,
|
ScopeTypeInfo,
|
||||||
CCLoc,
|
CCLoc,
|
||||||
DestructedType,
|
DestructedTypeInfo));
|
||||||
DestructedTypeStart));
|
|
||||||
if (HasTrailingLParen)
|
if (HasTrailingLParen)
|
||||||
return move(Result);
|
return move(Result);
|
||||||
|
|
||||||
return DiagnoseDtorReference(
|
return DiagnoseDtorReference(
|
||||||
DestructedTypeLoc->getTypeLoc().getSourceRange().getBegin(),
|
DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin(),
|
||||||
move(Result));
|
move(Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -884,28 +884,11 @@ public:
|
||||||
OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
|
OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
|
||||||
SourceLocation OperatorLoc,
|
SourceLocation OperatorLoc,
|
||||||
bool isArrow,
|
bool isArrow,
|
||||||
SourceLocation DestroyedTypeLoc,
|
NestedNameSpecifier *Qualifier,
|
||||||
QualType DestroyedType,
|
SourceRange QualifierRange,
|
||||||
NestedNameSpecifier *Qualifier,
|
TypeSourceInfo *ScopeType,
|
||||||
SourceRange QualifierRange) {
|
SourceLocation CCLoc,
|
||||||
CXXScopeSpec SS;
|
TypeSourceInfo *DestroyedType);
|
||||||
if (Qualifier) {
|
|
||||||
SS.setRange(QualifierRange);
|
|
||||||
SS.setScopeRep(Qualifier);
|
|
||||||
}
|
|
||||||
|
|
||||||
QualType BaseType = ((Expr*) Base.get())->getType();
|
|
||||||
|
|
||||||
DeclarationName Name
|
|
||||||
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
|
|
||||||
SemaRef.Context.getCanonicalType(DestroyedType));
|
|
||||||
|
|
||||||
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
|
|
||||||
OperatorLoc, isArrow,
|
|
||||||
SS, /*FIXME: FirstQualifier*/ 0,
|
|
||||||
Name, DestroyedTypeLoc,
|
|
||||||
/*TemplateArgs*/ 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// \brief Build a new unary operator expression.
|
/// \brief Build a new unary operator expression.
|
||||||
///
|
///
|
||||||
|
@ -4694,27 +4677,35 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
|
||||||
if (E->getQualifier() && !Qualifier)
|
if (E->getQualifier() && !Qualifier)
|
||||||
return SemaRef.ExprError();
|
return SemaRef.ExprError();
|
||||||
|
|
||||||
QualType DestroyedType;
|
// FIXME: Object type!
|
||||||
{
|
TypeSourceInfo *DestroyedTypeInfo
|
||||||
TemporaryBase Rebase(*this, E->getDestroyedTypeLoc(), DeclarationName());
|
= getDerived().TransformType(E->getDestroyedTypeInfo());
|
||||||
DestroyedType = getDerived().TransformType(E->getDestroyedType());
|
if (!DestroyedTypeInfo)
|
||||||
if (DestroyedType.isNull())
|
return SemaRef.ExprError();
|
||||||
|
|
||||||
|
// FIXME: Object type!
|
||||||
|
TypeSourceInfo *ScopeTypeInfo = 0;
|
||||||
|
if (E->getScopeTypeInfo()) {
|
||||||
|
ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
|
||||||
|
if (!ScopeTypeInfo)
|
||||||
return SemaRef.ExprError();
|
return SemaRef.ExprError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!getDerived().AlwaysRebuild() &&
|
if (!getDerived().AlwaysRebuild() &&
|
||||||
Base.get() == E->getBase() &&
|
Base.get() == E->getBase() &&
|
||||||
Qualifier == E->getQualifier() &&
|
Qualifier == E->getQualifier() &&
|
||||||
DestroyedType == E->getDestroyedType())
|
ScopeTypeInfo == E->getScopeTypeInfo() &&
|
||||||
|
DestroyedTypeInfo == E->getDestroyedTypeInfo())
|
||||||
return SemaRef.Owned(E->Retain());
|
return SemaRef.Owned(E->Retain());
|
||||||
|
|
||||||
return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
|
return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
|
||||||
E->getOperatorLoc(),
|
E->getOperatorLoc(),
|
||||||
E->isArrow(),
|
E->isArrow(),
|
||||||
E->getDestroyedTypeLoc(),
|
|
||||||
DestroyedType,
|
|
||||||
Qualifier,
|
Qualifier,
|
||||||
E->getQualifierRange());
|
E->getQualifierRange(),
|
||||||
|
ScopeTypeInfo,
|
||||||
|
E->getColonColonLoc(),
|
||||||
|
DestroyedTypeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Derived>
|
template<typename Derived>
|
||||||
|
@ -5755,6 +5746,50 @@ TreeTransform<Derived>::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op,
|
||||||
return move(Result);
|
return move(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
Sema::OwningExprResult
|
||||||
|
TreeTransform<Derived>::RebuildCXXPseudoDestructorExpr(ExprArg Base,
|
||||||
|
SourceLocation OperatorLoc,
|
||||||
|
bool isArrow,
|
||||||
|
NestedNameSpecifier *Qualifier,
|
||||||
|
SourceRange QualifierRange,
|
||||||
|
TypeSourceInfo *ScopeType,
|
||||||
|
SourceLocation CCLoc,
|
||||||
|
TypeSourceInfo *DestroyedType) {
|
||||||
|
CXXScopeSpec SS;
|
||||||
|
if (Qualifier) {
|
||||||
|
SS.setRange(QualifierRange);
|
||||||
|
SS.setScopeRep(Qualifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr *BaseE = (Expr *)Base.get();
|
||||||
|
QualType BaseType = BaseE->getType();
|
||||||
|
if (BaseE->isTypeDependent() ||
|
||||||
|
(!isArrow && !BaseType->getAs<RecordType>()) ||
|
||||||
|
(isArrow && BaseType->getAs<PointerType>() &&
|
||||||
|
!BaseType->getAs<PointerType>()->getAs<RecordType>())) {
|
||||||
|
// This pseudo-destructor expression is still a pseudo-destructor.
|
||||||
|
return SemaRef.BuildPseudoDestructorExpr(move(Base), OperatorLoc,
|
||||||
|
isArrow? tok::arrow : tok::period,
|
||||||
|
SS, ScopeType, CCLoc,
|
||||||
|
DestroyedType,
|
||||||
|
/*FIXME?*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
DeclarationName Name
|
||||||
|
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
|
||||||
|
SemaRef.Context.getCanonicalType(DestroyedType->getType()));
|
||||||
|
|
||||||
|
// FIXME: the ScopeType should be tacked onto SS.
|
||||||
|
|
||||||
|
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
|
||||||
|
OperatorLoc, isArrow,
|
||||||
|
SS, /*FIXME: FirstQualifier*/ 0,
|
||||||
|
Name,
|
||||||
|
DestroyedType->getTypeLoc().getSourceRange().getBegin(),
|
||||||
|
/*TemplateArgs*/ 0);
|
||||||
|
}
|
||||||
|
|
||||||
} // end namespace clang
|
} // end namespace clang
|
||||||
|
|
||||||
#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H
|
#endif // LLVM_CLANG_SEMA_TREETRANSFORM_H
|
||||||
|
|
Loading…
Reference in New Issue