From a6bbec2b56f4a07f408bf3213b3b15fa6fc10330 Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Wed, 11 Nov 2009 09:32:05 +0100
Subject: [PATCH] Added symbols for property declarations.

---
 src/libs/cplusplus/CheckUndefinedSymbols.cpp  | 13 ++++
 src/libs/cplusplus/CheckUndefinedSymbols.h    |  1 +
 src/shared/cplusplus/AST.h                    |  3 +
 .../cplusplus/CPlusPlusForwardDeclarations.h  |  1 +
 src/shared/cplusplus/CheckDeclaration.cpp     | 77 ++++++++++---------
 src/shared/cplusplus/Control.cpp              | 12 +++
 src/shared/cplusplus/Control.h                |  3 +
 src/shared/cplusplus/Symbol.cpp               |  3 +-
 src/shared/cplusplus/Symbol.h                 |  5 ++
 src/shared/cplusplus/SymbolVisitor.h          |  1 +
 src/shared/cplusplus/Symbols.cpp              | 19 +++++
 src/shared/cplusplus/Symbols.h                | 69 +++++++++++++++++
 12 files changed, 171 insertions(+), 36 deletions(-)

diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.cpp b/src/libs/cplusplus/CheckUndefinedSymbols.cpp
index 7ea1748e648..5d996579eed 100644
--- a/src/libs/cplusplus/CheckUndefinedSymbols.cpp
+++ b/src/libs/cplusplus/CheckUndefinedSymbols.cpp
@@ -518,3 +518,16 @@ bool CheckUndefinedSymbols::visit(ObjCProtocolRefsAST *ast)
 
     return false;
 }
+
+bool CheckUndefinedSymbols::visit(ObjCPropertyDeclarationAST *ast)
+{
+    for (List<ObjCPropertyDeclaration *> *iter = ast->symbols; iter; iter = iter->next) {
+        if (Name *getterName = iter->value->getterName())
+            ; // FIXME: resolve the symbol for the name, and check its signature.
+
+        if (Name *setterName = iter->value->setterName())
+            ; // FIXME: resolve the symbol for the name, and check its signature.
+    }
+
+    return false;
+}
diff --git a/src/libs/cplusplus/CheckUndefinedSymbols.h b/src/libs/cplusplus/CheckUndefinedSymbols.h
index fbdca0f94ec..4a13b6ee2dc 100644
--- a/src/libs/cplusplus/CheckUndefinedSymbols.h
+++ b/src/libs/cplusplus/CheckUndefinedSymbols.h
@@ -96,6 +96,7 @@ protected:
 
     virtual bool visit(ObjCClassDeclarationAST *ast);
     virtual bool visit(ObjCProtocolRefsAST *ast);
+    virtual bool visit(ObjCPropertyDeclarationAST *ast);
 
 private:
     Document::Ptr _doc;
diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h
index aec40834751..2a1c2d6ef03 100644
--- a/src/shared/cplusplus/AST.h
+++ b/src/shared/cplusplus/AST.h
@@ -2391,6 +2391,9 @@ public:
     unsigned rparen_token;
     DeclarationAST *simple_declaration;
 
+public: // annotations
+    List<ObjCPropertyDeclaration *> *symbols;
+
 public:
     virtual ObjCPropertyDeclarationAST *asObjCPropertyDeclaration() { return this; }
 
diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
index 9616f51780d..c21d0bbd0e3 100644
--- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
+++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h
@@ -130,6 +130,7 @@ class ObjCForwardClassDeclaration;
 class ObjCProtocol;
 class ObjCForwardProtocolDeclaration;
 class ObjCMethod;
+class ObjCPropertyDeclaration;
 
 } // end of namespace CPlusPlus
 
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index 728e87385d8..04ee291aef5 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -682,21 +682,6 @@ bool CheckDeclaration::visit(ObjCVisibilityDeclarationAST *ast)
     return false;
 }
 
-enum PropertyAttributes {
-    None = 0,
-    Assign = 1 << 0,
-    Retain = 1 << 1,
-    Copy = 1 << 2,
-    ReadOnly = 1 << 3,
-    ReadWrite = 1 << 4,
-    Getter = 1 << 5,
-    Setter = 1 << 6,
-    NonAtomic = 1 << 7,
-
-    WritabilityMask = ReadOnly | ReadWrite,
-    SetterSemanticsMask = Assign | Retain | Copy,
-};
-
 bool CheckDeclaration::checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst,
                                               int &flags,
                                               int attr)
