[cfe-commits] r63655 - in /cfe/trunk: Driver/PrintParserCallbacks.cpp include/clang/Parse/Action.h include/clang/Parse/Parser.h lib/Parse/ParseExpr.cpp lib/Parse/ParseExprCXX.cpp lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp test/SemaCXX/member-pointer.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Tue Feb 3 12:19:36 PST 2009


Author: cornedbee
Date: Tue Feb  3 14:19:35 2009
New Revision: 63655

URL: http://llvm.org/viewvc/llvm-project?rev=63655&view=rev
Log:
Allow taking the address of data members, resulting in a member pointer.
Pointers to functions don't work yet, and pointers to overloaded functions even less. Also, far too much illegal code is accepted.

Modified:
    cfe/trunk/Driver/PrintParserCallbacks.cpp
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/Parse/ParseExpr.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprCXX.cpp
    cfe/trunk/test/SemaCXX/member-pointer.cpp

Modified: cfe/trunk/Driver/PrintParserCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/PrintParserCallbacks.cpp?rev=63655&r1=63654&r2=63655&view=diff

==============================================================================
--- cfe/trunk/Driver/PrintParserCallbacks.cpp (original)
+++ cfe/trunk/Driver/PrintParserCallbacks.cpp Tue Feb  3 14:19:35 2009
@@ -447,7 +447,8 @@
     virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
                                                  IdentifierInfo &II,
                                                  bool HasTrailingLParen,
-                                                 const CXXScopeSpec *SS) {
+                                                 const CXXScopeSpec *SS,
+                                                 bool isAddressOfOperand) {
       llvm::cout << __FUNCTION__ << "\n";
       return ExprEmpty();
     }
@@ -455,7 +456,8 @@
     virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
                                Scope *S, SourceLocation OperatorLoc,
                                OverloadedOperatorKind Op,
-                               bool HasTrailingLParen, const CXXScopeSpec &SS) {
+                               bool HasTrailingLParen, const CXXScopeSpec &SS,
+                               bool isAddressOfOperand) {
       llvm::cout << __FUNCTION__ << "\n";
       return ExprEmpty();
     }
@@ -463,7 +465,7 @@
     virtual OwningExprResult ActOnCXXConversionFunctionExpr(
                                Scope *S, SourceLocation OperatorLoc,
                                TypeTy *Type, bool HasTrailingLParen,
-                               const CXXScopeSpec &SS) {
+                               const CXXScopeSpec &SS,bool isAddressOfOperand) {
       llvm::cout << __FUNCTION__ << "\n";
       return ExprEmpty();
     }

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=63655&r1=63654&r2=63655&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Feb  3 14:19:35 2009
@@ -551,7 +551,8 @@
   virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
                                                IdentifierInfo &II,
                                                bool HasTrailingLParen,
-                                               const CXXScopeSpec *SS = 0) {
+                                               const CXXScopeSpec *SS = 0,
+                                               bool isAddressOfOperand = false){
     return ExprEmpty();
   }
 
@@ -563,7 +564,8 @@
   virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(
                              Scope *S, SourceLocation OperatorLoc,
                              OverloadedOperatorKind Op,
-                             bool HasTrailingLParen, const CXXScopeSpec &SS) {
+                             bool HasTrailingLParen, const CXXScopeSpec &SS,
+                             bool isAddressOfOperand = false) {
     return ExprEmpty();
   }
 
@@ -575,7 +577,8 @@
   virtual OwningExprResult ActOnCXXConversionFunctionExpr(
                              Scope *S, SourceLocation OperatorLoc,
                              TypeTy *Type, bool HasTrailingLParen,
-                             const CXXScopeSpec &SS) {
+                             const CXXScopeSpec &SS,
+                             bool isAddressOfOperand = false) {
     return ExprEmpty();
   }
 

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=63655&r1=63654&r2=63655&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Feb  3 14:19:35 2009
@@ -572,7 +572,8 @@
 
   OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS,
                                               unsigned MinPrec);
-  OwningExprResult ParseCastExpression(bool isUnaryExpression);
+  OwningExprResult ParseCastExpression(bool isUnaryExpression,
+                                       bool isAddressOfOperand = false);
   OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS);
   OwningExprResult ParseSizeofAlignofExpression();
   OwningExprResult ParseBuiltinPrimaryExpression();
@@ -609,7 +610,7 @@
 
   //===--------------------------------------------------------------------===//
   // C++ Expressions
