public void testObjectMacroExpansionComplex() throws Exception {
    StringBuffer buffer = new StringBuffer("#define XYZ const\n"); // $NON-NLS-1$
    buffer.append("#define PO *\n"); // $NON-NLS-1$
    buffer.append("#define C_PO PO XYZ\n"); // $NON-NLS-1$
    buffer.append("#define IT int\n"); // $NON-NLS-1$
    buffer.append("#define V var\n"); // $NON-NLS-1$
    buffer.append("XYZ IT C_PO C_PO V;"); // $NON-NLS-1$
    String code = buffer.toString();

    for (ParserLanguage language : languages) {
      IASTTranslationUnit tu = parse(code, language);
      IASTPreprocessorObjectStyleMacroDefinition XYZ =
          (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[0];
      //            IASTPreprocessorObjectStyleMacroDefinition PO =
      // (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[1];
      IASTPreprocessorObjectStyleMacroDefinition C_PO =
          (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[2];
      IASTPreprocessorObjectStyleMacroDefinition IT =
          (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[3];
      IASTPreprocessorObjectStyleMacroDefinition V =
          (IASTPreprocessorObjectStyleMacroDefinition) tu.getMacroDefinitions()[4];

      IASTSimpleDeclaration var = (IASTSimpleDeclaration) tu.getDeclarations()[0];
      final IASTNodeLocation[] nodeLocations = var.getNodeLocations();

      assertEquals(10, nodeLocations.length);
      IASTMacroExpansionLocation first_loc = (IASTMacroExpansionLocation) nodeLocations[0];
      assertEqualsMacros(first_loc.getExpansion().getMacroDefinition(), XYZ);
      IASTFileLocation second_loc = (IASTFileLocation) nodeLocations[1];
      assertEquals(1, second_loc.getNodeLength());
      IASTMacroExpansionLocation third_loc = (IASTMacroExpansionLocation) nodeLocations[2];
      assertEqualsMacros(third_loc.getExpansion().getMacroDefinition(), IT);
      IASTFileLocation fourth_loc = (IASTFileLocation) nodeLocations[3];
      assertEquals(1, fourth_loc.getNodeLength());
      IASTMacroExpansionLocation fifth_loc = (IASTMacroExpansionLocation) nodeLocations[4];
      assertEqualsMacros(fifth_loc.getExpansion().getMacroDefinition(), C_PO);
      IASTFileLocation sixth_loc = (IASTFileLocation) nodeLocations[5];
      assertEquals(1, sixth_loc.getNodeLength());
      IASTMacroExpansionLocation seventh_loc = (IASTMacroExpansionLocation) nodeLocations[6];
      assertEqualsMacros(seventh_loc.getExpansion().getMacroDefinition(), C_PO);
      IASTFileLocation eighth_loc = (IASTFileLocation) nodeLocations[7];
      assertEquals(1, eighth_loc.getNodeLength());
      IASTMacroExpansionLocation ninth_loc = (IASTMacroExpansionLocation) nodeLocations[8];
      assertEqualsMacros(ninth_loc.getExpansion().getMacroDefinition(), V);
      IASTFileLocation tenth_loc = (IASTFileLocation) nodeLocations[9];
      assertEquals(1, tenth_loc.getNodeLength());

      final IASTFileLocation flatLocation = var.getFileLocation();
      assertNotNull(flatLocation);
      assertEquals(
          code.indexOf("XYZ IT C_PO C_PO V;"), flatLocation.getNodeOffset()); // $NON-NLS-1$
      assertEquals("XYZ IT C_PO C_PO V;".length(), flatLocation.getNodeLength()); // $NON-NLS-1$
    }
  }
  private void findDefinitionInsertLocation(IProgressMonitor pm) throws CoreException {
    if (definitionInsertLocation != null) {
      return;
    }

    IASTSimpleDeclaration decl = context.existingFields.get(0);
    MethodDefinitionInsertLocationFinder locationFinder =
        new MethodDefinitionInsertLocationFinder();
    InsertLocation location =
        locationFinder.find(tu, decl.getFileLocation(), decl.getParent(), astCache, pm);

    if (location.getFile() == null || NodeHelper.isContainedInTemplateDeclaration(decl)) {
      location.setNodeToInsertAfter(NodeHelper.findTopLevelParent(decl), tu);
    }

    definitionInsertLocation = location;
  }
  public void testStdioBug() throws ParserException {
    StringBuffer buffer = new StringBuffer("#define    _PTR        void *\n"); // $NON-NLS-1$
    buffer.append("#define __cdecl __attribute__ ((__cdecl__))\n"); // $NON-NLS-1$
    buffer.append("#define _EXFUN(name, proto)     __cdecl name proto\n"); // $NON-NLS-1$
    buffer.append("_PTR     _EXFUN(memchr,(const _PTR, int, size_t));\n"); // $NON-NLS-1$
    String code = buffer.toString();

    for (ParserLanguage language : languages) {
      IASTTranslationUnit tu = parse(code, language, true, true);
      final IASTPreprocessorMacroDefinition[] macroDefinitions = tu.getMacroDefinitions();
      IASTPreprocessorObjectStyleMacroDefinition _PTR =
          (IASTPreprocessorObjectStyleMacroDefinition) macroDefinitions[0];
      IASTPreprocessorFunctionStyleMacroDefinition _EXFUN =
          (IASTPreprocessorFunctionStyleMacroDefinition) macroDefinitions[2];
      IASTSimpleDeclaration memchr = (IASTSimpleDeclaration) tu.getDeclarations()[0];
      IASTNodeLocation[] locations = memchr.getNodeLocations();
      assertEquals(locations.length, 4);
      IASTMacroExpansionLocation loc_1 = (IASTMacroExpansionLocation) locations[0];
      assertEqualsMacros(_PTR, loc_1.getExpansion().getMacroDefinition());
      IASTFileLocation loc_2 = (IASTFileLocation) locations[1];
      assertEquals(loc_2.getNodeOffset(), code.indexOf("     _EXFUN(")); // $NON-NLS-1$
      assertEquals(loc_2.getNodeLength(), "     ".length()); // $NON-NLS-1$
      IASTMacroExpansionLocation loc_3 = (IASTMacroExpansionLocation) locations[2];
      assertEqualsMacros(_EXFUN, loc_3.getExpansion().getMacroDefinition());
      IASTFileLocation loc_4 = (IASTFileLocation) locations[3];
      assertEquals(loc_4.getNodeOffset(), code.indexOf(";")); // $NON-NLS-1$
      assertEquals(loc_4.getNodeLength(), 1);
      IASTFileLocation flat = memchr.getFileLocation();
      assertEquals(
          flat.getNodeOffset(),
          code.indexOf("_PTR     _EXFUN(memchr,(const _PTR, int, size_t));")); // $NON-NLS-1$
      assertEquals(
          flat.getNodeLength(),
          "_PTR     _EXFUN(memchr,(const _PTR, int, size_t));".length()); // $NON-NLS-1$

      IASTDeclarator d = memchr.getDeclarators()[0];
      IASTFileLocation f = d.getFileLocation();
      assertEquals(
          code.indexOf("_PTR     _EXFUN(memchr,(const _PTR, int, size_t))"),
          f.getNodeOffset()); // $NON-NLS-1$
      assertEquals(
          "_PTR     _EXFUN(memchr,(const _PTR, int, size_t))".length(),
          f.getNodeLength()); // $NON-NLS-1$
    }
  }
  private void visitType(IASTSimpleDeclaration declaration) throws BadLocationException {
    /* TODO: specific params: include type('class' / 'struct') */

    IASTDeclSpecifier spec = declaration.getDeclSpecifier();
    if (spec instanceof IASTCompositeTypeSpecifier) {
      String hint = ((IASTCompositeTypeSpecifier) spec).getName().getRawSignature();
      if (hint.isEmpty()) return;

      IASTFileLocation location = declaration.getFileLocation();
      int endLoc = location.getNodeOffset() + location.getNodeLength() - 1;
      int startLoc = location.getNodeOffset();
      _container.add(new Hint("type", startLoc, endLoc, hint)); // $NON-NLS-1$
    }

    if (spec instanceof ICPPASTNamedTypeSpecifier) {
      IASTName name = ((ICPPASTNamedTypeSpecifier) spec).getName();
      addBrackets(name);
    }
  }