@@ -714,7 +699,17 @@ bool CheckDeclaration::checkPropertyAttribute(ObjCPropertyAttributeAST *attrAst,
 
 bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
 {
-    int propAttrs = None;
+    semantic()->check(ast->simple_declaration, _scope);
+    SimpleDeclarationAST *simpleDecl = ast->simple_declaration->asSimpleDeclaration();
+
+    if (!simpleDecl) {
+        translationUnit()->warning(ast->simple_declaration->firstToken(),
+                                   "invalid type for property declaration");
+        return false;
+    }
+
+    int propAttrs = ObjCPropertyDeclaration::None;
+    Name *getterName = 0, *setterName = 0;
 
     for (ObjCPropertyAttributeListAST *iter= ast->property_attribute_list; iter; iter = iter->next) {
         ObjCPropertyAttributeAST *attrAst = iter->value;
@@ -723,45 +718,57 @@ bool CheckDeclaration::visit(ObjCPropertyDeclarationAST *ast)
 
         Identifier *attrId = identifier(attrAst->attribute_identifier_token);
         if (attrId == control()->objcGetterId()) {
-            if (checkPropertyAttribute(attrAst, propAttrs, Getter)) {
-                // TODO: find method declaration for getter
+            if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Getter)) {
+                getterName = semantic()->check(attrAst->method_selector, _scope);
             }
         } else if (attrId == control()->objcSetterId()) {
-            if (checkPropertyAttribute(attrAst, propAttrs, Setter)) {
-                // TODO: find method declaration for setter
+            if (checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Setter)) {
+                setterName = semantic()->check(attrAst->method_selector, _scope);
             }
         } else if (attrId == control()->objcReadwriteId()) {
-            checkPropertyAttribute(attrAst, propAttrs, ReadWrite);
+            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadWrite);
         } else if (attrId == control()->objcReadonlyId()) {
-            checkPropertyAttribute(attrAst, propAttrs, ReadOnly);
+            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::ReadOnly);
         } else if (attrId == control()->objcAssignId()) {
-            checkPropertyAttribute(attrAst, propAttrs, Assign);
+            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Assign);
         } else if (attrId == control()->objcRetainId()) {
-            checkPropertyAttribute(attrAst, propAttrs, Retain);
+            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Retain);
         } else if (attrId == control()->objcCopyId()) {
-            checkPropertyAttribute(attrAst, propAttrs, Copy);
+            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::Copy);
         } else if (attrId == control()->objcNonatomicId()) {
-            checkPropertyAttribute(attrAst, propAttrs, NonAtomic);
+            checkPropertyAttribute(attrAst, propAttrs, ObjCPropertyDeclaration::NonAtomic);
         }
     }
 
-    if (propAttrs & ReadOnly && propAttrs & ReadWrite)
+    if (propAttrs & ObjCPropertyDeclaration::ReadOnly &&
+        propAttrs & ObjCPropertyDeclaration::ReadWrite)
         // Should this be an error instead of only a warning?
         translationUnit()->warning(ast->property_token,
                                    "property can have at most one attribute \"readonly\" or \"readwrite\" specified");
-    int setterSemAttrs = propAttrs & SetterSemanticsMask;
+    int setterSemAttrs = propAttrs & ObjCPropertyDeclaration::SetterSemanticsMask;
     if (setterSemAttrs
-            && setterSemAttrs != Assign
-            && setterSemAttrs != Retain
-            && setterSemAttrs != Copy) {
+            && setterSemAttrs != ObjCPropertyDeclaration::Assign
+            && setterSemAttrs != ObjCPropertyDeclaration::Retain
+            && setterSemAttrs != ObjCPropertyDeclaration::Copy) {
         // Should this be an error instead of only a warning?
         translationUnit()->warning(ast->property_token,
                                    "property can have at most one attribute \"assign\", \"retain\", or \"copy\" specified");
     }
 
-    // TODO: Check if the next line is correct (EV)
-    semantic()->check(ast->simple_declaration, _scope);
+    List<ObjCPropertyDeclaration *> **lastSymbols = &ast->symbols;
+    for (List<Declaration*> *iter = simpleDecl->symbols; iter; iter = iter->next) {
+        ObjCPropertyDeclaration *propDecl = control()->newObjCPropertyDeclaration(ast->firstToken(),
+                                                                                  iter->value->name());
+        propDecl->setType(iter->value->type());
+        propDecl->setAttributes(propAttrs);
+        propDecl->setGetterName(getterName);
+        propDecl->setSetterName(setterName);
+        _scope->enterSymbol(propDecl);
+
+        *lastSymbols = new (translationUnit()->memoryPool()) List<ObjCPropertyDeclaration *>();
+        (*lastSymbols)->value = propDecl;
+        lastSymbols = &(*lastSymbols)->next;
+    }
+
     return false;
 }