-  OwningExprResult ParseCXXIdExpression();
+  OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false);
 
   /// ParseOptionalCXXScopeSpecifier - Parse global scope or
   /// nested-name-specifier if present.  Returns true if a nested-name-specifier

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Tue Feb  3 14:19:35 2009
@@ -345,7 +345,9 @@
 }
 
 /// ParseCastExpression - Parse a cast-expression, or, if isUnaryExpression is
-/// true, parse a unary-expression.
+/// true, parse a unary-expression. isAddressOfOperand exists because an
+/// id-expression that is the operand of address-of gets special treatment
+/// due to member pointers.
 ///
 ///       cast-expression: [C99 6.5.4]
 ///         unary-expression
@@ -451,7 +453,8 @@
 /// [GNU] binary-type-trait:
 ///                   '__is_base_of'                          [TODO]
 ///
-Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
+Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression,
+                                                     bool isAddressOfOperand) {
   OwningExprResult Res(Actions);
   tok::TokenKind SavedKind = Tok.getKind();
   
@@ -522,7 +525,7 @@
     if (getLang().CPlusPlus) {
       // If TryAnnotateTypeOrScopeToken annotates the token, tail recurse.
       if (TryAnnotateTypeOrScopeToken())
-        return ParseCastExpression(isUnaryExpression);
+        return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
     }
 
     // Consume the identifier so that we can see if it is followed by a '('.
@@ -570,7 +573,15 @@
       Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move_arg(Res));
     return move(Res);
   }
-  case tok::amp:           // unary-expression: '&' cast-expression
+  case tok::amp: {         // unary-expression: '&' cast-expression
+    // Special treatment because of member pointers
+    SourceLocation SavedLoc = ConsumeToken();
+    Res = ParseCastExpression(false, true);
+    if (!Res.isInvalid())
+      Res = Actions.ActOnUnaryOp(CurScope, SavedLoc, SavedKind, move_arg(Res));
+    return move(Res);
+  }
+
   case tok::star:          // unary-expression: '*' cast-expression
   case tok::plus:          // unary-expression: '+' cast-expression
   case tok::minus:         // unary-expression: '-' cast-expression
@@ -662,15 +673,15 @@
   case tok::annot_cxxscope: // [C++] id-expression: qualified-id
   case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id
                          //                      template-id
-    Res = ParseCXXIdExpression();
+    Res = ParseCXXIdExpression(isAddressOfOperand);
     return ParsePostfixExpressionSuffix(move(Res));
 
   case tok::coloncolon: {
     // ::foo::bar -> global qualified name etc.   If TryAnnotateTypeOrScopeToken
     // annotates the token, tail recurse.
     if (TryAnnotateTypeOrScopeToken())
-      return ParseCastExpression(isUnaryExpression);
-    
+      return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
+
     // ::new -> [C++] new-expression
     // ::delete -> [C++] delete-expression
     SourceLocation CCLoc = ConsumeToken();

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Tue Feb  3 14:19:35 2009
@@ -131,7 +131,12 @@
 /// That way Sema can handle and report similar errors for namespaces and the
 /// global scope.
 ///
-Parser::OwningExprResult Parser::ParseCXXIdExpression() {
+/// The isAddressOfOperand parameter indicates that this id-expression is a
+/// direct operand of the address-of operator. This is, besides member contexts,
+/// the only place where a qualified-id naming a non-static class member may
+/// appear.
+///
+Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
   // qualified-id:
   //   '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
   //   '::' unqualified-id
@@ -154,18 +159,20 @@
     // Consume the identifier so that we can see if it is followed by a '('.
     IdentifierInfo &II = *Tok.getIdentifierInfo();
     SourceLocation L = ConsumeToken();
-    return Actions.ActOnIdentifierExpr(CurScope, L, II,
-                                       Tok.is(tok::l_paren), &SS);
+    return Actions.ActOnIdentifierExpr(CurScope, L, II, Tok.is(tok::l_paren),
+                                       &SS, isAddressOfOperand);
   }
 
   case tok::kw_operator: {
     SourceLocation OperatorLoc = Tok.getLocation();
     if (OverloadedOperatorKind Op = TryParseOperatorFunctionId())
       return Actions.ActOnCXXOperatorFunctionIdExpr(
-                   CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS);
+                       CurScope, OperatorLoc, Op, Tok.is(tok::l_paren), SS,
+                       isAddressOfOperand);
     if (TypeTy *Type = ParseConversionFunctionId())
       return Actions.ActOnCXXConversionFunctionExpr(CurScope, OperatorLoc, Type,
-                                                    Tok.is(tok::l_paren), SS);
+                                                    Tok.is(tok::l_paren), SS,
+                                                    isAddressOfOperand);
 
     // We already complained about a bad conversion-function-id,
     // above.

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Feb  3 14:19:35 2009
@@ -1030,17 +1030,20 @@
   virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
                                                IdentifierInfo &II,
                                                bool HasTrailingLParen,
