summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaExpr.cpp62
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp31
-rw-r--r--clang/lib/Sema/TreeTransform.h67
3 files changed, 140 insertions, 20 deletions
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 720217a9103..58d6a0dbac7 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -1998,7 +1998,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
Base = MaybeConvertParenListExprToParenExpr(S, move(Base));
Expr *BaseExpr = Base.takeAs<Expr>();
- assert(BaseExpr && "no record expression");
+ assert(BaseExpr && "no base expression");
// Perform default conversions.
DefaultFunctionArrayConversion(BaseExpr);
@@ -2230,6 +2230,47 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
<< MemberName << int(OpKind == tok::arrow));
}
+ // Handle pseudo-destructors (C++ [expr.pseudo]). Since anything referring
+ // into a record type was handled above, any destructor we see here is a
+ // pseudo-destructor.
+ if (MemberName.getNameKind() == DeclarationName::CXXDestructorName) {
+ // C++ [expr.pseudo]p2:
+ // The left hand side of the dot operator shall be of scalar type. The
+ // left hand side of the arrow operator shall be of pointer to scalar
+ // type.
+ if (!BaseType->isScalarType())
+ return Owned(Diag(OpLoc, diag::err_pseudo_dtor_base_not_scalar)
+ << BaseType << BaseExpr->getSourceRange());
+
+ // [...] The type designated by the pseudo-destructor-name shall be the
+ // same as the object type.
+ if (!MemberName.getCXXNameType()->isDependentType() &&
+ !Context.hasSameUnqualifiedType(BaseType, MemberName.getCXXNameType()))
+ return Owned(Diag(OpLoc, diag::err_pseudo_dtor_type_mismatch)
+ << BaseType << MemberName.getCXXNameType()
+ << BaseExpr->getSourceRange() << SourceRange(MemberLoc));
+
+ // [...] Furthermore, the two type-names in a pseudo-destructor-name of
+ // the form
+ //
+ // ::[opt] nested-name-specifier[opt] type-name :: ̃ type-name
+ //
+ // shall designate the same scalar type.
+ //
+ // FIXME: DPG can't see any way to trigger this particular clause, so it
+ // isn't checked here.
+
+ // FIXME: We've lost the precise spelling of the type by going through
+ // DeclarationName. Can we do better?
+ return Owned(new (Context) CXXPseudoDestructorExpr(Context, BaseExpr,
+ OpKind == tok::arrow,
+ OpLoc,
+ (NestedNameSpecifier *)(SS? SS->getScopeRep() : 0),
+ SS? SS->getRange() : SourceRange(),
+ MemberName.getCXXNameType(),
+ MemberLoc));
+ }
+
// Handle properties on ObjC 'Class' types.
if (OpKind == tok::period && BaseType->isObjCClassType()) {
// Also must look for a getter name which uses property syntax.
@@ -2684,6 +2725,25 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc,
DeclarationName UnqualifiedName;
if (getLangOptions().CPlusPlus) {
+ // If this is a pseudo-destructor expression, build the call immediately.
+ if (isa<CXXPseudoDestructorExpr>(Fn)) {
+ if (NumArgs > 0) {
+ // Pseudo-destructor calls should not have any arguments.
+ Diag(Fn->getLocStart(), diag::err_pseudo_dtor_call_with_args)
+ << CodeModificationHint::CreateRemoval(
+ SourceRange(Args[0]->getLocStart(),
+ Args[NumArgs-1]->getLocEnd()));
+
+ for (unsigned I = 0; I != NumArgs; ++I)
+ Args[I]->Destroy(Context);
+
+ NumArgs = 0;
+ }
+
+ return Owned(new (Context) CallExpr(Context, Fn, 0, 0, Context.VoidTy,
+ RParenLoc));
+ }
+
// Determine whether this is a dependent call inside a C++ template,
// in which case we won't do any semantic analysis now.
// FIXME: Will need to cache the results of name lookup (including ADL) in
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index c62159d001d..4d49f87a9a8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -1821,26 +1821,19 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,
if (SS && SS->isInvalid())
return ExprError();
- Expr *BaseExpr = (Expr *)Base.get();
-
- if (BaseExpr->isTypeDependent() ||
- (SS && isDependentScopeSpecifier(*SS))) {
- // FIXME: Return an unresolved ref expr.
- return ExprError();
- }
-
- TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, SS);
- if (!BaseTy) {
- Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
- << ClassName;
- return ExprError();
- }
+ QualType BaseType;
+ if (SS && isUnknownSpecialization(*SS))
+ BaseType = Context.getTypenameType((NestedNameSpecifier *)SS->getScopeRep(),
+ ClassName);
+ else {
+ TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, SS);
+ if (!BaseTy) {
+ Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
+ << ClassName;
+ return ExprError();
+ }
- QualType BaseType = GetTypeFromParser(BaseTy);
- if (!BaseType->isRecordType()) {
- Diag(ClassNameLoc, diag::err_type_in_pseudo_dtor_not_a_class_type)
- << BaseType;
- return ExprError();
+ BaseType = GetTypeFromParser(BaseTy);
}
CanQualType CanBaseType = Context.getCanonicalType(BaseType);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 2faaa44daf9..22e01ab5814 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -783,6 +783,36 @@ public:
return getSema().ActOnParenExpr(LParen, RParen, move(SubExpr));
}
+ /// \brief Build a new pseudo-destructor expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ OwningExprResult RebuildCXXPseudoDestructorExpr(ExprArg Base,
+ SourceLocation OperatorLoc,
+ bool isArrow,
+ SourceLocation DestroyedTypeLoc,
+ QualType DestroyedType,
+ NestedNameSpecifier *Qualifier,
+ SourceRange QualifierRange) {
+ CXXScopeSpec SS;
+ if (Qualifier) {
+ SS.setRange(QualifierRange);
+ SS.setScopeRep(Qualifier);
+ }
+
+ DeclarationName Name
+ = SemaRef.Context.DeclarationNames.getCXXDestructorName(
+ SemaRef.Context.getCanonicalType(DestroyedType));
+
+ return getSema().BuildMemberReferenceExpr(/*Scope=*/0, move(Base),
+ OperatorLoc,
+ isArrow? tok::arrow : tok::period,
+ DestroyedTypeLoc,
+ Name,
+ Sema::DeclPtrTy::make((Decl *)0),
+ &SS);
+ }
+
/// \brief Build a new unary operator expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -3814,6 +3844,43 @@ TreeTransform<Derived>::TransformCXXDeleteExpr(CXXDeleteExpr *E) {
template<typename Derived>
Sema::OwningExprResult
+TreeTransform<Derived>::TransformCXXPseudoDestructorExpr(
+ CXXPseudoDestructorExpr *E) {
+ OwningExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return SemaRef.ExprError();
+
+ NestedNameSpecifier *Qualifier
+ = getDerived().TransformNestedNameSpecifier(E->getQualifier(),
+ E->getQualifierRange());
+ if (E->getQualifier() && !Qualifier)
+ return SemaRef.ExprError();
+
+ QualType DestroyedType;
+ {
+ TemporaryBase Rebase(*this, E->getDestroyedTypeLoc(), DeclarationName());
+ DestroyedType = getDerived().TransformType(E->getDestroyedType());
+ if (DestroyedType.isNull())
+ return SemaRef.ExprError();
+ }
+
+ if (!getDerived().AlwaysRebuild() &&
+ Base.get() == E->getBase() &&
+ Qualifier == E->getQualifier() &&
+ DestroyedType == E->getDestroyedType())
+ return SemaRef.Owned(E->Retain());
+
+ return getDerived().RebuildCXXPseudoDestructorExpr(move(Base),
+ E->getOperatorLoc(),
+ E->isArrow(),
+ E->getDestroyedTypeLoc(),
+ DestroyedType,
+ Qualifier,
+ E->getQualifierRange());
+}
+
+template<typename Derived>
+Sema::OwningExprResult
TreeTransform<Derived>::TransformUnresolvedFunctionNameExpr(
UnresolvedFunctionNameExpr *E) {
// There is no transformation we can apply to an unresolved function name.
OpenPOWER on IntegriCloud