-
-
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 249d671ae17..d2b91e14a2b 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -129,6 +129,7 @@ public:
         delete_array_entries(objcForwardClassDeclarations);
         delete_array_entries(objcForwardProtocolDeclarations);
         delete_array_entries(objcMethods);
+        delete_array_entries(objcPropertyDeclarations);
     }
 
     NameId *findOrInsertNameId(Identifier *id)
@@ -393,6 +394,13 @@ public:
         return method;
     }
 
+    ObjCPropertyDeclaration *newObjCPropertyDeclaration(unsigned sourceLocation, Name *name)
+    {
+        ObjCPropertyDeclaration *decl = new ObjCPropertyDeclaration(translationUnit, sourceLocation, name);
+        objcPropertyDeclarations.push_back(decl);
+        return decl;
+    }
+
     Enum *newEnum(unsigned sourceLocation, Name *name)
     {
         Enum *e = new Enum(translationUnit,
@@ -577,6 +585,7 @@ public:
     std::vector<ObjCForwardClassDeclaration *> objcForwardClassDeclarations;
     std::vector<ObjCForwardProtocolDeclaration *> objcForwardProtocolDeclarations;
     std::vector<ObjCMethod *> objcMethods;
+    std::vector<ObjCPropertyDeclaration *> objcPropertyDeclarations;
 
     // ObjC context keywords:
     Identifier *objcGetterId;
@@ -787,6 +796,9 @@ ObjCForwardProtocolDeclaration *Control::newObjCForwardProtocolDeclaration(unsig
 ObjCMethod *Control::newObjCMethod(unsigned sourceLocation, Name *name)
 { return d->newObjCMethod(sourceLocation, name); }
 
+ObjCPropertyDeclaration *Control::newObjCPropertyDeclaration(unsigned sourceLocation, Name *name)
+{ return d->newObjCPropertyDeclaration(sourceLocation, name); }
+
 Identifier *Control::objcGetterId() const
 { return d->objcGetterId; }
 
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index d4db273e431..6abeb8ef6d0 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -169,6 +169,9 @@ public:
     /// Creates a new Objective-C method symbol.
     ObjCMethod *newObjCMethod(unsigned sourceLocation, Name *name = 0);
 
+    /// Creates a new Objective-C @property declaration symbol.
+    ObjCPropertyDeclaration *newObjCPropertyDeclaration(unsigned sourceLocation, Name *name);
+
     // Objective-C specific context keywords.
     Identifier *objcGetterId() const;
     Identifier *objcSetterId() const;
diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp
index 6cd6573aa6a..e8b80fdcae9 100644
--- a/src/shared/cplusplus/Symbol.cpp
+++ b/src/shared/cplusplus/Symbol.cpp
@@ -488,4 +488,5 @@ bool Symbol::isObjCForwardProtocolDeclaration() const
 bool Symbol::isObjCMethod() const
 { return asObjCMethod() != 0; }
 
-
+bool Symbol::isObjCPropertyDeclaration() const
+{ return asObjCPropertyDeclaration() != 0; }
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
index 93d730b0cfb..61abe02c7e1 100644
--- a/src/shared/cplusplus/Symbol.h
+++ b/src/shared/cplusplus/Symbol.h
@@ -228,6 +228,9 @@ public:
     /// Returns true if this Symbol is an Objective-C method declaration.
     bool isObjCMethod() const;
 
+    /// Returns true if this Symbol is an Objective-C @property declaration.
+    bool isObjCPropertyDeclaration() const;
+
     virtual const ScopedSymbol *asScopedSymbol() const { return 0; }
     virtual const Enum *asEnum() const { return 0; }
     virtual const Function *asFunction() const { return 0; }
@@ -247,6 +250,7 @@ public:
     virtual const ObjCProtocol *asObjCProtocol() const { return 0; }
     virtual const ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() const { return 0; }
     virtual const ObjCMethod *asObjCMethod() const { return 0; }
+    virtual const ObjCPropertyDeclaration *asObjCPropertyDeclaration() const { return 0; }
 
     virtual ScopedSymbol *asScopedSymbol() { return 0; }
     virtual Enum *asEnum() { return 0; }
@@ -267,6 +271,7 @@ public:
     virtual ObjCProtocol *asObjCProtocol() { return 0; }
     virtual ObjCForwardProtocolDeclaration *asObjCForwardProtocolDeclaration() { return 0; }
     virtual ObjCMethod *asObjCMethod() { return 0; }
+    virtual ObjCPropertyDeclaration *asObjCPropertyDeclaration() { return 0; }
 
     /// Returns this Symbol's type.
     virtual FullySpecifiedType type() const = 0;
diff --git a/src/shared/cplusplus/SymbolVisitor.h b/src/shared/cplusplus/SymbolVisitor.h
index 4bfa3794308..0e6440b750c 100644
--- a/src/shared/cplusplus/SymbolVisitor.h
+++ b/src/shared/cplusplus/SymbolVisitor.h
@@ -88,6 +88,7 @@ public:
     virtual bool visit(ObjCProtocol *) { return true; }
     virtual bool visit(ObjCForwardProtocolDeclaration *) { return true; }
     virtual bool visit(ObjCMethod *) { return true; }
+    virtual bool visit(ObjCPropertyDeclaration *) { return true; }
 };
 
 } // end of namespace CPlusPlus
diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp
index 8ddaf3ef5dd..819c8730ed5 100644
--- a/src/shared/cplusplus/Symbols.cpp
+++ b/src/shared/cplusplus/Symbols.cpp
@@ -820,4 +820,23 @@ void ObjCMethod::visitSymbol0(SymbolVisitor *visitor)
     }
 }
 