-                                               const CXXScopeSpec *SS = 0);
+                                               const CXXScopeSpec *SS = 0,
+                                               bool isAddressOfOperand = false);
   virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr(Scope *S,
                                                     SourceLocation OperatorLoc,
                                                     OverloadedOperatorKind Op,
                                                     bool HasTrailingLParen,
-                                                    const CXXScopeSpec &SS);
+                                                    const CXXScopeSpec &SS,
+                                                    bool isAddressOfOperand);
   virtual OwningExprResult ActOnCXXConversionFunctionExpr(Scope *S,
                                                     SourceLocation OperatorLoc,
                                                     TypeTy *Ty,
                                                     bool HasTrailingLParen,
-                                                    const CXXScopeSpec &SS);
+                                                    const CXXScopeSpec &SS,
+                                                    bool isAddressOfOperand);
   DeclRefExpr *BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
                                 bool TypeDependent, bool ValueDependent,
                                 const CXXScopeSpec *SS = 0);
@@ -1053,7 +1056,8 @@
                                             DeclarationName Name,
                                             bool HasTrailingLParen,
                                             const CXXScopeSpec *SS,
-                                            bool ForceResolution = false);
+                                            bool ForceResolution = false,
+                                            bool isAddressOfOperand = false);
 
   virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc,
                                                tok::TokenKind Kind);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Feb  3 14:19:35 2009
@@ -363,16 +363,19 @@
 Sema::OwningExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
                                                  IdentifierInfo &II,
                                                  bool HasTrailingLParen,
-                                                 const CXXScopeSpec *SS) {
-  return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS);
+                                                 const CXXScopeSpec *SS,
+                                                 bool isAddressOfOperand) {
+  return ActOnDeclarationNameExpr(S, Loc, &II, HasTrailingLParen, SS,
+                                  /*ForceResolution*/false, isAddressOfOperand);
 }
 
 /// BuildDeclRefExpr - Build either a DeclRefExpr or a
 /// QualifiedDeclRefExpr based on whether or not SS is a
 /// nested-name-specifier.
-DeclRefExpr *Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
-                                    bool TypeDependent, bool ValueDependent,
-                                    const CXXScopeSpec *SS) {
+DeclRefExpr *
+Sema::BuildDeclRefExpr(NamedDecl *D, QualType Ty, SourceLocation Loc,
+                       bool TypeDependent, bool ValueDependent,
+                       const CXXScopeSpec *SS) {
   if (SS && !SS->isEmpty())
     return new (Context) QualifiedDeclRefExpr(D, Ty, Loc, TypeDependent, 
                        ValueDependent, SS->getRange().getBegin());
@@ -535,10 +538,16 @@
 /// If ForceResolution is true, then we will attempt to resolve the
 /// name even if it looks like a dependent name. This option is off by
 /// default.
+///
+/// isAddressOfOperand means that this expression is the direct operand
+/// of an address-of operator. This matters because this is the only
+/// situation where a qualified name referencing a non-static member may
+/// appear outside a member function of this class.
 Sema::OwningExprResult
 Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
                                DeclarationName Name, bool HasTrailingLParen,
-                               const CXXScopeSpec *SS, bool ForceResolution) {
+                               const CXXScopeSpec *SS, bool ForceResolution,
+                               bool isAddressOfOperand) {
   if (S->getTemplateParamParent() && Name.getAsIdentifierInfo() &&
       HasTrailingLParen && !SS && !ForceResolution) {
     // We've seen something of the form
@@ -554,11 +563,11 @@
   }
 
   // Could be enum-constant, value decl, instance variable, etc.
-  Decl *D = 0;
   if (SS && SS->isInvalid())
     return ExprError();
   LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName);
 
+  Decl *D = 0;
   if (Lookup.isAmbiguous()) {
     DiagnoseAmbiguousLookup(Lookup, Name, Loc,
                             SS && SS->isSet() ? SS->getRange()
@@ -618,6 +627,41 @@
     }
   }
 
+  // If this is an expression of the form &Class::member, don't build an
+  // implicit member ref, because we want a pointer to the member in general,
+  // not any specific instance's member.
+  if (isAddressOfOperand && SS && !SS->isEmpty() && !HasTrailingLParen) {
+    NamedDecl *ND = dyn_cast<NamedDecl>(D);
+    DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
+    if (ND && isa<CXXRecordDecl>(DC)) {
+      QualType DType;
+      if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) {
+        DType = FD->getType().getNonReferenceType();
+      } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
+        DType = Method->getType();
+      } else if (isa<OverloadedFunctionDecl>(D)) {
+        DType = Context.OverloadTy;
+      }
+      // Could be an inner type. That's diagnosed below, so ignore it here.
+      if (!DType.isNull()) {
+        // The pointer is type- and value-dependent if it points into something
+        // dependent.
+        bool Dependent = false;
+        for (; DC; DC = DC->getParent()) {
+          // FIXME: could stop early at namespace scope.
+          if (DC->isRecord()) {
+            CXXRecordDecl *Record = cast<CXXRecordDecl>(DC);
+            if (Context.getTypeDeclType(Record)->isDependentType()) {
+              Dependent = true;
+              break;
+            }
+          }
+        }
+        return Owned(BuildDeclRefExpr(ND, DType, Loc, Dependent, Dependent,SS));
+      }
+    }
+  }
+
   // We may have found a field within an anonymous union or struct
   // (C++ [class.union]).
   if (FieldDecl *FD = dyn_cast<FieldDecl>(D))
