Support typedef names redeclared to identifiers in inner scopes
diff --git a/tests/test_c_parser.py b/tests/test_c_parser.py
index b489bb8..2695beb 100644
--- a/tests/test_c_parser.py
+++ b/tests/test_c_parser.py
@@ -811,6 +811,37 @@
         # just make sure this doesn't raise ParseError
         self.parse(s4)
 
+    def test_struct_members_namespace(self):
+        """ Tests that structure/union member names reside in a separate namespace and
+            can be named after existing types.
+        """
+        s1 = """
+                typedef int Name;
+                typedef Name NameArray[10];
+
+                struct {
+                    Name Name;
+                    Name NameArray[3];
+                } sye;
+
+                void main(void)
+                {
+                    sye.Name = 1;
+                }
+            """
+
+        s1_ast = self.parse(s1)
+        self.assertEqual(expand_decl(s1_ast.ext[2]),
+            ['Decl', 'sye',
+                ['TypeDecl', ['Struct', None,
+                    [   ['Decl', 'Name',
+                            ['TypeDecl',
+                                ['IdentifierType', ['Name']]]],
+                        ['Decl', 'NameArray',
+                            ['ArrayDecl', '3',
+                                ['TypeDecl', ['IdentifierType', ['Name']]]]]]]]])
+        self.assertEqual(s1_ast.ext[3].body.block_items[0].lvalue.field.name, 'Name')
+
     def test_struct_bitfields(self):
         # a struct with two bitfields, one unnamed
         s1 = """
@@ -924,17 +955,49 @@
         for b in bad:
             self.assertRaises(ParseError, self.parse, b)
 
-        # Issue 60
-        badcode1 = '''
+    def test_duplicate_typedef(self):
+        """ Tests that redeclarations of existing types are parsed correctly.
+            This is non-standard, but allowed by many compilers.
+        """
+        d1 = '''
             typedef int numbertype;
-            typedef char numbertype;
+            typedef int numbertype;
         '''
-        try:
-            self.parse(badcode1)
-        except ParseError as err:
-            self.assertTrue(':3' in str(err))
-        else:
-            self.fail('Expected fail with ParseError')
+
+        self.assertEqual(self.get_decl(d1, 0),
+            ['Typedef', 'numbertype',
+                ['TypeDecl', ['IdentifierType', ['int']]]])
+        self.assertEqual(self.get_decl(d1, 1),
+            ['Typedef', 'numbertype',
+                ['TypeDecl', ['IdentifierType', ['int']]]])
+
+        d2 = '''
+            typedef int (*funcptr)(int x);
+            typedef int (*funcptr)(int x);
+        '''
+        self.assertEqual(self.get_decl(d2, 0),
+            ['Typedef', 'funcptr',
+                ['PtrDecl', ['FuncDecl',
+                    [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
+                    ['TypeDecl', ['IdentifierType', ['int']]]]]])
+        self.assertEqual(self.get_decl(d2, 1),
+            ['Typedef', 'funcptr',
+                ['PtrDecl', ['FuncDecl',
+                    [['Decl', 'x', ['TypeDecl', ['IdentifierType', ['int']]]]],
+                    ['TypeDecl', ['IdentifierType', ['int']]]]]])
+
+        d3 = '''
+            typedef int numberarray[5];
+            typedef int numberarray[5];
+        '''
+        self.assertEqual(self.get_decl(d3, 0),
+            ['Typedef', 'numberarray',
+                ['ArrayDecl', '5',
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
+        self.assertEqual(self.get_decl(d3, 1),
+            ['Typedef', 'numberarray',
+                ['ArrayDecl', '5',
+                    ['TypeDecl', ['IdentifierType', ['int']]]]])
 
     def test_decl_inits(self):
         d1 = 'int a = 16;'
@@ -1532,10 +1595,150 @@
             '''
         self.assertTrue(isinstance(self.parse(s2), FileAST))
 
+    def test_innerscope_reuse_typedef_name(self):
+        # identifiers can be reused in inner scopes; the original should be
+        # restored at the end of the block
+        s1 = r'''
+            typedef char TT;
+            void foo(void) {
+              unsigned TT;
+              TT = 10;
+            }
+            TT x = 5;
+            '''
+        s1_ast = self.parse(s1)
+        self.assertEqual(expand_decl(s1_ast.ext[1].body.block_items[0]),
+            ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
 
+        # this should be recognized even with an initializer
+        s2 = r'''
+            typedef char TT;
+            void foo(void) {
+              unsigned TT = 10;
+            }
+            '''
+        s2_ast = self.parse(s2)
+        self.assertEqual(expand_decl(s2_ast.ext[1].body.block_items[0]),
+            ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
+
+        # before the second local variable, TT is a type; after, it's a
+        # variable
+        s3 = r'''
+            typedef char TT;
+            void foo(void) {
+              TT tt = sizeof(TT);
+              unsigned TT = 10;
+            }
+            '''
+        s3_ast = self.parse(s3)
+        self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[0]),
+            ['Decl', 'tt', ['TypeDecl', ['IdentifierType', ['TT']]]])
+        self.assertEqual(expand_decl(s3_ast.ext[1].body.block_items[1]),
+            ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
+
+        # a variable and its type can even share the same name
+        s4 = r'''
+            typedef char TT;
+            void foo(void) {
+              TT TT = sizeof(TT);
+              unsigned uu = TT * 2;
+            }
+            '''
+        s4_ast = self.parse(s4)
+        self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[0]),
+            ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['TT']]]])
+        self.assertEqual(expand_decl(s4_ast.ext[1].body.block_items[1]),
+            ['Decl', 'uu', ['TypeDecl', ['IdentifierType', ['unsigned']]]])
+
+        # ensure an error is raised if a type, redeclared as a variable, is
+        # used as a type
+        s5 = r'''
+            typedef char TT;
+            void foo(void) {
+              unsigned TT = 10;
+              TT erroneous = 20;
+            }
+            '''
+        self.assertRaises(ParseError, self.parse, s5)
+
+    def test_parameter_reuse_typedef_name(self):
+        # identifiers can be reused as parameter names; parameter name scope
+        # begins and ends with the function body; it's important that TT is
+        # used immediately after the LBRACE and RBRACE, to test a corner case
+        s1 = r'''
+            typedef char TT;
+            void foo(unsigned TT, TT bar) {
+              TT = 10;
+            }
+            TT x = 5;
+            '''
+        s1_ast = self.parse(s1)
+        self.assertEqual(expand_decl(s1_ast.ext[1].decl),
+            ['Decl', 'foo',
+                ['FuncDecl',
+                    [   ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
+                        ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
+                    ['TypeDecl', ['IdentifierType', ['void']]]]])
+
+        # the scope of a parameter name in a function declaration ends at the
+        # end of the declaration...so it is effectively never used; it's
+        # important that TT is used immediately after the declaration, to
+        # test a corner case
+        s2 = r'''
+            typedef char TT;
+            void foo(unsigned TT, TT bar);
+            TT x = 5;
+            '''
+        s2_ast = self.parse(s2)
+        self.assertEqual(expand_decl(s2_ast.ext[1]),
+            ['Decl', 'foo',
+                ['FuncDecl',
+                    [   ['Decl', 'TT', ['TypeDecl', ['IdentifierType', ['unsigned']]]],
+                        ['Decl', 'bar', ['TypeDecl', ['IdentifierType', ['TT']]]]],
+                    ['TypeDecl', ['IdentifierType', ['void']]]]])
+
+        # ensure an error is raised if a type, redeclared as a parameter, is
+        # used as a type
+        s3 = r'''
+            typedef char TT;
+            void foo(unsigned TT, TT bar) {
+              TT erroneous = 20;
+            }
+            '''
+        self.assertRaises(ParseError, self.parse, s3)
+
+    def test_nested_function_decls(self):
+        # parameter names of nested function declarations must not escape into
+        # the top-level function _definition's_ scope; the following must
+        # succeed because TT is still a typedef inside foo's body
+        s1 = r'''
+            typedef char TT;
+            void foo(unsigned bar(int TT)) {
+              TT x = 10;
+            }
+            '''
+        self.assertTrue(isinstance(self.parse(s1), FileAST))
+
+    def test_samescope_reuse_name(self):
+        # a typedef name cannot be reused as an object name in the same scope
+        s1 = r'''
+            typedef char TT;
+            char TT = 5;
+            '''
+        self.assertRaises(ParseError, self.parse, s1)
+
+        # ...and vice-versa
+        s2 = r'''
+            char TT = 5;
+            typedef char TT;
+            '''
+        self.assertRaises(ParseError, self.parse, s2)
 
 if __name__ == '__main__':
     #~ suite = unittest.TestLoader().loadTestsFromNames(
+        #~ ['test_c_parser.TestCParser_typenames.test_parameter_reuse_typedef_name'])
+
+    #~ suite = unittest.TestLoader().loadTestsFromNames(
         #~ ['test_c_parser.TestCParser_fundamentals.test_typedef'])
 
     #~ suite = unittest.TestLoader().loadTestsFromNames(