+ObjCPropertyDeclaration::ObjCPropertyDeclaration(TranslationUnit *translationUnit,
+                                                 unsigned sourceLocation,
+                                                 Name *name):
+    Symbol(translationUnit, sourceLocation, name),
+    _propertyAttributes(None),
+    _getterName(0),
+    _setterName(0)
+{}
+
+ObjCPropertyDeclaration::~ObjCPropertyDeclaration()
+{}
+
+FullySpecifiedType ObjCPropertyDeclaration::type() const
+{ return _type; }
 
+void ObjCPropertyDeclaration::visitSymbol0(SymbolVisitor *visitor)
+{
+    if (visitor->visit(this)) {
+    }
+}
diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h
index acd13085f5b..88d8d521cda 100644
--- a/src/shared/cplusplus/Symbols.h
+++ b/src/shared/cplusplus/Symbols.h
@@ -729,6 +729,75 @@ private:
     Scope *_arguments;
 };
 
+class CPLUSPLUS_EXPORT ObjCPropertyDeclaration: public Symbol
+{
+public:
+    enum PropertyAttributes {
+        None = 0,
+        Assign = 1 << 0,
+        Retain = 1 << 1,
+        Copy = 1 << 2,
+        ReadOnly = 1 << 3,
+        ReadWrite = 1 << 4,
+        Getter = 1 << 5,
+        Setter = 1 << 6,
+        NonAtomic = 1 << 7,
+
+        WritabilityMask = ReadOnly | ReadWrite,
+        SetterSemanticsMask = Assign | Retain | Copy,
+    };
+
+public:
+    ObjCPropertyDeclaration(TranslationUnit *translationUnit,
+                            unsigned sourceLocation,
+                            Name *name);
+    virtual ~ObjCPropertyDeclaration();
+
+    bool hasAttribute(int attribute) const
+    { return _propertyAttributes & attribute; }
+
+    void setAttributes(int attributes)
+    { _propertyAttributes = attributes; }
+
+    bool hasGetter() const
+    { return hasAttribute(Getter); }
+
+    bool hasSetter() const
+    { return hasAttribute(Setter); }
+
+    Name *getterName() const
+    { return _getterName; }
+
+    void setGetterName(Name *getterName)
+    { _getterName = getterName; }
+
+    Name *setterName() const
+    { return _setterName; }
+
+    void setSetterName(Name *setterName)
+    { _setterName = setterName; }
+
+    void setType(const FullySpecifiedType &type)
+    { _type = type; }
+
+    // Symbol's interface
+    virtual FullySpecifiedType type() const;
+
+    virtual const ObjCPropertyDeclaration *asOObjCPropertyDeclaration() const
+    { return this; }
+
+    virtual ObjCPropertyDeclaration *asObjCPropertyDeclaration()
+    { return this; }
+
+protected:
+    virtual void visitSymbol0(SymbolVisitor *visitor);
+
+private:
+    FullySpecifiedType _type;
+    int _propertyAttributes;
+    Name *_getterName, *_setterName;
+};
+
 } // end of namespace CPlusPlus
 
 
-- 
GitLab