@@ -3428,6 +3472,14 @@
       return Context.OverloadTy;
     } else if (isa<FieldDecl>(dcl)) {
       // Okay: we can take the address of a field.
+      // Could be a pointer to member, though, if there is an explicit
+      // scope qualifier for the class.
+      if (isa<QualifiedDeclRefExpr>(op)) {
+        DeclContext *Ctx = dcl->getDeclContext();
+        if (Ctx && Ctx->isRecord())
+          return Context.getMemberPointerType(op->getType(),
+                Context.getTypeDeclType(cast<RecordDecl>(Ctx)).getTypePtr());
+      }
     } else if (isa<FunctionDecl>(dcl)) {
       // Okay: we can take the address of a function.
     }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Feb  3 14:19:35 2009
@@ -28,13 +28,14 @@
 Sema::OwningExprResult
 Sema::ActOnCXXConversionFunctionExpr(Scope *S, SourceLocation OperatorLoc,
                                      TypeTy *Ty, bool HasTrailingLParen,
-                                     const CXXScopeSpec &SS) {
+                                     const CXXScopeSpec &SS,
+                                     bool isAddressOfOperand) {
   QualType ConvType = QualType::getFromOpaquePtr(Ty);
   QualType ConvTypeCanon = Context.getCanonicalType(ConvType);
   DeclarationName ConvName 
     = Context.DeclarationNames.getCXXConversionFunctionName(ConvTypeCanon);
   return ActOnDeclarationNameExpr(S, OperatorLoc, ConvName, HasTrailingLParen,
-                                  &SS);
+                                  &SS, /*ForceRes*/false, isAddressOfOperand);
 }
 
 /// ActOnCXXOperatorFunctionIdExpr - Parse a C++ overloaded operator
@@ -46,9 +47,11 @@
 Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc,
                                      OverloadedOperatorKind Op,
                                      bool HasTrailingLParen,
-                                     const CXXScopeSpec &SS) {
+                                     const CXXScopeSpec &SS,
+                                     bool isAddressOfOperand) {
   DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(Op);
-  return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS);
+  return ActOnDeclarationNameExpr(S, OperatorLoc, Name, HasTrailingLParen, &SS,
+                                  /*ForceRes*/false, isAddressOfOperand);
 }
 
 /// ActOnCXXTypeidOfType - Parse typeid( type-id ).

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

==============================================================================
--- cfe/trunk/test/SemaCXX/member-pointer.cpp (original)
+++ cfe/trunk/test/SemaCXX/member-pointer.cpp Tue Feb  3 14:19:35 2009
@@ -40,3 +40,23 @@
   // Conversion to member of base.
   pdi1 = pdid; // expected-error {{incompatible type assigning 'int struct D::*', expected 'int struct A::*'}}
 }
+
+struct HasMembers
+{
+  int i;
+  void f();
+};
+
+namespace Fake
+{
+  int i;
+  void f();
+}
+
+void g() {
+  int HasMembers::*pmi = &HasMembers::i;
+  int *pni = &Fake::i;
+
+  // FIXME: Test the member function, too.
+  void (*pnf)() = &Fake::f;
+}





More information about the cfe-commits mailing list