[cfe-commits] r48972 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclObjC.h lib/AST/Decl.cpp lib/Sema/SemaExpr.cpp test/Sema/objc-ivar-lookup.m

Chris Lattner sabre at nondot.org
Sun Mar 30 17:36:03 PDT 2008


Author: lattner
Date: Sun Mar 30 19:36:02 2008
New Revision: 48972

URL: http://llvm.org/viewvc/llvm-project?rev=48972&view=rev
Log:
rename Decl::CompatibleAlias -> ObjCCompatibleAlias.

Fix objc ivar lookup.  Ivar lookup should occur between lookup
of method-local values and lookup of globals.  Emulate this with
some logic in the handling of Sema::ActOnIdentifierExpr.

Two todo's left:
 1) sema shouldn't turn a bare reference to an ivar into "self->ivar"
    in the AST.  This is a hack.
 2) The new ScopedDecl::isDefinedOutsideFunctionOrMethod method does
    not correctly handle typedefs and enum constants yet.


Added:
    cfe/trunk/test/Sema/objc-ivar-lookup.m
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sun Mar 30 19:36:02 2008
@@ -51,7 +51,7 @@
            ObjCProtocol,
            PropertyDecl,
     //     ScopedDecl
-             CompatibleAlias,
+             ObjCCompatibleAlias,
     //       TypeDecl
                ObjCInterface,
                Typedef,
@@ -78,7 +78,7 @@
     // of the class, to allow efficient classof.
     NamedFirst  = Field,         NamedLast  = ParmVar,
     FieldFirst  = Field,         FieldLast  = ObjCIvar,
-    ScopedFirst = CompatibleAlias, ScopedLast = ParmVar,
+    ScopedFirst = ObjCCompatibleAlias, ScopedLast = ParmVar,
     TypeFirst   = ObjCInterface, TypeLast   = Class,
     TagFirst    = Enum         , TagLast    = Class,
     RecordFirst = Struct       , RecordLast = Class,
@@ -161,7 +161,7 @@
     case ParmVar:
     case EnumConstant:
     case ObjCInterface:
-    case CompatibleAlias:
+    case ObjCCompatibleAlias:
       return IDNS_Ordinary;
     case Struct:
     case Union:
@@ -247,6 +247,12 @@
   const ScopedDecl *getNextDeclarator() const { return NextDeclarator; }
   void setNextDeclarator(ScopedDecl *N) { NextDeclarator = N; }
   
+  // isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+  // scoped decl is defined outside the current function or method.  This is
+  // roughly global variables and functions, but also handles enums (which could
+  // be defined inside or outside a function etc).
+  bool isDefinedOutsideFunctionOrMethod() const;
+  
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) {
     return D->getKind() >= ScopedFirst && D->getKind() <= ScopedLast;
@@ -348,7 +354,11 @@
   virtual void ReadImpl(llvm::Deserializer& S);
 };
 
-/// BlockVarDecl - Represent a local variable declaration.
+/// BlockVarDecl - Represent a local variable declaration.  Note that this
+/// includes static variables inside of functions.
+///
+///   void foo() { int x; static int y; extern int z; }
+///
 class BlockVarDecl : public VarDecl {
   BlockVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S,
                ScopedDecl *PrevDecl)

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sun Mar 30 19:36:02 2008
@@ -877,7 +877,7 @@
   
   ObjCCompatibleAliasDecl(SourceLocation L, IdentifierInfo *Id,
                          ObjCInterfaceDecl* aliasedClass)
-  : ScopedDecl(CompatibleAlias, L, Id, 0), AliasedClass(aliasedClass) {}
+  : ScopedDecl(ObjCCompatibleAlias, L, Id, 0), AliasedClass(aliasedClass) {}
 public:
   static ObjCCompatibleAliasDecl *Create(ASTContext &C, SourceLocation L,
                                          IdentifierInfo *Id,
@@ -887,7 +887,7 @@
   ObjCInterfaceDecl *getClassInterface() { return AliasedClass; }
   
   static bool classof(const Decl *D) {
-    return D->getKind() == CompatibleAlias;
+    return D->getKind() == ObjCCompatibleAlias;
   }
   static bool classof(const ObjCCompatibleAliasDecl *D) { return true; }
   

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

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Mar 30 19:36:02 2008
@@ -193,7 +193,7 @@
   case ObjCIvar:            nIvarDecls++; break;
   case ObjCImplementation:  nObjCImplementationDecls++; break;
   case ObjCCategoryImpl:    nObjCCategoryImpl++; break;
-  case CompatibleAlias:     nObjCCompatibleAlias++; break;
+  case ObjCCompatibleAlias: nObjCCompatibleAlias++; break;
   case PropertyDecl:        nObjCPropertyDecl++; break;
   case LinkageSpec:         nLinkageSpecDecl++; break;
   case FileScopeAsm:        nFileScopeAsmDecl++; break;
@@ -319,12 +319,46 @@
   return (*DeclAttrs)[this];
 }
 
+//===----------------------------------------------------------------------===//
+// NamedDecl Implementation
+//===----------------------------------------------------------------------===//
+
 const char *NamedDecl::getName() const {
   if (const IdentifierInfo *II = getIdentifier())
     return II->getName();
   return "";
 }
 
