[cfe-commits] r63983 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/StmtVisitor.h include/clang/Basic/DiagnosticSemaKinds.def lib/AST/Expr.cpp lib/Parse/ParseExpr.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaInherit.h lib/Sema/SemaLookup.cpp test/SemaCXX/member-pointer.cpp www/cxx_status.html

Sebastian Redl sebastian.redl at getdesigned.at
Fri Feb 6 16:15:41 PST 2009


Author: cornedbee
Date: Fri Feb  6 18:15:38 2009
New Revision: 63983

URL: http://llvm.org/viewvc/llvm-project?rev=63983&view=rev
Log:
Implement dereferencing of pointers-to-member.

Modified:
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/StmtVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaInherit.h
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/SemaCXX/member-pointer.cpp
    cfe/trunk/www/cxx_status.html

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Fri Feb  6 18:15:38 2009
@@ -1085,6 +1085,7 @@
   enum Opcode {
     // Operators listed in order of precedence.
     // Note that additions to this should also update the StmtVisitor class.
+    PtrMemD, PtrMemI, // [C++ 5.5] Pointer-to-member operators.
     Mul, Div, Rem,    // [C99 6.5.5] Multiplicative operators.
     Add, Sub,         // [C99 6.5.6] Additive operators.
     Shl, Shr,         // [C99 6.5.7] Bitwise shift operators.

Modified: cfe/trunk/include/clang/AST/StmtVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtVisitor.h?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtVisitor.h (original)
+++ cfe/trunk/include/clang/AST/StmtVisitor.h Fri Feb  6 18:15:38 2009
@@ -35,6 +35,8 @@
     if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
       switch (BinOp->getOpcode()) {
       default: assert(0 && "Unknown binary operator!");
+      case BinaryOperator::PtrMemD:   DISPATCH(BinPtrMemD,   BinaryOperator);
+      case BinaryOperator::PtrMemI:   DISPATCH(BinPtrMemI,   BinaryOperator);
       case BinaryOperator::Mul:       DISPATCH(BinMul,       BinaryOperator);
       case BinaryOperator::Div:       DISPATCH(BinDiv,       BinaryOperator);
       case BinaryOperator::Rem:       DISPATCH(BinRem,       BinaryOperator);
@@ -95,7 +97,7 @@
       case UnaryOperator::Imag:         DISPATCH(UnaryImag,      UnaryOperator);
       case UnaryOperator::Extension:    DISPATCH(UnaryExtension, UnaryOperator);
       case UnaryOperator::OffsetOf:     DISPATCH(UnaryOffsetOf,  UnaryOperator);
-      }          
+      }
     }
     
     // Top switch stmt: dispatch to VisitFooStmt for each FooStmt.
@@ -119,6 +121,7 @@
   RetTy VisitBin ## NAME(BinaryOperator *S) { \
     DISPATCH(BinaryOperator, BinaryOperator); \
   }
+  BINOP_FALLBACK(PtrMemD)                    BINOP_FALLBACK(PtrMemI)
   BINOP_FALLBACK(Mul)   BINOP_FALLBACK(Div)  BINOP_FALLBACK(Rem)
   BINOP_FALLBACK(Add)   BINOP_FALLBACK(Sub)  BINOP_FALLBACK(Shl)
   BINOP_FALLBACK(Shr)

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.def Fri Feb  6 18:15:38 2009
@@ -863,6 +863,12 @@
      "exception declarator cannot be qualified")
 DIAG(err_early_catch_all, ERROR,
      "catch-all handler must come last")
+DIAG(err_bad_memptr_rhs, ERROR,
+     "right hand operand to %0 must be a pointer to member of a complete class "
+     "but is %1")
+DIAG(err_bad_memptr_lhs, ERROR,
+     "left hand operand to ->* must be a %select{|pointer to }0class "
+     "compatible with the right hand operand, but is %1")
 
 DIAG(err_invalid_use_of_function_type, ERROR,
      "a function type is not allowed here")

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Fri Feb  6 18:15:38 2009
@@ -496,6 +496,12 @@
         BinOp->getOpcode() == BinaryOperator::Comma)
       return BinOp->getRHS()->isLvalue(Ctx);
 
