6

Using the GNAT compiler, when I try to compile or check semantic on the following files, I get some variation of the error package "Foo" does not allow a body. I'm new to the language and can't find an answer to this seemingly basic problem anywhere on the Internet. Please advise.

foo.ads

package Foo is
   type Shape_Enum is (Circle, Triangle, Rectangle);
end Foo;

foo.adb

package body Foo is
   procedure Foo is
      MyShape : Shape_Enum;
   begin
      MyShape := Rectangle;
   end Foo;   
end Foo;
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
weberc2
  • 7,423
  • 4
  • 41
  • 57

3 Answers3

10

A package is only allowed to have a body if the specification includes something that requires a body. (This avoid problems where an optional body might accidentally be left out of a build.)

You have a procedure in the body of the package (Foo.Foo), but there's no way to call it.

If you add a declaration:

procedure Foo;

to the specification, that should (a) fix the error, and (b) permit the procedure to be called by clients of the package. Or you can use pragma Elaborate_Body; to require it to have a body if you don't want the procedure to be visible to clients.

Incidentally, there's nothing special about a procedure with the same name as the package that contains it (unlike in C++, where such a function is a constructor for the containing class). It would probably be clearer to use a different name.

See section 7.2 of the Ada Reference Manual (I'm using a recent draft of the 2012 standard):

A package_body shall be the completion of a previous package_declaration or generic_package_declaration. A library package_declaration or library generic_package_declaration shall not have a body unless it requires a body; pragma Elaborate_Body can be used to require a library_unit_declaration to have a body (see 10.2.1) if it would not otherwise require one.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • Thank you sincerely for your help. I'd consider a different name, but I've never spent so much time on such simple problems and found so little useful information on the Internet. I'm sure Ada is positively wonderful in some obscure way. – weberc2 Sep 27 '12 at 23:11
  • I typed into Google and found http://www.adaic.org/resources/add_content/standards/05aarm/html/AA-7-2.html as the top hit, which seems as though it might have helped. But I've been using Ada for a while now, so I'm not the person to judge! – Simon Wright Sep 28 '12 at 07:34
  • This issue just came up at work. Note that there is a difference between the two. If your "unexpectedly required" package has `begin...end` body code you want run, it is quite possible that `pragma elaborate_body` may cause elaboration issues (even circularities). In this case, the fake procedure method is a better solution. In other words, `Elaborate_Body` has side effects that you may not find desirable, whereas the dummy routine method does not. – T.E.D. Mar 15 '13 at 14:32
3

You could also declare the function to be private by adding:

private
    procedure Foo;

to the specification. Which will prevent it's use outside of the package.

Melllvar
  • 46
  • 4
2

Apparently Ada needs you to explicitly force a package body with pragma elaborate_body. I found the answer here:

http://objectmix.com/ada/338459-erreur-de-compilation.html#post1225079 (thank God I speak French):

ORIGINAL

entier_paquetage.adb:4:01: spec of this package does not allow a body

Si la spec ne demande pas un corps, le corps n'est pas autorisé. On peut forcer un corps en mettant "pragma elaborate_body;" dans la spec.

English

If the spec doesn't demand (or ask for) a body, the body will not be authorize . We can force a body by putting "pragma elaborate_body;"

Community
  • 1
  • 1
weberc2
  • 7,423
  • 4
  • 41
  • 57
  • That's one way. Of course one could ask why you want a package body when nothing in there can be run, used, or invoked in any way. Isn't that all dead code? – T.E.D. Sep 28 '12 at 12:46
  • That depends on what you mean by "dead code". All it does is set a variable value, which in and of itself is worthless; however, I've made my example as simple as possible so as to isolate the cause. Moreover, Ada seems extremely counter-intuitive and GNAT's errors are of little help, so it seems necessary to eliminate as much Ada-convolution as possible. – weberc2 Sep 28 '12 at 13:27
  • By "dead code" I mean code that cannot be reached from the program's entry point, or (in Ada's case) the entry point of any task. A subroutine in a package body that isn't in the spec, isn't called from the package's own "begin...end" code, isn't called directly or indirectly by another routine declared in the package spec, and isn't called from a task defined in that same package body, cannot be reached by anything. It's dead code. – T.E.D. Sep 28 '12 at 15:17
  • I didn't realize Ada doesn't know how to execute code specified apart from the spec. Had I known that, I wouldn't have posted this question. ;) – weberc2 Sep 28 '12 at 16:13
  • 2
    It isn't really an Ada thing, its a simple matter of scope. You'd have this issue in *any* language that supports this kind of modularity (Modula-2, C++, etc). For example, the C++ equivalent would be creating a class with no public methods or constructors, and then being surprised when the linker optimizes away your private methods. – T.E.D. Sep 28 '12 at 18:27
  • 2
    Though a valid case for Elaborate_Body could be a task that's not meant to be called by clients and has no public spec. – Álex Sep 28 '12 at 22:48
  • @T.E.D., not true, I don't have to declare a function in a c++ header file in order to use it in a program: http://pastebin.com/VtnAsEcJ I understand there is a difference between Ada spec files and .h files; however, that difference is the "Ada thing..." I was referring to. – weberc2 Sep 30 '12 at 20:12
  • @weberc2 - I did not say anything about "header file"s. I was talking about C++ class declarations. "header files" are a hack that C programmers learned to use a long time ago to provide kind of a poor-man's modularity feature. I understand the C++ folks are looking at replacing them with a real module feature sometime in the future (http://stackoverflow.com/questions/3596147/modules-in-c11), but for now C++ users are stuck with `#include` – T.E.D. Sep 30 '12 at 21:43
  • @T.E.D. I wasn't making a class in Ada; I was making a module with a function--the same as I demonstrated in C++. The fact that Ada requires me to declare a procedure in the specification is counter intuitive, and the fact that there is no decent online documentation (please don't point me to the Ada reference manual! :p ) is worse. I'm not arguing the merits of header files--generally I try to avoid both C++ and Ada in favor of languages that are easy to troubleshoot. – weberc2 Oct 01 '12 at 01:28