+//===----------------------------------------------------------------------===//
+// ScopedDecl Implementation
+//===----------------------------------------------------------------------===//
+
+// isDefinedOutsideFunctionOrMethod - This predicate returns true if this
+// scoped decl is defined outside the current function or method.  This is
+// roughly global variables and functions, but also handles enums (which could
+// be defined inside or outside a function etc).
+bool ScopedDecl::isDefinedOutsideFunctionOrMethod() const {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(this))
+    return VD->hasGlobalStorage();
+  if (isa<FunctionDecl>(this))
+    return true;
+  
+  // FIXME: Why is ObjCCompatibleAlias a scopedecl?
+  if (isa<ObjCCompatibleAliasDecl>(this))
+    return true;
+  
+  // FIXME: This needs to check the context the decl was defined in!
+  if (isa<TypeDecl>(this) || isa<EnumConstantDecl>(this))
+    return true;
+  
+  assert(0 && "Unknown ScopedDecl!");
+  return false;
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionDecl Implementation
+//===----------------------------------------------------------------------===//
+
 FunctionDecl::~FunctionDecl() {
   delete[] ParamInfo;
 }
@@ -346,6 +380,9 @@
   }
 }
 
+//===----------------------------------------------------------------------===//
+// RecordDecl Implementation
+//===----------------------------------------------------------------------===//
 
 /// defineBody - When created, RecordDecl's correspond to a forward declared
 /// record.  This method is used to mark the decl as being defined, with the
@@ -360,14 +397,13 @@
   }
 }
 
-FieldDecl* RecordDecl::getMember(IdentifierInfo *name) {
+FieldDecl *RecordDecl::getMember(IdentifierInfo *II) {
   if (Members == 0 || NumMembers < 0)
     return 0;
   
-  // linear search. When C++ classes come along, will likely need to revisit.
-  for (int i = 0; i < NumMembers; ++i) {
-    if (Members[i]->getIdentifier() == name)
+  // Linear search.  When C++ classes come along, will likely need to revisit.
+  for (int i = 0; i != NumMembers; ++i)
+    if (Members[i]->getIdentifier() == II)
       return Members[i];
-  }
   return 0;
 }

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Mar 30 19:36:02 2008
@@ -74,31 +74,43 @@
 Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
                                            IdentifierInfo &II,
                                            bool HasTrailingLParen) {
-  // Could be enum-constant or decl.
+  // Could be enum-constant, value decl, instance variable, etc.
   ScopedDecl *D = LookupScopedDecl(&II, Decl::IDNS_Ordinary, Loc, S);
+  
+  // If this reference is in an Objective-C method, then ivar lookup happens as
+  // well.
+  if (CurMethodDecl) {
+    // There are two cases to handle here.  1) scoped lookup could have failed,
+    // in which case we should look for an ivar.  2) scoped lookup could have
+    // found a decl, but that decl is outside the current method (i.e. a global
+    // variable).  In these two cases, we do a lookup for an ivar with this
+    // name, if the lookup suceeds, we replace it our current decl.
+    if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) {
+      ObjCInterfaceDecl *IFace = CurMethodDecl->getClassInterface(), *DeclClass;
+      if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II, DeclClass)) {
+        // FIXME: This should use a new expr for a direct reference, don't turn
+        // this into Self->ivar, just return a BareIVarExpr or something.
+        IdentifierInfo &II = Context.Idents.get("self");
+        ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
+        return new ObjCIvarRefExpr(IV, IV->getType(), Loc, 
+                                 static_cast<Expr*>(SelfExpr.Val), true, true);
+      }
+    }
+  }
+  
   if (D == 0) {
     // Otherwise, this could be an implicitly declared function reference (legal
     // in C90, extension in C99).
     if (HasTrailingLParen &&
-        // Not in C++.
-        !getLangOptions().CPlusPlus)
+        !getLangOptions().CPlusPlus) // Not in C++.
       D = ImplicitlyDefineFunction(Loc, II, S);
     else {
-      if (CurMethodDecl) {
-        ObjCInterfaceDecl *IFace = CurMethodDecl->getClassInterface();
-        ObjCInterfaceDecl *clsDeclared;
-        if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(&II, clsDeclared)) {
-          IdentifierInfo &II = Context.Idents.get("self");
-          ExprResult SelfExpr = ActOnIdentifierExpr(S, Loc, II, false);
-          return new ObjCIvarRefExpr(IV, IV->getType(), Loc, 
-                       static_cast<Expr*>(SelfExpr.Val), true, true);
-        }
-      }
       // If this name wasn't predeclared and if this is not a function call,
       // diagnose the problem.
       return Diag(Loc, diag::err_undeclared_var_use, II.getName());
     }
   }
+  
   if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
     // check if referencing an identifier with __attribute__((deprecated)).
     if (VD->getAttr<DeprecatedAttr>())
@@ -109,6 +121,7 @@
       return true;
     return new DeclRefExpr(VD, VD->getType(), Loc);
   }
+  
   if (isa<TypedefDecl>(D))
     return Diag(Loc, diag::err_unexpected_typedef, II.getName());
   if (isa<ObjCInterfaceDecl>(D))

Added: cfe/trunk/test/Sema/objc-ivar-lookup.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/objc-ivar-lookup.m?rev=48972&view=auto

==============================================================================
--- cfe/trunk/test/Sema/objc-ivar-lookup.m (added)
+++ cfe/trunk/test/Sema/objc-ivar-lookup.m Sun Mar 30 19:36:02 2008
@@ -0,0 +1,18 @@
+// RUN: clang %s -fsyntax-only -verify
+
+ at interface Test {
+   int x;
+}
+
+-(void) setX: (int) d;
+ at end
+
+extern struct foo x;
+
+ at implementation Test
+
+-(void) setX: (int) n {
+   x = n;
+}
+
+ at end





More information about the cfe-commits mailing list