+    // C++ [expr.mptr.oper]p6
+    if ((BinOp->getOpcode() == BinaryOperator::PtrMemD ||
+         BinOp->getOpcode() == BinaryOperator::PtrMemI) &&
+        !BinOp->getType()->isFunctionType())
+      return BinOp->getLHS()->isLvalue(Ctx);
+
     if (!BinOp->isAssignmentOp())
       return LV_InvalidExpression;
 

Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Feb  6 18:15:38 2009
@@ -33,20 +33,21 @@
 /// productions.  Low precedences numbers bind more weakly than high numbers.
 namespace prec {
   enum Level {
-    Unknown        = 0,    // Not binary operator.
-    Comma          = 1,    // ,
-    Assignment     = 2,    // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
-    Conditional    = 3,    // ?
-    LogicalOr      = 4,    // ||
-    LogicalAnd     = 5,    // &&
-    InclusiveOr    = 6,    // |
-    ExclusiveOr    = 7,    // ^
-    And            = 8,    // &
-    Equality       = 9,    // ==, !=
-    Relational     = 10,   //  >=, <=, >, <
-    Shift          = 11,   // <<, >>
-    Additive       = 12,   // -, +
-    Multiplicative = 13    // *, /, %
+    Unknown         = 0,    // Not binary operator.
+    Comma           = 1,    // ,
+    Assignment      = 2,    // =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
+    Conditional     = 3,    // ?
+    LogicalOr       = 4,    // ||
+    LogicalAnd      = 5,    // &&
+    InclusiveOr     = 6,    // |
+    ExclusiveOr     = 7,    // ^
+    And             = 8,    // &
+    Equality        = 9,    // ==, !=
+    Relational      = 10,   //  >=, <=, >, <
+    Shift           = 11,   // <<, >>
+    Additive        = 12,   // -, +
+    Multiplicative  = 13,   // *, /, %
+    PointerToMember = 14    // .*, ->*
   };
 }
 
@@ -88,6 +89,8 @@
   case tok::percent:
   case tok::slash:
   case tok::star:                 return prec::Multiplicative;
+  case tok::periodstar:
+  case tok::arrowstar:            return prec::PointerToMember;
   }
 }
 
@@ -104,7 +107,13 @@
 /// consistency, we parse the LHS as a conditional-expression, then check for
 /// l-value-ness in semantic analysis stages.
 ///
+///       pm-expression: [C++ 5.5]
+///         cast-expression
+///         pm-expression '.*' cast-expression
+///         pm-expression '->*' cast-expression
+///
 ///       multiplicative-expression: [C99 6.5.5]
+///     Note: in C++, apply pm-expression instead of cast-expression
 ///         cast-expression
 ///         multiplicative-expression '*' cast-expression
 ///         multiplicative-expression '/' cast-expression
@@ -270,7 +279,7 @@
     // Consume the operator, saving the operator token for error reporting.
     Token OpToken = Tok;
     ConsumeToken();
-    
+
     // Special case handling for the ternary operator.
     OwningExprResult TernaryMiddle(Actions, true);
     if (NextTokPrec == prec::Conditional) {

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Feb  6 18:15:38 2009
@@ -1788,16 +1788,18 @@
   bool PerformImplicitConversion(Expr *&From, QualType ToType,
                                  const StandardConversionSequence& SCS,
                                  const char *Flavor);
-  
+
   /// the following "Check" methods will return a valid/converted QualType
   /// or a null QualType (indicating an error diagnostic was issued).
-    
-  /// type checking binary operators (subroutines of ActOnBinOp).
+
+  /// type checking binary operators (subroutines of CreateBuiltinBinOp).
   inline QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex);
+  inline 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); 
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckRemainderOperands( // C99 6.5.5
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); 
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckAdditionOperands( // C99 6.5.6
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckSubtractionOperands( // C99 6.5.6
@@ -1807,7 +1809,7 @@
   inline QualType CheckCompareOperands( // C99 6.5.8/9
     Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isRelational);
   inline QualType CheckBitwiseOperands( // C99 6.5.[10...12]
-    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); 
+    Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false);
   inline QualType CheckLogicalOperands( // C99 6.5.[13,14]
     Expr *&lex, Expr *&rex, SourceLocation OpLoc);
   // CheckAssignmentOperands is used for both simple and compound assignment.

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Feb  6 18:15:38 2009
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "SemaInherit.h"
 #include "Sema.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclObjC.h"
@@ -2701,7 +2702,73 @@
     << lex->getType() << rex->getType()
     << lex->getSourceRange() << rex->getSourceRange();
   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)
+        << 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)
+        << (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) 
@@ -3535,6 +3602,8 @@
   BinaryOperator::Opcode Opc;
   switch (Kind) {
   default: assert(0 && "Unknown binop!");
+  case tok::periodstar:           Opc = BinaryOperator::PtrMemD; break;
+  case tok::arrowstar:            Opc = BinaryOperator::PtrMemI; break;
   case tok::star:                 Opc = BinaryOperator::Mul; break;
   case tok::slash:                Opc = BinaryOperator::Div; break;
   case tok::percent:              Opc = BinaryOperator::Rem; break;
@@ -3605,7 +3674,12 @@
   case BinaryOperator::Assign:
     ResultTy = CheckAssignmentOperands(lhs, rhs, OpLoc, QualType());
     break;
-  case BinaryOperator::Mul: 
+  case BinaryOperator::PtrMemD:
+  case BinaryOperator::PtrMemI:
+    ResultTy = CheckPointerToMemberOperands(lhs, rhs, OpLoc,
+                                            Opc == BinaryOperator::PtrMemI);
+    break;
+  case BinaryOperator::Mul:
   case BinaryOperator::Div:
     ResultTy = CheckMultiplyDivideOperands(lhs, rhs, OpLoc);
     break;
@@ -3618,7 +3692,7 @@
   case BinaryOperator::Sub:
     ResultTy = CheckSubtractionOperands(lhs, rhs, OpLoc);
     break;
-  case BinaryOperator::Shl: 
+  case BinaryOperator::Shl:
   case BinaryOperator::Shr:
     ResultTy = CheckShiftOperands(lhs, rhs, OpLoc);
     break;
@@ -3707,11 +3781,11 @@
                                               Context.DependentTy,
                                               Context.DependentTy, TokLoc));
     else
