Use CXXPseudoDestructorExpr as the stored representation for dependent
expressions that look like pseudo-destructors, e.g.,
p->T::~T()
where p has dependent type.
At template instantiate time, we determine whether we actually have a
pseudo-destructor or a member access, and funnel down to the
appropriate routine in Sema.
Fixes PR6380.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97092 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index abc775e..1bc084c 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -95,6 +95,7 @@
class ObjCMethodDecl;
class ObjCPropertyDecl;
class ObjCContainerDecl;
+ class PseudoDestructorTypeStorage;
class FunctionProtoType;
class CXXBasePath;
class CXXBasePaths;
@@ -2188,20 +2189,9 @@
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType,
+ PseudoDestructorTypeStorage DestroyedType,
bool HasTrailingLParen);
-
- OwningExprResult ActOnDependentPseudoDestructorExpr(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen);
-
+
virtual OwningExprResult ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
SourceLocation OpLoc,
tok::TokenKind OpKind,
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 025f2ad..64f2ef2 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -161,7 +161,7 @@
Found.clear();
if (Step == 0 && LookupCtx)
LookupQualifiedName(Found, LookupCtx);
- else if (Step == 1 && LookInScope)
+ else if (Step == 1 && LookInScope && S)
LookupName(Found, S);
else
continue;
@@ -2441,9 +2441,9 @@
TypeSourceInfo *ScopeTypeInfo,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestructedTypeInfo,
+ PseudoDestructorTypeStorage Destructed,
bool HasTrailingLParen) {
- assert(DestructedTypeInfo && "No destructed type in pseudo-destructor expr?");
+ TypeSourceInfo *DestructedTypeInfo = Destructed.getTypeSourceInfo();
// C++ [expr.pseudo]p2:
// The left-hand side of the dot operator shall be of scalar type. The
@@ -2475,21 +2475,24 @@
// 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 = DestructedTypeInfo->getType();
- SourceLocation DestructedTypeStart
- = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
- if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
- !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
- Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
- << ObjectType << DestructedType << BaseE->getSourceRange()
- << DestructedTypeInfo->getTypeLoc().getSourceRange();
-
- // Recover by
- DestructedType = ObjectType;
- DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
- DestructedTypeStart);
+ if (DestructedTypeInfo) {
+ QualType DestructedType = DestructedTypeInfo->getType();
+ SourceLocation DestructedTypeStart
+ = DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin();
+ if (!DestructedType->isDependentType() && !ObjectType->isDependentType() &&
+ !Context.hasSameUnqualifiedType(DestructedType, ObjectType)) {
+ Diag(DestructedTypeStart, diag::err_pseudo_dtor_type_mismatch)
+ << ObjectType << DestructedType << BaseE->getSourceRange()
+ << DestructedTypeInfo->getTypeLoc().getSourceRange();
+
+ // Recover by setting the destructed type to the object type.
+ DestructedType = ObjectType;
+ DestructedTypeInfo = Context.getTrivialTypeSourceInfo(ObjectType,
+ DestructedTypeStart);
+ Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+ }
}
-
+
// C++ [expr.pseudo]p2:
// [...] Furthermore, the two type-names in a pseudo-destructor-name of the
// form
@@ -2522,148 +2525,12 @@
ScopeTypeInfo,
CCLoc,
TildeLoc,
- DestructedTypeInfo));
+ Destructed));
+
if (HasTrailingLParen)
return move(Result);
- return DiagnoseDtorReference(
- DestructedTypeInfo->getTypeLoc().getSourceRange().getBegin(),
- move(Result));
-}
-
-Sema::OwningExprResult
-Sema::ActOnDependentPseudoDestructorExpr(Scope *S,
- ExprArg Base,
- SourceLocation OpLoc,
- tok::TokenKind OpKind,
- const CXXScopeSpec &SS,
- UnqualifiedId &FirstTypeName,
- SourceLocation CCLoc,
- SourceLocation TildeLoc,
- UnqualifiedId &SecondTypeName,
- bool HasTrailingLParen) {
- Expr *BaseE = (Expr *)Base.get();
- QualType ObjectType = BaseE->getType();
- assert(ObjectType->isDependentType());
-
- // The nested-name-specifier provided by the parser, then extended
- // by the "type-name ::" in the pseudo-destructor-name, if present.
- CXXScopeSpec ExtendedSS = SS;
-
- if (FirstTypeName.getKind() == UnqualifiedId::IK_TemplateId ||
- FirstTypeName.Identifier) {
- // We have a pseudo-destructor with a "type-name ::".
- // FIXME: As a temporary hack, we go ahead and resolve this to part of
- // a nested-name-specifier.
- if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
- // Resolve the identifier to a nested-name-specifier.
- CXXScopeTy *FinalScope
- = ActOnCXXNestedNameSpecifier(S, SS,
- FirstTypeName.StartLocation,
- CCLoc,
- *FirstTypeName.Identifier,
- true,
- ObjectType.getAsOpaquePtr(),
- false);
- if (SS.getBeginLoc().isInvalid())
- ExtendedSS.setBeginLoc(FirstTypeName.StartLocation);
- ExtendedSS.setEndLoc(CCLoc);
- ExtendedSS.setScopeRep(FinalScope);
- } else {
- // Resolve the template-id to a type, and that to a
- // nested-name-specifier.
- TemplateIdAnnotation *TemplateId = FirstTypeName.TemplateId;
- ASTTemplateArgsPtr TemplateArgsPtr(*this,
- TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc);
- if (!T.isInvalid()) {
- CXXScopeTy *FinalScope
- = ActOnCXXNestedNameSpecifier(S, SS, T.get(),
- SourceRange(TemplateId->TemplateNameLoc,
- TemplateId->RAngleLoc),
- CCLoc,
- true);
- if (SS.getBeginLoc().isInvalid())
- ExtendedSS.setBeginLoc(TemplateId->TemplateNameLoc);
- ExtendedSS.setEndLoc(CCLoc);
- ExtendedSS.setScopeRep(FinalScope);
- }
- }
- }
-
- // Produce a destructor name based on the second type-name (which
- // follows the tilde).
- TypeTy *DestructedType;
- SourceLocation EndLoc;
- if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
- const CXXScopeSpec *LookupSS = &SS;
- bool isDependent = isDependentScopeSpecifier(ExtendedSS);
- if (isDependent || computeDeclContext(ExtendedSS))
- LookupSS = &ExtendedSS;
-
- DestructedType = getTypeName(*SecondTypeName.Identifier,
- SecondTypeName.StartLocation,
- S, LookupSS, true, ObjectType.getTypePtr());
- if (!DestructedType && isDependent) {
- // We didn't find our type, but that's okay: it's dependent
- // anyway.
- // FIXME: We should not be building a typename type here!
- NestedNameSpecifier *NNS = 0;
- SourceRange Range;
- if (SS.isSet()) {
- NNS = (NestedNameSpecifier *)ExtendedSS.getScopeRep();
- Range = SourceRange(ExtendedSS.getRange().getBegin(),
- SecondTypeName.StartLocation);
- } else {
- NNS = NestedNameSpecifier::Create(Context, SecondTypeName.Identifier);
- Range = SourceRange(SecondTypeName.StartLocation);
- }
-
- DestructedType = CheckTypenameType(NNS, *SecondTypeName.Identifier,
- Range).getAsOpaquePtr();
- if (!DestructedType)
- return ExprError();
- }
-
- if (!DestructedType) {
- // FIXME: Crummy diagnostic.
- Diag(SecondTypeName.StartLocation, diag::err_destructor_class_name);
- return ExprError();
- }
-
- EndLoc = SecondTypeName.EndLocation;
- } else {
- // Resolve the template-id to a type, and that to a
- // nested-name-specifier.
- TemplateIdAnnotation *TemplateId = SecondTypeName.TemplateId;
- ASTTemplateArgsPtr TemplateArgsPtr(*this,
- TemplateId->getTemplateArgs(),
- TemplateId->NumArgs);
- EndLoc = TemplateId->RAngleLoc;
- TypeResult T = ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
- TemplateId->TemplateNameLoc,
- TemplateId->LAngleLoc,
- TemplateArgsPtr,
- TemplateId->RAngleLoc);
- if (T.isInvalid() || !T.get())
- return ExprError();
-
- DestructedType = T.get();
- }
-
- // Form a (possibly fake) destructor name and let the member access
- // expression code deal with this.
- // FIXME: Don't do this! It's totally broken!
- UnqualifiedId Destructor;
- Destructor.setDestructorName(TildeLoc, DestructedType, EndLoc);
- return ActOnMemberAccessExpr(S, move(Base), OpLoc, OpKind, ExtendedSS,
- Destructor, DeclPtrTy(), HasTrailingLParen);
-
+ return DiagnoseDtorReference(Destructed.getLocation(), move(Result));
}
Sema::OwningExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, ExprArg Base,
@@ -2683,11 +2550,6 @@
"Invalid second type name in pseudo-destructor");
Expr *BaseE = (Expr *)Base.get();
- if (BaseE->isTypeDependent())
- return ActOnDependentPseudoDestructorExpr(S, move(Base), OpLoc, OpKind,
- SS, FirstTypeName, CCLoc,
- TildeLoc, SecondTypeName,
- HasTrailingLParen);
// C++ [expr.pseudo]p2:
// The left-hand side of the dot operator shall be of scalar type. The
@@ -2697,27 +2559,46 @@
if (OpKind == tok::arrow) {
if (const PointerType *Ptr = ObjectType->getAs<PointerType>()) {
ObjectType = Ptr->getPointeeType();
- } else if (!BaseE->isTypeDependent()) {
+ } else if (!ObjectType->isDependentType()) {
// 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;
}
}
+
+ // Compute the object type that we should use for name lookup purposes. Only
+ // record types and dependent types matter.
+ void *ObjectTypePtrForLookup = 0;
+ if (!SS.isSet()) {
+ ObjectTypePtrForLookup = (void *)ObjectType->getAs<RecordType>();
+ if (!ObjectTypePtrForLookup && ObjectType->isDependentType())
+ ObjectTypePtrForLookup = Context.DependentTy.getAsOpaquePtr();
+ }
// Convert the name of the type being destructed (following the ~) into a
// type (with source-location information).
QualType DestructedType;
TypeSourceInfo *DestructedTypeInfo = 0;
+ PseudoDestructorTypeStorage Destructed;
if (SecondTypeName.getKind() == UnqualifiedId::IK_Identifier) {
TypeTy *T = getTypeName(*SecondTypeName.Identifier,
SecondTypeName.StartLocation,
- S, &SS);
- if (!T) {
+ S, &SS, true, ObjectTypePtrForLookup);
+ if (!T &&
+ ((SS.isSet() && !computeDeclContext(SS, false)) ||
+ (!SS.isSet() && ObjectType->isDependentType()))) {
+ // The name of the type being destroyed is a dependent name, and we
+ // couldn't find anything useful in scope. Just store the identifier and
+ // it's location, and we'll perform (qualified) name lookup again at
+ // template instantiation time.
+ Destructed = PseudoDestructorTypeStorage(SecondTypeName.Identifier,
+ SecondTypeName.StartLocation);
+ } else if (!T) {
Diag(SecondTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
<< SecondTypeName.Identifier << ObjectType;
@@ -2748,9 +2629,12 @@
// If we've performed some kind of recovery, (re-)build the type source
// information.
- if (!DestructedTypeInfo)
- DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
+ if (!DestructedType.isNull()) {
+ if (!DestructedTypeInfo)
+ DestructedTypeInfo = Context.getTrivialTypeSourceInfo(DestructedType,
SecondTypeName.StartLocation);
+ Destructed = PseudoDestructorTypeStorage(DestructedTypeInfo);
+ }
// Convert the name of the scope type (the type prior to '::') into a type.
TypeSourceInfo *ScopeTypeInfo = 0;
@@ -2760,7 +2644,7 @@
if (FirstTypeName.getKind() == UnqualifiedId::IK_Identifier) {
TypeTy *T = getTypeName(*FirstTypeName.Identifier,
FirstTypeName.StartLocation,
- S, &SS);
+ S, &SS, false, ObjectTypePtrForLookup);
if (!T) {
Diag(FirstTypeName.StartLocation,
diag::err_pseudo_dtor_destructor_non_type)
@@ -2799,7 +2683,7 @@
return BuildPseudoDestructorExpr(move(Base), OpLoc, OpKind, SS,
ScopeTypeInfo, CCLoc, TildeLoc,
- DestructedTypeInfo, HasTrailingLParen);
+ Destructed, HasTrailingLParen);
}
CXXMemberCallExpr *Sema::BuildCXXMemberCallExpr(Expr *Exp,
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 922c041..416f480 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -884,12 +884,12 @@
OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
SourceLocation OperatorLoc,
bool isArrow,
- NestedNameSpecifier *Qualifier,
+ NestedNameSpecifier *Qualifier,
SourceRange QualifierRange,
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType);
+ PseudoDestructorTypeStorage Destroyed);
/// \brief Build a new unary operator expression.
///
@@ -4671,34 +4671,67 @@
if (Base.isInvalid())
return SemaRef.ExprError();
+ Sema::TypeTy *ObjectTypePtr = 0;
+ bool MayBePseudoDestructor = false;
+ Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),
+ E->getOperatorLoc(),
+ E->isArrow()? tok::arrow : tok::period,
+ ObjectTypePtr,
+ MayBePseudoDestructor);
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr);
NestedNameSpecifier *Qualifier
= getDerived().TransformNestedNameSpecifier(E->getQualifier(),
E->getQualifierRange(),
- true);
+ true,
+ ObjectType);
if (E->getQualifier() && !Qualifier)
return SemaRef.ExprError();
- // FIXME: Object type!
- TypeSourceInfo *DestroyedTypeInfo
- = getDerived().TransformType(E->getDestroyedTypeInfo());
- if (!DestroyedTypeInfo)
- return SemaRef.ExprError();
+ PseudoDestructorTypeStorage Destroyed;
+ if (E->getDestroyedTypeInfo()) {
+ TypeSourceInfo *DestroyedTypeInfo
+ = getDerived().TransformType(E->getDestroyedTypeInfo(), ObjectType);
+ if (!DestroyedTypeInfo)
+ return SemaRef.ExprError();
+ Destroyed = DestroyedTypeInfo;
+ } else if (ObjectType->isDependentType()) {
+ // We aren't likely to be able to resolve the identifier down to a type
+ // now anyway, so just retain the identifier.
+ Destroyed = PseudoDestructorTypeStorage(E->getDestroyedTypeIdentifier(),
+ E->getDestroyedTypeLoc());
+ } else {
+ // Look for a destructor known with the given name.
+ CXXScopeSpec SS;
+ if (Qualifier) {
+ SS.setScopeRep(Qualifier);
+ SS.setRange(E->getQualifierRange());
+ }
+
+ Sema::TypeTy *T = SemaRef.getDestructorName(E->getTildeLoc(),
+ *E->getDestroyedTypeIdentifier(),
+ E->getDestroyedTypeLoc(),
+ /*Scope=*/0,
+ SS, ObjectTypePtr,
+ false);
+ if (!T)
+ return SemaRef.ExprError();
+
+ Destroyed
+ = SemaRef.Context.getTrivialTypeSourceInfo(SemaRef.GetTypeFromParser(T),
+ E->getDestroyedTypeLoc());
+ }
- // FIXME: Object type!
TypeSourceInfo *ScopeTypeInfo = 0;
if (E->getScopeTypeInfo()) {
- ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo());
+ ScopeTypeInfo = getDerived().TransformType(E->getScopeTypeInfo(),
+ ObjectType);
if (!ScopeTypeInfo)
return SemaRef.ExprError();
}
- if (!getDerived().AlwaysRebuild() &&
- Base.get() == E->getBase() &&
- Qualifier == E->getQualifier() &&
- ScopeTypeInfo == E->getScopeTypeInfo() &&
- DestroyedTypeInfo == E->getDestroyedTypeInfo())
- return SemaRef.Owned(E->Retain());
-
return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
E->getOperatorLoc(),
E->isArrow(),
@@ -4707,7 +4740,7 @@
ScopeTypeInfo,
E->getColonColonLoc(),
E->getTildeLoc(),
- DestroyedTypeInfo);
+ Destroyed);
}
template<typename Derived>
@@ -5758,7 +5791,7 @@
TypeSourceInfo *ScopeType,
SourceLocation CCLoc,
SourceLocation TildeLoc,
- TypeSourceInfo *DestroyedType) {
+ PseudoDestructorTypeStorage Destroyed) {
CXXScopeSpec SS;
if (Qualifier) {
SS.setRange(QualifierRange);
@@ -5767,18 +5800,19 @@
Expr *BaseE = (Expr *)Base.get();
QualType BaseType = BaseE->getType();
- if (BaseE->isTypeDependent() ||
+ if (BaseE->isTypeDependent() || Destroyed.getIdentifier() ||
(!isArrow && !BaseType->getAs<RecordType>()) ||
(isArrow && BaseType->getAs<PointerType>() &&
- !BaseType->getAs<PointerType>()->getAs<RecordType>())) {
+ !BaseType->getAs<PointerType>()->getPointeeType()->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, TildeLoc,
- DestroyedType,
+ Destroyed,
/*FIXME?*/true);
}
+ TypeSourceInfo *DestroyedType = Destroyed.getTypeSourceInfo();
DeclarationName Name
= SemaRef.Context.DeclarationNames.getCXXDestructorName(
SemaRef.Context.getCanonicalType(DestroyedType->getType()));
@@ -5788,8 +5822,7 @@
return getSema().BuildMemberReferenceExpr(move(Base), BaseType,
OperatorLoc, isArrow,
SS, /*FIXME: FirstQualifier*/ 0,
- Name,
- DestroyedType->getTypeLoc().getSourceRange().getBegin(),
+ Name, Destroyed.getLocation(),
/*TemplateArgs*/ 0);
}