diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 88d7a0f6f4aa..22599f3f1e5c 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1794,7 +1794,7 @@ public: /// type checking binary operators (subroutines of CreateBuiltinBinOp). inline QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex); - inline QualType CheckPointerToMemberOperands( // C++ 5.5 + QualType CheckPointerToMemberOperands( // C++ 5.5 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isIndirect); inline QualType CheckMultiplyDivideOperands( // C99 6.5.5 Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 8ce8bfdd8baf..c12440322d0a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#include "SemaInherit.h" #include "Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclObjC.h" @@ -2703,72 +2702,6 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, return QualType(); } -inline QualType Sema::CheckPointerToMemberOperands( - Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) -{ - const char *OpSpelling = isIndirect ? "->*" : ".*"; - // C++ 5.5p2 - // The binary operator .* [p3: ->*] binds its second operand, which shall - // be of type "pointer to member of T" (where T is a completely-defined - // class type) [...] - QualType RType = rex->getType(); - const MemberPointerType *MemPtr = RType->getAsMemberPointerType(); - if (!MemPtr || MemPtr->getClass()->isIncompleteType()) { - Diag(Loc, diag::err_bad_memptr_rhs) - << OpSpelling << RType << rex->getSourceRange(); - return QualType(); - } - QualType Class(MemPtr->getClass(), 0); - - // C++ 5.5p2 - // [...] to its first operand, which shall be of class T or of a class of - // which T is an unambiguous and accessible base class. [p3: a pointer to - // such a class] - QualType LType = lex->getType(); - if (isIndirect) { - if (const PointerType *Ptr = LType->getAsPointerType()) - LType = Ptr->getPointeeType().getNonReferenceType(); - else { - Diag(Loc, diag::err_bad_memptr_lhs) - << OpSpelling << 1 << LType << lex->getSourceRange(); - return QualType(); - } - } - - if (Context.getCanonicalType(Class).getUnqualifiedType() != - Context.getCanonicalType(LType).getUnqualifiedType()) { - BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, - /*DetectVirtual=*/false); - // FIXME: Would it be useful to print full ambiguity paths, - // or is that overkill? - if (!IsDerivedFrom(LType, Class, Paths) || - Paths.isAmbiguous(Context.getCanonicalType(Class))) { - Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling - << (int)isIndirect << lex->getType() << lex->getSourceRange(); - return QualType(); - } - } - - // C++ 5.5p2 - // The result is an object or a function of the type specified by the - // second operand. - // The cv qualifiers are the union of those in the pointer and the left side, - // in accordance with 5.5p5 and 5.2.5. - // FIXME: This returns a dereferenced member function pointer as a normal - // function type. However, the only operation valid on such functions is - // calling them. There's also a GCC extension to get a function pointer to - // the thing, which is another complication, because this type - unlike the - // type that is the result of this expression - takes the class as the first - // argument. - // We probably need a "MemberFunctionClosureType" or something like that. - QualType Result = MemPtr->getPointeeType(); - if (LType.isConstQualified()) - Result.addConst(); - if (LType.isVolatileQualified()) - Result.addVolatile(); - return Result; -} - inline QualType Sema::CheckMultiplyDivideOperands( Expr *&lex, Expr *&rex, SourceLocation Loc, bool isCompAssign) { diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 748eddc5f73a..9155ec45d766 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "SemaInherit.h" #include "Sema.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ASTContext.h" @@ -883,3 +884,69 @@ Sema::OwningExprResult Sema::ActOnUnaryTypeTrait(UnaryTypeTrait OTT, QualType::getFromOpaquePtr(Ty), RParen, Context.BoolTy)); } + +QualType Sema::CheckPointerToMemberOperands( + Expr *&lex, Expr *&rex, SourceLocation Loc, bool isIndirect) +{ + const char *OpSpelling = isIndirect ? "->*" : ".*"; + // C++ 5.5p2 + // The binary operator .* [p3: ->*] binds its second operand, which shall + // be of type "pointer to member of T" (where T is a completely-defined + // class type) [...] + QualType RType = rex->getType(); + const MemberPointerType *MemPtr = RType->getAsMemberPointerType(); + if (!MemPtr || MemPtr->getClass()->isIncompleteType()) { + Diag(Loc, diag::err_bad_memptr_rhs) + << OpSpelling << RType << rex->getSourceRange(); + return QualType(); + } + QualType Class(MemPtr->getClass(), 0); + + // C++ 5.5p2 + // [...] to its first operand, which shall be of class T or of a class of + // which T is an unambiguous and accessible base class. [p3: a pointer to + // such a class] + QualType LType = lex->getType(); + if (isIndirect) { + if (const PointerType *Ptr = LType->getAsPointerType()) + LType = Ptr->getPointeeType().getNonReferenceType(); + else { + Diag(Loc, diag::err_bad_memptr_lhs) + << OpSpelling << 1 << LType << lex->getSourceRange(); + return QualType(); + } + } + + if (Context.getCanonicalType(Class).getUnqualifiedType() != + Context.getCanonicalType(LType).getUnqualifiedType()) { + BasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/false, + /*DetectVirtual=*/false); + // FIXME: Would it be useful to print full ambiguity paths, + // or is that overkill? + if (!IsDerivedFrom(LType, Class, Paths) || + Paths.isAmbiguous(Context.getCanonicalType(Class))) { + Diag(Loc, diag::err_bad_memptr_lhs) << OpSpelling + << (int)isIndirect << lex->getType() << lex->getSourceRange(); + return QualType(); + } + } + + // C++ 5.5p2 + // The result is an object or a function of the type specified by the + // second operand. + // The cv qualifiers are the union of those in the pointer and the left side, + // in accordance with 5.5p5 and 5.2.5. + // FIXME: This returns a dereferenced member function pointer as a normal + // function type. However, the only operation valid on such functions is + // calling them. There's also a GCC extension to get a function pointer to + // the thing, which is another complication, because this type - unlike the + // type that is the result of this expression - takes the class as the first + // argument. + // We probably need a "MemberFunctionClosureType" or something like that. + QualType Result = MemPtr->getPointeeType(); + if (LType.isConstQualified()) + Result.addConst(); + if (LType.isVolatileQualified()) + Result.addVolatile(); + return Result; +} diff --git a/clang/lib/Sema/SemaInherit.cpp b/clang/lib/Sema/SemaInherit.cpp index 0772bc3c1e84..fe1c96b09db1 100644 --- a/clang/lib/Sema/SemaInherit.cpp +++ b/clang/lib/Sema/SemaInherit.cpp @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#include "Sema.h" #include "SemaInherit.h" +#include "Sema.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h"