-      return Owned(new (Context) BinaryOperator(lhs, rhs, Opc, Context.DependentTy,
-                                                TokLoc));
+      return Owned(new (Context) BinaryOperator(lhs, rhs, Opc,
+                                                Context.DependentTy, TokLoc));
   }
 
-  if (getLangOptions().CPlusPlus &&
+  if (getLangOptions().CPlusPlus && Opc != BinaryOperator::PtrMemD &&
       (lhs->getType()->isRecordType() || lhs->getType()->isEnumeralType() ||
        rhs->getType()->isRecordType() || rhs->getType()->isEnumeralType())) {
     // If this is one of the assignment operators, we only perform
@@ -3724,6 +3798,8 @@
 
     // Determine which overloaded operator we're dealing with.
     static const OverloadedOperatorKind OverOps[] = {
+      // Overloading .* is not possible.
+      static_cast<OverloadedOperatorKind>(0), OO_ArrowStar,
       OO_Star, OO_Slash, OO_Percent,
       OO_Plus, OO_Minus,
       OO_LessLess, OO_GreaterGreater,

Modified: cfe/trunk/lib/Sema/SemaInherit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInherit.h?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaInherit.h (original)
+++ cfe/trunk/lib/Sema/SemaInherit.h Fri Feb  6 18:15:38 2009
@@ -16,6 +16,7 @@
 #ifndef LLVM_CLANG_SEMA_INHERIT_H
 #define LLVM_CLANG_SEMA_INHERIT_H
 
+#include "Sema.h"
 #include "clang/AST/DeclarationName.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/Type.h"
@@ -25,7 +26,6 @@
 #include <map>
 
 namespace clang {
-  class Sema;
   class CXXBaseSpecifier;
   class CXXRecordType;
 

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Fri Feb  6 18:15:38 2009
@@ -610,8 +610,8 @@
         // using-directives later.
         for (OutOfLineCtx = Ctx; OutOfLineCtx && !OutOfLineCtx->isFileContext();
              OutOfLineCtx = OutOfLineCtx->getParent()) {
-          if (R = LookupQualifiedName(OutOfLineCtx, Name, NameKind,
-                                      RedeclarationOnly))
+          if ((R = LookupQualifiedName(OutOfLineCtx, Name, NameKind,
+                                      RedeclarationOnly)))
             return std::make_pair(true, R);
         }
       }
@@ -638,7 +638,7 @@
   // context as well as walking through the scopes.
 
   LookupResultsTy LookupResults;
-  assert(!OutOfLineCtx || OutOfLineCtx->isFileContext() &&
+  assert((!OutOfLineCtx || OutOfLineCtx->isFileContext()) &&
          "We should have been looking only at file context here already.");
   bool LookedInCtx = false;
   LookupResult Result;

Modified: cfe/trunk/test/SemaCXX/member-pointer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/member-pointer.cpp?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Fri Feb  6 18:15:38 2009
@@ -79,3 +79,28 @@
 
   void (HasMembers::*pmd)() = &HasMembers::d;
 }
+
+void h() {
+  HasMembers hm, *phm = &hm;
+
+  int HasMembers::*pi = &HasMembers::i;
+  hm.*pi = 0;
+  int i = phm->*pi;
+  (void)&(hm.*pi);
+  (void)&(phm->*pi);
+  (void)&((&hm)->*pi); // expected-error {{address expression must be an lvalue or a function designator}}
+
+  void (HasMembers::*pf)() = &HasMembers::f;
+  (hm.*pf)();
+  (phm->*pf)();
+}
+
+struct OverloadsPtrMem
+{
+  int operator ->*(const char *);
+};
+
+void i() {
+  OverloadsPtrMem m;
+  int foo = m->*"Awesome!";
+}

Modified: cfe/trunk/www/cxx_status.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/cxx_status.html?rev=63983&r1=63982&r2=63983&view=diff

==============================================================================
--- cfe/trunk/www/cxx_status.html (original)
+++ cfe/trunk/www/cxx_status.html Fri Feb  6 18:15:38 2009
@@ -698,11 +698,11 @@
 </tr>
 <tr>
   <td>  5.5 [expr.mptr.oper]</td>
-  <td class="broken"></td>
-  <td class="broken"></td>
-  <td class="broken"></td>
-  <td></td>
+  <td class="complete" align="center">&#x2713;</td>
+  <td class="advanced"></td>
+  <td class="advanced"></td>
   <td></td>
+  <td>Dereferenced member function pointers have the wrong type.</td>
 </tr>
 <tr>
   <td>  5.6 [expr.mul]</td>





More information about the cfe-commits mailing list