Merge from trunk.
[bpt/emacs.git] / lisp / emacs-lisp / advice.el
index a245a91..ecaf686 100644 (file)
@@ -1,6 +1,6 @@
-;;; advice.el --- an overloading mechanism for Emacs Lisp functions
+;;; advice.el --- An overloading mechanism for Emacs Lisp functions  -*- lexical-binding: t -*-
 
-;; Copyright (C) 1993-1994, 2000-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1993-1994, 2000-2012 Free Software Foundation, Inc.
 
 ;; Author: Hans Chalupsky <hans@cs.buffalo.edu>
 ;; Maintainer: FSF
 
 ;;; Commentary:
 
-;; NOTE: This documentation is slightly out of date. In particular, all the
-;; references to Emacs-18 are obsolete now, because it is not any longer
-;; supported by this version of Advice.
-
 ;; Advice is documented in the Emacs Lisp Manual.
 
 ;; @ Introduction:
 ;; - Provides manipulation mechanisms for sets of advised functions via
 ;;   regular expressions that match advice names
 
-;; @ How to get Advice for Emacs-18:
-;; =================================
-;; `advice18.el', a version of Advice that also works in Emacs-18 is available
-;; either via anonymous ftp from `ftp.cs.buffalo.edu (128.205.32.9)' with
-;; pathname `/pub/Emacs/advice18.el', or from one of the Emacs Lisp archive
-;; sites, or send email to <hans@cs.buffalo.edu> and I'll mail it to you.
-
 ;; @ Overview, or how to read this file:
 ;; =====================================
-;; NOTE: This documentation is slightly out of date. In particular, all the
-;; references to Emacs-18 are obsolete now, because it is not any longer
-;; supported by this version of Advice. An up-to-date version will soon be
-;; available as an info file (thanks to the kind help of Jack Vinson and
-;; David M. Smith). Until then you can use `outline-mode' to help you read
-;; this documentation (set `outline-regexp' to `";; @+"').
+;; You can use `outline-mode' to help you read this documentation (set
+;; `outline-regexp' to `";; @+"').
 ;;
 ;; The four major sections of this file are:
 ;;
 
 ;; @ Restrictions:
 ;; ===============
-;; - This version of Advice only works for Emacs 19.26 and later. It uses
-;;   new versions of the built-in functions `fset/defalias' which are not
-;;   yet available in Lucid Emacs, hence, it won't work there.
 ;; - Advised functions/macros/subrs will only exhibit their advised behavior
 ;;   when they are invoked via their function cell. This means that advice will
 ;;   not work for the following:
 
 ;; @@ Terminology:
 ;; ===============
-;; - Emacs, Emacs-19: Emacs as released by the GNU Project
-;; - Lemacs: Lucid's version of Emacs with major version 19
-;; - v18: Any Emacs with major version 18 or built as an extension to that
-;;        (such as Epoch)
-;; - v19: Any Emacs with major version 19
-;; - jwz: Jamie Zawinski - former keeper of Lemacs and creator of the optimizing
-;;        byte-compiler used in v19s.
+;; - Emacs: Emacs as released by the GNU Project
+;; - jwz: Jamie Zawinski - creator of the byte-compiler used in v19s.
 ;; - Advice: The name of this package.
 ;; - advices: Short for "pieces of advice".
 
 ;;              generates a compiled advised definition according to the
 ;;              current advice state which will be used during activation
 ;;              if appropriate. Only use this if the `defadvice' gets
-;;              actually compiled (with a v18 byte-compiler put the `defadvice'
-;;              into the body of a `defun' to accomplish proper compilation).
+;;              actually compiled.
 
 ;; An optional <documentation-string> can be supplied to document the advice.
 ;; On call of the `documentation' function it will be combined with the
 ;; first argument list defined in the list of before/around/after advices.
 ;; The values of <arglist> variables can be accessed/changed in the body of
 ;; an advice by simply referring to them by their original name, however,
-;; more portable argument access macros are also provided (see below).  For
-;; subrs/special-forms for which neither explicit argument list definitions
-;; are available, nor their documentation strings contain such definitions
-;; (as they do v19s), `(&rest ad-subr-args)' will be used.
+;; more portable argument access macros are also provided (see below).
 
 ;; <advised-docstring> is an optional, special documentation string which will
 ;; be expanded into a proper documentation string upon call of `documentation'.
 ;; gets redefined in a non-advice style into a function by the edebug
 ;; package. If the advice assumes `eval-region' to be a subr it might break
 ;; once edebug is loaded. Similar situations arise when one wants to use the
-;; same piece of advice across different versions of Emacs. Some subrs in a
-;; v18 Emacs are functions in v19 and vice versa, but for the most part the
-;; semantics remain the same, hence, the same piece of advice might be usable
-;; in both Emacs versions.
+;; same piece of advice across different versions of Emacs.
 
 ;; As a solution to that advice provides argument list access macros that get
 ;; translated into the proper access forms at activation time, i.e., when the
 
 ;; @@@ Argument list mapping:
 ;; ==========================
-;; Because `defadvice' allows the specification of the argument list of the
-;; advised function we need a mapping mechanism that maps this argument list
-;; onto that of the original function. For example, somebody might specify
-;; `(sym newdef)' as the argument list of `fset', while advice might use
-;; `(&rest ad-subr-args)' as the argument list of the original function
-;; (depending on what Emacs version is used). Hence SYM and NEWDEF have to
-;; be properly mapped onto the &rest variable when the original definition is
-;; called. Advice automatically takes care of that mapping, hence, the advice
-;; programmer can specify an argument list without having to know about the
-;; exact structure of the original argument list as long as the new argument
-;; list takes a compatible number/magnitude of actual arguments.
+;; Because `defadvice' allows the specification of the argument list
+;; of the advised function we need a mapping mechanism that maps this
+;; argument list onto that of the original function. Hence SYM and
+;; NEWDEF have to be properly mapped onto the &rest variable when the
+;; original definition is called. Advice automatically takes care of
+;; that mapping, hence, the advice programmer can specify an argument
+;; list without having to know about the exact structure of the
+;; original argument list as long as the new argument list takes a
+;; compatible number/magnitude of actual arguments.
 
 ;; @@ Activation and deactivation:
 ;; ===============================
 ;; defined. The special forms `defun' and `defmacro' have been advised to
 ;; check whether the function/macro they defined had advice information
 ;; associated with it. If so and forward advice is enabled, the original
-;; definition will be saved, and then the advice will be activated. When a
-;; file is loaded in a v18 Emacs the functions/macros it defines are also
-;; defined with calls to `defun/defmacro'.  Hence, we can forward advise
-;; functions/macros which will be defined later during a load/autoload of some
-;; file (for compiled files generated by jwz's byte-compiler in a v19 Emacs
-;; this is slightly more complicated but the basic idea is the same).
+;; definition will be saved, and then the advice will be activated.
 
 ;; @@ Enabling/disabling pieces or sets of advice:
 ;; ===============================================
 ;;
 ;;    (ad-activate-regexp "^ange-ftp-")
 ;;
-;; A saver way would have been to use
+;; A safer way would have been to use
 ;;
 ;;    (ad-update-regexp "^ange-ftp-")
 ;;
 ;; instead which would have only reactivated currently actively advised
-;; functions, but not functions that were currently deactivated. All these
+;; functions, but not functions that were currently inactive. All these
 ;; functions can also be called interactively.
 
 ;; A certain piece of advice is considered a match if its name contains a
 
 ;; @@@ Enabling automatic advice activation:
 ;; =========================================
-;; Automatic advice activation is enabled by default. It can be disabled by
-;; doint `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'.
+;; Automatic advice activation is enabled by default. It can be disabled with
+;; `M-x ad-stop-advice' and enabled again with `M-x ad-start-advice'.
 
 ;; @@ Caching of advised definitions:
 ;; ==================================
 ;; specified as disabled) and all other currently enabled pieces of advice to
 ;; construct an advised definition and an identifying cache-id and makes them
 ;; part of the `defadvice' expansion which will then be compiled by the
-;; byte-compiler (to ensure that in a v18 emacs you have to put the
-;; `defadvice' inside a `defun' to get it compiled and then you have to call
-;; that compiled `defun' in order to actually execute the `defadvice'). When
-;; the file with the compiled, preactivating `defadvice' gets loaded the
+;; byte-compiler.
+;; When the file with the compiled, preactivating `defadvice' gets loaded the
 ;; precompiled advised definition will be cached on the advised function's
 ;; advice-info. When it gets activated (can be immediately on execution of the
 ;; `defadvice' or any time later) the cache-id gets checked against the
 ;; advised definition of a function, rather they are assembled into a hook
 ;; form which will be evaluated whenever the advice-info of the advised
 ;; function gets activated or deactivated. One application of this mechanism
-;; is to define file load hooks for files that do not provide such hooks
-;; (v19s already come with a general file-load-hook mechanism, v18s don't).
+;; is to define file load hooks for files that do not provide such hooks.
 ;; For example, suppose you want to print a message whenever `file-x' gets
 ;; loaded, and suppose the last function defined in `file-x' is
 ;; `file-x-last-fn'.  Then we can define the following advice:
 ;;     Reactivate an advised function but only if its advice is currently
 ;;     active. This can be used to bring all currently advised function up
 ;;     to date with the current state of advice without also activating
-;;     currently deactivated functions.
+;;     currently inactive functions.
 ;; - Caching:
 ;;     Is the saving of an advised definition and an identifying cache-id so
 ;;     it can be reused, for example, for activation after deactivation.
 ;; - ad-activate to activate the advice of a FUNCTION
 ;; - ad-deactivate to deactivate the advice of a FUNCTION
 ;; - ad-update   to activate the advice of a FUNCTION unless it was not
-;;               yet activated or is currently deactivated.
+;;               yet activated or is currently inactive.
 ;; - ad-unadvise deactivates a FUNCTION and removes all of its advice
 ;;               information, hence, it cannot be activated again
 ;; - ad-recover  tries to redefine a FUNCTION to its original definition and
 ;; @@ Summary of forms with special meanings when used within an advice:
 ;; =====================================================================
 ;;   ad-return-value   name of the return value variable (get/settable)
-;;   ad-subr-args      name of &rest argument variable used for advised
-;;                     subrs whose actual argument list cannot be
-;;                     determined (get/settable)
 ;;   (ad-get-arg <pos>), (ad-get-args <pos>),
 ;;   (ad-set-arg <pos> <value>), (ad-set-args <pos> <value-list>)
 ;;                     argument access text macros to get/set the values of
 ;; contain some advice matched by the regular expression. This is a save
 ;; way to update the activation of advised functions whose advice changed
 ;; in some way or other without accidentally also activating currently
-;; deactivated functions:
+;; inactive functions:
 ;;
 ;; (ad-update-regexp "^fg-")
 ;; nil
 ;;
 ;; If you put a preactivating `defadvice' into a Lisp file that gets byte-
 ;; compiled then the constructed advised definition will get compiled by
-;; the byte-compiler. For that to occur in a v18 emacs you have to put the
-;; `defadvice' inside a `defun' because the v18 compiler does not compile
+;; the byte-compiler. For that to occur in a v18 Emacs you had to put the
+;; `defadvice' inside a `defun' because the v18 compiler did not compile
 ;; top-level forms other than `defun' or `defmacro', for example,
 ;;
 ;; (defun fg-defadvice-fum ()
 ;; if one advises a subr such as `eval-region' which then gets redefined by
 ;; some package (e.g., edebug) into a function with different argument names,
 ;; then a piece of advice written for `eval-region' that was written with
-;; the subr arguments in mind will break. Similar situations arise when one
-;; switches between major Emacs versions, e.g., certain subrs in v18 are
-;; functions in v19 and vice versa. Also, in v19s subr argument lists
-;; are available and will be used, while they are not available in v18.
+;; the subr arguments in mind will break.
 ;;
 ;; Argument access text macros allow one to access arguments of an advised
 ;; function in a portable way without having to worry about all these
 ;; fii
 ;;
 ;; Now we advise `fii' to use an optional second argument that controls the
-;; amount of incrementation. A list following the (optional) position
+;; amount of incrementing. A list following the (optional) position
 ;; argument of the advice will be interpreted as an argument list
 ;; specification. This means you cannot specify an empty argument list, and
 ;; why would you want to anyway?
 (provide 'advice-preload)
 ;; During a normal load this is a noop:
 (require 'advice-preload "advice.el")
-
+(require 'macroexp)
+;; At run-time also, since ad-do-advised-functions returns code that uses it.
+(require 'cl-lib)
 
 ;; @@ Variable definitions:
 ;; ========================
@@ -1820,84 +1776,6 @@ generates a copy of TREE."
          (funcall fUnCtIoN tReE))
         (t tReE)))
 
-;; this is just faster than `ad-substitute-tree':
-(defun ad-copy-tree (tree)
-  "Return a copy of the list structure of TREE."
-  (cond ((consp tree)
-        (cons (ad-copy-tree (car tree))
-              (ad-copy-tree (cdr tree))))
-       (t tree)))
-
-(defmacro ad-dolist (varform &rest body)
-  "A Common-Lisp-style dolist iterator with the following syntax:
-
-    (ad-dolist (VAR INIT-FORM [RESULT-FORM])
-       BODY-FORM...)
-
-which will iterate over the list yielded by INIT-FORM binding VAR to the
-current head at every iteration.  If RESULT-FORM is supplied its value will
-be returned at the end of the iteration, nil otherwise.  The iteration can be
-exited prematurely with `(ad-do-return [VALUE])'."
-  (let ((expansion
-         `(let ((ad-dO-vAr ,(car (cdr varform)))
-                ,(car varform))
-           (while ad-dO-vAr
-             (setq ,(car varform) (car ad-dO-vAr))
-             ,@body
-             ;;work around a backquote bug:
-             ;;(` ((,@ '(foo)) (bar))) => (append '(foo) '(((bar)))) wrong
-             ;;(` ((,@ '(foo)) (, '(bar)))) => (append '(foo) (list '(bar)))
-             ,'(setq ad-dO-vAr (cdr ad-dO-vAr)))
-           ,(car (cdr (cdr varform))))))
-    ;;ok, this wastes some cons cells but only during compilation:
-    (if (catch 'contains-return
-         (ad-substitute-tree
-          (function (lambda (subtree)
-             (cond ((eq (car-safe subtree) 'ad-dolist))
-                   ((eq (car-safe subtree) 'ad-do-return)
-                    (throw 'contains-return t)))))
-          'identity body)
-         nil)
-       `(catch 'ad-dO-eXiT ,expansion)
-        expansion)))
-
-(defmacro ad-do-return (value)
-  `(throw 'ad-dO-eXiT ,value))
-
-(if (not (get 'ad-dolist 'lisp-indent-hook))
-    (put 'ad-dolist 'lisp-indent-hook 1))
-
-
-;; @@ Save real definitions of subrs used by Advice:
-;; =================================================
-;; Advice depends on the real, unmodified functionality of various subrs,
-;; we save them here so advised versions will not interfere (eventually,
-;; we will save all subrs used in code generated by Advice):
-
-(defmacro ad-save-real-definition (function)
-  (let ((saved-function (intern (format "ad-real-%s" function))))
-    ;; Make sure the compiler is loaded during macro expansion:
-    (require 'byte-compile "bytecomp")
-    `(if (not (fboundp ',saved-function))
-      (progn (fset ',saved-function (symbol-function ',function))
-             ;; Copy byte-compiler properties:
-             ,@(if (get function 'byte-compile)
-                   `((put ',saved-function 'byte-compile
-                      ',(get function 'byte-compile))))
-             ,@(if (get function 'byte-opcode)
-                   `((put ',saved-function 'byte-opcode
-                      ',(get function 'byte-opcode))))))))
-
-(defun ad-save-real-definitions ()
-  ;; Macro expansion will hardcode the values of the various byte-compiler
-  ;; properties into the compiled version of this function such that the
-  ;; proper values will be available at runtime without loading the compiler:
-  (ad-save-real-definition fset)
-  (ad-save-real-definition documentation))
-
-(ad-save-real-definitions)
-
-
 ;; @@ Advice info access fns:
 ;; ==========================
 
@@ -1932,19 +1810,15 @@ exited prematurely with `(ad-do-return [VALUE])'."
      ad-advised-functions)))
 
 (defmacro ad-do-advised-functions (varform &rest body)
-  "`ad-dolist'-style iterator that maps over `ad-advised-functions'.
-\(ad-do-advised-functions (VAR [RESULT-FORM])
+  "`dolist'-style iterator that maps over advised functions.
+\(ad-do-advised-functions (VAR)
    BODY-FORM...)
 On each iteration VAR will be bound to the name of an advised function
 \(a symbol)."
-  `(ad-dolist (,(car varform)
-               ad-advised-functions
-               ,(car (cdr varform)))
-    (setq ,(car varform) (intern (car ,(car varform))))
-    ,@body))
-
-(if (not (get 'ad-do-advised-functions 'lisp-indent-hook))
-    (put 'ad-do-advised-functions 'lisp-indent-hook 1))
+  (declare (indent 1))
+  `(cl-dolist (,(car varform) ad-advised-functions)
+     (setq ,(car varform) (intern (car ,(car varform))))
+     ,@body))
 
 (defun ad-get-advice-info (function)
   (get function 'ad-advice-info))
@@ -1952,16 +1826,23 @@ On each iteration VAR will be bound to the name of an advised function
 (defmacro ad-get-advice-info-macro (function)
   `(get ,function 'ad-advice-info))
 
-(defmacro ad-set-advice-info (function advice-info)
-  `(put ,function 'ad-advice-info ,advice-info))
+(defsubst ad-set-advice-info (function advice-info)
+  (cond
+   (advice-info
+    (add-function :around (get function 'defalias-fset-function)
+                  #'ad--defalias-fset))
+   ((get function 'defalias-fset-function)
+    (remove-function (get function 'defalias-fset-function)
+                     #'ad--defalias-fset)))
+  (put function 'ad-advice-info advice-info))
 
 (defmacro ad-copy-advice-info (function)
-  `(ad-copy-tree (get ,function 'ad-advice-info)))
+  `(copy-tree (get ,function 'ad-advice-info)))
 
 (defmacro ad-is-advised (function)
   "Return non-nil if FUNCTION has any advice info associated with it.
 This does not mean that the advice is also active."
-  (list 'ad-get-advice-info-macro function))
+  `(ad-get-advice-info-macro ,function))
 
 (defun ad-initialize-advice-info (function)
   "Initialize the advice info for FUNCTION.
@@ -2030,8 +1911,8 @@ either t or nil, and DEFINITION should be a list of the form
 
 (defun ad-has-enabled-advice (function class)
   "True if at least one of FUNCTION's advices in CLASS is enabled."
-  (ad-dolist (advice (ad-get-advice-info-field function class))
-    (if (ad-advice-enabled advice) (ad-do-return t))))
+  (cl-dolist (advice (ad-get-advice-info-field function class))
+    (if (ad-advice-enabled advice) (cl-return t))))
 
 (defun ad-has-redefining-advice (function)
   "True if FUNCTION's advice info defines at least 1 redefining advice.
@@ -2044,14 +1925,14 @@ Redefining advices affect the construction of an advised definition."
 (defun ad-has-any-advice (function)
   "True if the advice info of FUNCTION defines at least one advice."
   (and (ad-is-advised function)
-       (ad-dolist (class ad-advice-classes nil)
+       (cl-dolist (class ad-advice-classes)
         (if (ad-get-advice-info-field function class)
-            (ad-do-return t)))))
+            (cl-return t)))))
 
 (defun ad-get-enabled-advices (function class)
   "Return the list of enabled advices of FUNCTION in CLASS."
   (let (enabled-advices)
-    (ad-dolist (advice (ad-get-advice-info-field function class))
+    (dolist (advice (ad-get-advice-info-field function class))
       (if (ad-advice-enabled advice)
          (push advice enabled-advices)))
     (reverse enabled-advices)))
@@ -2060,18 +1941,10 @@ Redefining advices affect the construction of an advised definition."
 ;; @@ Dealing with automatic advice activation via `fset/defalias':
 ;; ================================================================
 
-;; Since Emacs 19.26 the built-in versions of `fset' and `defalias'
-;; take care of automatic advice activation, hence, we don't have to
-;; hack it anymore by advising `fset/defun/defmacro/byte-code/etc'.
+;; Automatic activation happens when a function gets defined via `defalias',
+;; which calls the `defalias-fset-function' (which we set to
+;; `ad--defalias-fset') instead of `fset', if non-nil.
 
-;; The functionality of the new `fset' is as follows:
-;;
-;;     fset(sym,newdef)
-;;       assign NEWDEF to SYM
-;;       if (get SYM 'ad-advice-info)
-;;          ad-activate-internal(SYM, nil)
-;;       return (symbol-function SYM)
-;;
 ;; Whether advised definitions created by automatic activations will be
 ;; compiled depends on the value of `ad-default-compilation-action'.
 
@@ -2083,13 +1956,17 @@ Redefining advices affect the construction of an advised definition."
 ;; to `ad-activate' by using `ad-with-auto-activation-disabled' where
 ;; appropriate, especially in a safe version of `fset'.
 
+(defun ad--defalias-fset (fsetfun function definition)
+  (funcall (or fsetfun #'fset) function definition)
+  (ad-activate-internal function nil))
+
 ;; For now define `ad-activate-internal' to the dummy definition:
-(defun ad-activate-internal (function &optional compile)
+(defun ad-activate-internal (_function &optional _compile)
   "Automatic advice activation is disabled. `ad-start-advice' enables it."
   nil)
 
 ;; This is just a copy of the above:
-(defun ad-activate-internal-off (function &optional compile)
+(defun ad-activate-internal-off (_function &optional _compile)
   "Automatic advice activation is disabled. `ad-start-advice' enables it."
   nil)
 
@@ -2100,12 +1977,6 @@ Redefining advices affect the construction of an advised definition."
   `(let ((ad-activate-on-top-level nil))
     ,@body))
 
-(defun ad-safe-fset (symbol definition)
-  "A safe `fset' which will never call `ad-activate-internal' recursively."
-  (ad-with-auto-activation-disabled
-   (ad-real-fset symbol definition)))
-
-
 ;; @@ Access functions for original definitions:
 ;; ============================================
 ;; The advice-info of an advised function contains its `origname' which is
@@ -2125,8 +1996,7 @@ Redefining advices affect the construction of an advised definition."
         (symbol-function origname))))
 
 (defmacro ad-set-orig-definition (function definition)
-  `(ad-safe-fset
-    (ad-get-advice-info-field ,function 'origname) ,definition))
+  `(fset (ad-get-advice-info-field ,function 'origname) ,definition))
 
 (defmacro ad-clear-orig-definition (function)
   `(fmakunbound (ad-get-advice-info-field ,function 'origname)))
@@ -2147,7 +2017,7 @@ function at point for which PREDICATE returns non-nil)."
       (error "ad-read-advised-function: There are no advised functions"))
   (setq default
        (or default
-           ;; Prefer func name at point, if it's in ad-advised-functions etc.
+           ;; Prefer func name at point, if it's an advised function etc.
            (let ((function (progn
                              (require 'help)
                              (function-called-at-point))))
@@ -2156,24 +2026,20 @@ function at point for which PREDICATE returns non-nil)."
                   (or (null predicate)
                       (funcall predicate function))
                   function))
-           (ad-do-advised-functions (function)
-             (if (or (null predicate)
-                     (funcall predicate function))
-                 (ad-do-return function)))
+            (cl-block nil
+              (ad-do-advised-functions (function)
+                (if (or (null predicate)
+                        (funcall predicate function))
+                    (cl-return function))))
            (error "ad-read-advised-function: %s"
                   "There are no qualifying advised functions")))
-  (let* ((ad-pReDiCaTe predicate)
-        (function
+  (let* ((function
          (completing-read
           (format "%s (default %s): " (or prompt "Function") default)
           ad-advised-functions
           (if predicate
-              (function
-               (lambda (function)
-                 ;; Oops, no closures - the joys of dynamic scoping:
-                 ;; `predicate' clashed with the `predicate' argument
-                 ;; of Lemacs' `completing-read'.....
-                 (funcall ad-pReDiCaTe (intern (car function))))))
+               (lambda (function)
+                 (funcall predicate (intern (car function)))))
           t)))
     (if (equal function "")
        (if (ad-is-advised default)
@@ -2192,9 +2058,9 @@ be returned on empty input (defaults to the first non-empty advice
 class of FUNCTION)."
   (setq default
        (or default
-           (ad-dolist (class ad-advice-classes)
+           (cl-dolist (class ad-advice-classes)
              (if (ad-get-advice-info-field function class)
-                 (ad-do-return class)))
+                 (cl-return class)))
            (error "ad-read-advice-class: `%s' has no advices" function)))
   (let ((class (completing-read
                (format "%s (default %s): " (or prompt "Class") default)
@@ -2263,18 +2129,18 @@ NAME can be a symbol or a regular expression matching part of an advice name.
 If CLASS is `any' all valid advice classes will be checked."
   (if (ad-is-advised function)
       (let (found-advice)
-       (ad-dolist (advice-class ad-advice-classes)
+       (cl-dolist (advice-class ad-advice-classes)
          (if (or (eq class 'any) (eq advice-class class))
              (setq found-advice
-                   (ad-dolist (advice (ad-get-advice-info-field
+                   (cl-dolist (advice (ad-get-advice-info-field
                                        function advice-class))
                      (if (or (and (stringp name)
                                   (string-match
                                    name (symbol-name
                                          (ad-advice-name advice))))
                              (eq name (ad-advice-name advice)))
-                         (ad-do-return advice)))))
-         (if found-advice (ad-do-return found-advice))))))
+                         (cl-return advice)))))
+         (if found-advice (cl-return found-advice))))))
 
 (defun ad-enable-advice-internal (function class name flag)
   "Set enable FLAG of FUNCTION's advices in CLASS matching NAME.
@@ -2285,10 +2151,10 @@ considered.  The number of changed advices will be returned (or nil if
 FUNCTION was not advised)."
   (if (ad-is-advised function)
       (let ((matched-advices 0))
-       (ad-dolist (advice-class ad-advice-classes)
+       (dolist (advice-class ad-advice-classes)
          (if (or (eq class 'any) (eq advice-class class))
-             (ad-dolist (advice (ad-get-advice-info-field
-                                 function advice-class))
+             (dolist (advice (ad-get-advice-info-field
+                               function advice-class))
                (cond ((or (and (stringp name)
                                (string-match
                                 name (symbol-name (ad-advice-name advice))))
@@ -2426,12 +2292,6 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
   "Take a macro function DEFINITION and make a lambda out of it."
   `(cdr ,definition))
 
-(defun ad-special-form-p (definition)
-  "Non-nil if and only if DEFINITION is a special form."
-  (if (and (symbolp definition) (fboundp definition))
-      (setq definition (indirect-function definition)))
-  (and (subrp definition) (eq (cdr (subr-arity definition)) 'unevalled)))
-
 (defmacro ad-subr-p (definition)
   ;;"non-nil if DEFINITION is a subr."
   (list 'subrp definition))
@@ -2449,12 +2309,6 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
   ;;"non-nil if DEFINITION is a piece of advice."
   `(eq (car-safe ,definition) 'advice))
 
-;; Emacs/Lemacs cross-compatibility
-;; (compiled-function-p is an obsolete function in Emacs):
-(if (and (not (fboundp 'byte-code-function-p))
-        (fboundp 'compiled-function-p))
-    (ad-safe-fset 'byte-code-function-p 'compiled-function-p))
-
 (defmacro ad-compiled-p (definition)
   "Return non-nil if DEFINITION is a compiled byte-code object."
   `(or (byte-code-function-p ,definition)
@@ -2477,10 +2331,8 @@ See Info node `(elisp)Computed Advice' for detailed documentation."
         (cdr definition))
        (t nil)))
 
-(defun ad-arglist (definition &optional name)
-  "Return the argument list of DEFINITION.
-If DEFINITION could be from a subr then its NAME should be
-supplied to make subr arglist lookup more efficient."
+(defun ad-arglist (definition)
+  "Return the argument list of DEFINITION."
   (require 'help-fns)
   (help-function-arglist
    (if (or (ad-macro-p definition) (ad-advice-p definition))
@@ -2492,7 +2344,7 @@ supplied to make subr arglist lookup more efficient."
   "Return the unexpanded docstring of DEFINITION."
   (let ((docstring
         (if (ad-compiled-p definition)
-            (ad-real-documentation definition t)
+            (documentation definition t)
           (car (cdr (cdr (ad-lambda-expression definition)))))))
     (if (or (stringp docstring)
            (natnump docstring))
@@ -2515,13 +2367,15 @@ Like `interactive-form', but also works on pieces of advice."
                    (if (ad-interactive-form definition) 1 0))
                 (cdr (cdr (ad-lambda-expression definition)))))))
 
-(defun ad-make-advised-definition-docstring (function)
+(defun ad-make-advised-definition-docstring (_function)
   "Make an identifying docstring for the advised definition of FUNCTION.
 Put function name into the documentation string so we can infer
 the name of the advised function from the docstring.  This is needed
 to generate a proper advised docstring even if we are just given a
 definition (see the code for `documentation')."
-  (propertize "Advice doc string" 'ad-advice-info function))
+  (eval-when-compile
+    (propertize "Advice doc string" 'dynamic-docstring-function
+                #'ad--make-advised-docstring)))
 
 (defun ad-advised-definition-p (definition)
   "Return non-nil if DEFINITION was generated from advice information."
@@ -2530,14 +2384,14 @@ definition (see the code for `documentation')."
          (ad-compiled-p definition))
       (let ((docstring (ad-docstring definition)))
        (and (stringp docstring)
-            (get-text-property 0 'ad-advice-info docstring)))))
+            (get-text-property 0 'dynamic-docstring-function docstring)))))
 
 (defun ad-definition-type (definition)
   "Return symbol that describes the type of DEFINITION."
   (cond
    ((ad-macro-p definition) 'macro)
    ((ad-subr-p definition)
-    (if (ad-special-form-p definition)
+    (if (special-form-p definition)
         'special-form
       'subr))
    ((or (ad-lambda-p definition)
@@ -2550,7 +2404,7 @@ definition (see the code for `documentation')."
 For that it has to be fbound with a non-autoload definition."
   (and (symbolp function)
        (fboundp function)
-       (not (eq (car-safe (symbol-function function)) 'autoload))))
+       (not (autoloadp (symbol-function function)))))
 
 ;; The following two are necessary for the sake of packages such as
 ;; ange-ftp which redefine functions via fcell indirection:
@@ -2574,6 +2428,7 @@ For that it has to be fbound with a non-autoload definition."
           (ad-macro-p (symbol-function function)))
        (not (ad-compiled-p (symbol-function function)))))
 
+(defvar warning-suppress-types)         ;From warnings.el.
 (defun ad-compile-function (function)
   "Byte-compiles FUNCTION (or macro) if it is not yet compiled."
   (interactive "aByte-compile function: ")
@@ -2594,41 +2449,6 @@ For that it has to be fbound with a non-autoload definition."
         (byte-compile symbol)
         (fset function (symbol-function symbol))))))
 
-
-;; @@ Constructing advised definitions:
-;; ====================================
-;;
-;; Main design decisions about the form of advised definitions:
-;;
-;; A) How will original definitions be called?
-;; B) What will argument lists of advised functions look like?
-;;
-;; Ad A)
-;;    I chose to use function indirection for all four types of original
-;;    definitions (functions, macros, subrs and special forms), i.e., create
-;;    a unique symbol `ad-Orig-<name>' which is fbound to the original
-;;    definition and call it according to type and arguments.  Functions and
-;;    subrs that don't have any &rest arguments can be called directly in a
-;;    `(ad-Orig-<name> ....)' form.  If they have a &rest argument we have to
-;;    use `apply'.  Macros will be called with
-;;    `(macroexpand '(ad-Orig-<name> ....))', and special forms also need a
-;;    form like that with `eval' instead of `macroexpand'.
-;;
-;; Ad B)
-;;    Use original arguments where possible and `(&rest ad-subr-args)'
-;;    otherwise, even though this seems to be more complicated and less
-;;    uniform than a general `(&rest args)' approach.  My reason to still
-;;    do it that way is that in most cases my approach leads to the more
-;;    efficient form for the advised function, and portability (e.g., to
-;;    make the same advice work regardless of whether something is a
-;;    function or a subr) can still be achieved with argument access macros.
-
-
-(defun ad-prognify (forms)
-  (cond ((<= (length forms) 1)
-        (car forms))
-       (t (cons 'progn forms))))
-
 ;; @@@ Accessing argument lists:
 ;; =============================
 
@@ -2739,24 +2559,20 @@ The assignment starts at position INDEX."
   (let ((values-index 0)
        argument-access set-forms)
     (while (setq argument-access (ad-access-argument arglist index))
-      (if (symbolp argument-access)
-         (setq set-forms
-               (cons (ad-set-argument
-                      arglist index
-                      (ad-element-access values-index 'ad-vAlUeS))
-                     set-forms))
-          (setq set-forms
-                (cons (if (= (car argument-access) 0)
-                          (list 'setq
-                                (car (cdr argument-access))
-                                (ad-list-access values-index 'ad-vAlUeS))
-                          (list 'setcdr
-                                (ad-list-access (1- (car argument-access))
-                                                (car (cdr argument-access)))
-                                (ad-list-access values-index 'ad-vAlUeS)))
-                      set-forms))
-          ;; terminate loop
-          (setq arglist nil))
+      (push (if (symbolp argument-access)
+                (ad-set-argument
+                 arglist index
+                 (ad-element-access values-index 'ad-vAlUeS))
+              (setq arglist nil) ;; Terminate loop.
+              (if (= (car argument-access) 0)
+                  `(setq
+                    ,(car (cdr argument-access))
+                    ,(ad-list-access values-index 'ad-vAlUeS))
+                `(setcdr
+                  ,(ad-list-access (1- (car argument-access))
+                                   (car (cdr argument-access)))
+                  ,(ad-list-access values-index 'ad-vAlUeS))))
+            set-forms)
       (setq index (1+ index))
       (setq values-index (1+ values-index)))
     (if (null set-forms)
@@ -2765,8 +2581,8 @@ The assignment starts at position INDEX."
         (if (= (length set-forms) 1)
             ;; For exactly one set-form we can use values-form directly,...
             (ad-substitute-tree
-             (function (lambda (form) (eq form 'ad-vAlUeS)))
-             (function (lambda (form) values-form))
+             (lambda (form) (eq form 'ad-vAlUeS))
+             (lambda (_form) values-form)
              (car set-forms))
             ;; ...if we have more we have to bind it to a variable:
             `(let ((ad-vAlUeS ,values-form))
@@ -2836,11 +2652,10 @@ Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return
            (cond (need-apply
                   ;; `apply' can take care of that directly:
                   (append source-reqopt-args (list source-rest-arg)))
-                 (t (mapcar (function
-                             (lambda (arg)
-                               (setq target-arg-index (1+ target-arg-index))
-                               (ad-get-argument
-                                source-arglist target-arg-index)))
+                 (t (mapcar (lambda (_arg)
+                               (setq target-arg-index (1+ target-arg-index))
+                               (ad-get-argument
+                                source-arglist target-arg-index))
                             (append target-reqopt-args
                                     (and target-rest-arg
                                          ;; If we have a rest arg gobble up
@@ -2871,11 +2686,6 @@ Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return
   (let ((advice-docstring (ad-docstring (ad-advice-definition advice))))
     (cond ((eq style 'plain)
           advice-docstring)
-         ((eq style 'freeze)
-          (format "Permanent %s-advice `%s':%s%s"
-                  class (ad-advice-name advice)
-                  (if advice-docstring "\n" "")
-                  (or advice-docstring "")))
          (t (if advice-docstring
                 (format "%s-advice `%s':\n%s"
                         (capitalize (symbol-name class))
@@ -2888,26 +2698,30 @@ Example: `(ad-map-arglists '(a &rest args) '(w x y z))' will return
 (require 'help-fns)        ;For help-split-fundoc and help-add-fundoc-usage.
 
 (defun ad-make-advised-docstring (function &optional style)
+  (let* ((origdef (ad-real-orig-definition function))
+        (origdoc
+         ;; Retrieve raw doc, key substitution will be taken care of later:
+         (documentation origdef t)))
+    (ad--make-advised-docstring origdoc function style)))
+
+(defun ad--make-advised-docstring (origdoc function &optional style)
   "Construct a documentation string for the advised FUNCTION.
 It concatenates the original documentation with the documentation
 strings of the individual pieces of advice which will be formatted
-according to STYLE.  STYLE can be `plain' or `freeze', everything else
+according to STYLE.  STYLE can be `plain', everything else
 will be interpreted as `default'.  The order of the advice documentation
 strings corresponds to before/around/after and the individual ordering
 in any of these classes."
   (let* ((origdef (ad-real-orig-definition function))
         (origtype (symbol-name (ad-definition-type origdef)))
-        (origdoc
-         ;; Retrieve raw doc, key substitution will be taken care of later:
-         (ad-real-documentation origdef t))
         (usage (help-split-fundoc origdoc function))
-        paragraphs advice-docstring ad-usage)
+        paragraphs advice-docstring)
     (setq usage (if (null usage) t (setq origdoc (cdr usage)) (car usage)))
     (if origdoc (setq paragraphs (list origdoc)))
     (unless (eq style 'plain)
       (push (concat "This " origtype " is advised.") paragraphs))
-    (ad-dolist (class ad-advice-classes)
-      (ad-dolist (advice (ad-get-enabled-advices function class))
+    (dolist (class ad-advice-classes)
+      (dolist (advice (ad-get-enabled-advices function class))
        (setq advice-docstring
              (ad-make-single-advice-docstring advice class style))
        (if advice-docstring
@@ -2916,37 +2730,37 @@ in any of these classes."
                      (propertize
                       ;; separate paragraphs with blank lines:
                       (mapconcat 'identity (nreverse paragraphs) "\n\n")
-                      'ad-advice-info function)))
+                       ;; FIXME: what is this for?
+                      'dynamic-docstring-function
+                       #'ad--make-advised-docstring)))
     (help-add-fundoc-usage origdoc usage)))
 
 (defun ad-make-plain-docstring (function)
   (ad-make-advised-docstring function 'plain))
-(defun ad-make-freeze-docstring (function)
-  (ad-make-advised-docstring function 'freeze))
 
 ;; @@@ Accessing overriding arglists and interactive forms:
 ;; ========================================================
 
 (defun ad-advised-arglist (function)
   "Find first defined arglist in FUNCTION's redefining advices."
-  (ad-dolist (advice (append (ad-get-enabled-advices function 'before)
+  (cl-dolist (advice (append (ad-get-enabled-advices function 'before)
                             (ad-get-enabled-advices function 'around)
                             (ad-get-enabled-advices function 'after)))
     (let ((arglist (ad-arglist (ad-advice-definition advice))))
       (if arglist
          ;; We found the first one, use it:
-         (ad-do-return arglist)))))
+         (cl-return arglist)))))
 
 (defun ad-advised-interactive-form (function)
   "Find first interactive form in FUNCTION's redefining advices."
-  (ad-dolist (advice (append (ad-get-enabled-advices function 'before)
+  (cl-dolist (advice (append (ad-get-enabled-advices function 'before)
                             (ad-get-enabled-advices function 'around)
                             (ad-get-enabled-advices function 'after)))
     (let ((interactive-form
           (ad-interactive-form (ad-advice-definition advice))))
       (if interactive-form
          ;; We found the first one, use it:
-         (ad-do-return interactive-form)))))
+         (cl-return interactive-form)))))
 
 ;; @@@ Putting it all together:
 ;; ============================
@@ -2959,10 +2773,10 @@ in any of these classes."
             (origname (ad-get-advice-info-field function 'origname))
             (orig-interactive-p (commandp origdef))
             (orig-subr-p (ad-subr-p origdef))
-            (orig-special-form-p (ad-special-form-p origdef))
+            (orig-special-form-p (special-form-p origdef))
             (orig-macro-p (ad-macro-p origdef))
             ;; Construct the individual pieces that we need for assembly:
-            (orig-arglist (ad-arglist origdef function))
+            (orig-arglist (ad-arglist origdef))
             (advised-arglist (or (ad-advised-arglist function)
                                  orig-arglist))
             (advised-interactive-form (ad-advised-interactive-form function))
@@ -3033,49 +2847,51 @@ definition, INTERACTIVE if non-nil is the interactive form to be used,
 ORIG is a form that calls the body of the original unadvised function,
 and BEFORES, AROUNDS and AFTERS are the lists of advices with which ORIG
 should be modified.  The assembled function will be returned."
-
-  (let (before-forms around-form around-form-protected after-forms definition)
-    (ad-dolist (advice befores)
-               (cond ((and (ad-advice-protected advice)
-                           before-forms)
-                      (setq before-forms
-                            `((unwind-protect
-                                   ,(ad-prognify before-forms)
-                                ,@(ad-body-forms
-                                   (ad-advice-definition advice))))))
-                     (t (setq before-forms
-                              (append before-forms
-                                      (ad-body-forms (ad-advice-definition advice)))))))
-
-    (setq around-form `(setq ad-return-value ,orig))
-    (ad-dolist (advice (reverse arounds))
-               ;; If any of the around advices is protected then we
-               ;; protect the complete around advice onion:
-               (if (ad-advice-protected advice)
-                   (setq around-form-protected t))
-               (setq around-form
-                     (ad-substitute-tree
-                      (function (lambda (form) (eq form 'ad-do-it)))
-                      (function (lambda (form) around-form))
-                      (ad-prognify (ad-body-forms (ad-advice-definition advice))))))
+  ;; The ad-do-it call should always have the right number of arguments,
+  ;; but the compiler might signal a bogus warning because it checks the call
+  ;; against the advertised calling convention.
+  (let ((around-form `(setq ad-return-value (with-no-warnings ,orig)))
+        before-forms around-form-protected after-forms definition)
+    (dolist (advice befores)
+      (cond ((and (ad-advice-protected advice)
+                  before-forms)
+             (setq before-forms
+                   `((unwind-protect
+                         ,(macroexp-progn before-forms)
+                       ,@(ad-body-forms
+                          (ad-advice-definition advice))))))
+            (t (setq before-forms
+                     (append before-forms
+                             (ad-body-forms (ad-advice-definition advice)))))))
+
+    (dolist (advice (reverse arounds))
+      ;; If any of the around advices is protected then we
+      ;; protect the complete around advice onion:
+      (if (ad-advice-protected advice)
+          (setq around-form-protected t))
+      (setq around-form
+            (ad-substitute-tree
+             (lambda (form) (eq form 'ad-do-it))
+             (lambda (_form) around-form)
+             (macroexp-progn (ad-body-forms (ad-advice-definition advice))))))
 
     (setq after-forms
          (if (and around-form-protected before-forms)
              `((unwind-protect
-                     ,(ad-prognify before-forms)
+                     ,(macroexp-progn before-forms)
                   ,around-form))
               (append before-forms (list around-form))))
-    (ad-dolist (advice afters)
-               (cond ((and (ad-advice-protected advice)
-                           after-forms)
-                      (setq after-forms
-                            `((unwind-protect
-                                   ,(ad-prognify after-forms)
-                                ,@(ad-body-forms
-                                   (ad-advice-definition advice))))))
-                     (t (setq after-forms
-                              (append after-forms
-                                      (ad-body-forms (ad-advice-definition advice)))))))
+    (dolist (advice afters)
+      (cond ((and (ad-advice-protected advice)
+                  after-forms)
+             (setq after-forms
+                   `((unwind-protect
+                         ,(macroexp-progn after-forms)
+                       ,@(ad-body-forms
+                          (ad-advice-definition advice))))))
+            (t (setq after-forms
+                     (append after-forms
+                             (ad-body-forms (ad-advice-definition advice)))))))
 
     (setq definition
          `(,@(if (memq type '(macro special-form)) '(macro))
@@ -3099,7 +2915,7 @@ should be modified.  The assembled function will be returned."
                             (ad-body-forms (ad-advice-definition advice))))
                 (ad-get-enabled-advices function hook-name))))
     (if hook-forms
-       (ad-prognify (apply 'append hook-forms)))))
+       (macroexp-progn (apply 'append hook-forms)))))
 
 
 ;; @@ Caching:
@@ -3191,10 +3007,10 @@ advised definition from scratch."
          (mapcar (function (lambda (advice) (ad-advice-name advice)))
                  (ad-get-enabled-advices function 'after))
          (ad-definition-type original-definition)
-         (if (equal (ad-arglist original-definition function)
+         (if (equal (ad-arglist original-definition)
                     (ad-arglist cached-definition))
              t
-           (ad-arglist original-definition function))
+           (ad-arglist original-definition))
          (if (eq (ad-definition-type original-definition) 'function)
              (equal (interactive-form original-definition)
                     (interactive-form cached-definition))))))
@@ -3209,11 +3025,11 @@ advised definition from scratch."
        (nth 2 cache-id)))))
 
 (defun ad-verify-cache-class-id (cache-class-id advices)
-  (ad-dolist (advice advices (null cache-class-id))
+  (cl-dolist (advice advices (null cache-class-id))
     (if (ad-advice-enabled advice)
        (if (eq (car cache-class-id) (ad-advice-name advice))
            (setq cache-class-id (cdr cache-class-id))
-         (ad-do-return nil)))))
+         (cl-return nil)))))
 
 ;; There should be a way to monitor if and why a cache verification failed
 ;; in order to determine whether a certain preactivation could be used or
@@ -3239,7 +3055,7 @@ advised definition from scratch."
           (and (eq (nth 3 cache-id) (ad-definition-type original-definition))
                (setq code 'arglist-mismatch)
                (equal (if (eq (nth 4 cache-id) t)
-                          (ad-arglist original-definition function)
+                          (ad-arglist original-definition)
                         (nth 4 cache-id) )
                       (ad-arglist cached-definition))
                (setq code 'interactive-form-mismatch)
@@ -3298,94 +3114,10 @@ advised definition from scratch."
       (ad-set-advice-info function old-advice-info)
       ;; Don't `fset' function to nil if it was previously unbound:
       (if function-defined-p
-         (ad-safe-fset function old-definition)
+         (fset function old-definition)
        (fmakunbound function)))))
 
 
-;; @@ Freezing:
-;; ============
-;; Freezing transforms a `defadvice' into a redefining `defun/defmacro'
-;; for the advised function without keeping any advice information. This
-;; feature was jwz's idea: It generates a dumpable function definition
-;; whose documentation can be written to the DOC file, and the generated
-;; code does not need any Advice runtime support. Of course, frozen advices
-;; cannot be undone.
-
-;; Freezing only considers the advice of the particular `defadvice', other
-;; already existing advices for the same function will be ignored. To ensure
-;; proper interaction when an already advised function gets redefined with
-;; a frozen advice, frozen advices always use the actual original definition
-;; of the function, i.e., they are always at the core of the onion. E.g., if
-;; an already advised function gets redefined with a frozen advice and then
-;; unadvised, the frozen advice remains as the new definition of the function.
-
-;; While multiple freeze advices for a single function or freeze-advising
-;; of an already advised function are possible, they are better avoided,
-;; because definition/compile/load ordering is relevant, and it becomes
-;; incomprehensible pretty quickly.
-
-(defun ad-make-freeze-definition (function advice class position)
-  (if (not (ad-has-proper-definition function))
-      (error
-       "ad-make-freeze-definition: `%s' is not yet defined"
-       function))
-  (let* ((name (ad-advice-name advice))
-        ;; With a unique origname we can have multiple freeze advices
-        ;; for the same function, each overloading the previous one:
-        (unique-origname
-         (intern (format "%s-%s-%s" (ad-make-origname function) class name)))
-        (orig-definition
-         ;; If FUNCTION is already advised, we'll use its current origdef
-         ;; as the original definition of the frozen advice:
-         (or (ad-get-orig-definition function)
-             (symbol-function function)))
-        (old-advice-info
-         (if (ad-is-advised function)
-             (ad-copy-advice-info function)))
-        (real-docstring-fn
-         (symbol-function 'ad-make-advised-definition-docstring))
-        (real-origname-fn
-         (symbol-function 'ad-make-origname))
-        (frozen-definition
-         (unwind-protect
-               (progn
-                 ;; Make sure we construct a proper docstring:
-                 (ad-safe-fset 'ad-make-advised-definition-docstring
-                               'ad-make-freeze-docstring)
-                 ;; Make sure `unique-origname' is used as the origname:
-                 (ad-safe-fset 'ad-make-origname (lambda (x) unique-origname))
-                 ;; No we reset all current advice information to nil and
-                 ;; generate an advised definition that's solely determined
-                 ;; by ADVICE and the current origdef of FUNCTION:
-                 (ad-set-advice-info function nil)
-                 (ad-add-advice function advice class position)
-                 ;; The following will provide proper real docstrings as
-                 ;; well as a definition that will make the compiler happy:
-                 (ad-set-orig-definition function orig-definition)
-                 (ad-make-advised-definition function))
-           ;; Restore the old advice state:
-           (ad-set-advice-info function old-advice-info)
-           ;; Restore functions:
-           (ad-safe-fset
-            'ad-make-advised-definition-docstring real-docstring-fn)
-           (ad-safe-fset 'ad-make-origname real-origname-fn))))
-    (if frozen-definition
-       (let* ((macro-p (ad-macro-p frozen-definition))
-              (body (cdr (if macro-p
-                             (ad-lambdafy frozen-definition)
-                              frozen-definition))))
-         `(progn
-            (if (not (fboundp ',unique-origname))
-                (fset ',unique-origname
-                      ;; avoid infinite recursion in case the function
-                      ;; we want to freeze is already advised:
-                      (or (ad-get-orig-definition ',function)
-                          (symbol-function ',function))))
-            (,(if macro-p 'defmacro 'defun)
-             ,function
-             ,@body))))))
-
-
 ;; @@ Activation and definition handling:
 ;; ======================================
 
@@ -3416,7 +3148,7 @@ The current definition and its cache-id will be put into the cache."
   (let ((verified-cached-definition
         (if (ad-verify-cache-id function)
             (ad-get-cache-definition function))))
-    (ad-safe-fset function
+    (fset function
                  (or verified-cached-definition
                      (ad-make-advised-definition function)))
     (if (ad-should-compile function compile)
@@ -3458,7 +3190,7 @@ the value of `ad-redefinition-action' and de/activate again."
                    (error "ad-handle-definition (see its doc): `%s' %s"
                           function "invalidly redefined")
                  (if (eq ad-redefinition-action 'discard)
-                     (ad-safe-fset function original-definition)
+                     (fset function original-definition)
                    (ad-set-orig-definition function current-definition)
                    (if (eq ad-redefinition-action 'warn)
                        (message "ad-handle-definition: `%s' got redefined"
@@ -3533,7 +3265,7 @@ a call to `ad-activate'."
           (if (not (ad-get-orig-definition function))
               (error "ad-deactivate: `%s' has no original definition"
                      function)
-            (ad-safe-fset function (ad-get-orig-definition function))
+            (fset function (ad-get-orig-definition function))
             (ad-set-advice-info-field function 'active nil)
             (eval (ad-make-hook-form function 'deactivation))
             function)))))
@@ -3571,7 +3303,7 @@ Use in emergencies."
          (completing-read "Recover advised function: " obarray nil t))))
   (cond ((ad-is-advised function)
         (cond ((ad-get-orig-definition function)
-               (ad-safe-fset function (ad-get-orig-definition function))
+               (fset function (ad-get-orig-definition function))
                (ad-clear-orig-definition function)))
         (ad-set-advice-info function nil)
         (ad-pop-advised-function function))))
@@ -3652,7 +3384,7 @@ deactivation, which might run hooks and get into other trouble."
 ;; Completion alist of valid `defadvice' flags
 (defvar ad-defadvice-flags
   '(("protect") ("disable") ("activate")
-    ("compile") ("preactivate") ("freeze")))
+    ("compile") ("preactivate")))
 
 ;;;###autoload
 (defmacro defadvice (function args &rest body)
@@ -3671,7 +3403,7 @@ POSITION ::= `first' | `last' | NUMBER. Optional, defaults to `first',
 ARGLIST ::= An optional argument list to be used for the advised function
     instead of the argument list of the original.  The first one found in
     before/around/after-advices will be used.
-FLAG ::= `protect'|`disable'|`activate'|`compile'|`preactivate'|`freeze'.
+FLAG ::= `protect'|`disable'|`activate'|`compile'|`preactivate'.
     All flags can be specified with unambiguous initial substrings.
 DOCSTRING ::= Optional documentation for this piece of advice.
 INTERACTIVE-FORM ::= Optional interactive form to be used for the advised
@@ -3697,18 +3429,20 @@ time.  This generates a compiled advised definition according to the current
 advice state that will be used during activation if appropriate.  Only use
 this if the `defadvice' gets actually compiled.
 
-`freeze': Expands the `defadvice' into a redefining `defun/defmacro' according
-to this particular single advice.  No other advice information will be saved.
-Frozen advices cannot be undone, they behave like a hard redefinition of
-the advised function.  `freeze' implies `activate' and `preactivate'.  The
-documentation of the advised function can be dumped onto the `DOC' file
-during preloading.
-
 See Info node `(elisp)Advising Functions' for comprehensive documentation.
 usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
           [DOCSTRING] [INTERACTIVE-FORM]
           BODY...)"
-  (declare (doc-string 3))
+  (declare (doc-string 3)
+           (debug (&define name  ;; thing being advised.
+                           (name ;; class is [&or "before" "around" "after"
+                                 ;;               "activation" "deactivation"]
+                            name ;; name of advice
+                            &rest sexp ;; optional position and flags
+                            )
+                           [&optional stringp]
+                           [&optional ("interactive" interactive)]
+                           def-body)))
   (if (not (ad-name-p function))
       (error "defadvice: Invalid function name: %s" function))
   (let* ((class (car args))
@@ -3744,29 +3478,24 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
                            (ad-preactivate-advice
                             function advice class position))))
     ;; Now for the things to be done at evaluation time:
-    (if (memq 'freeze flags)
-       ;; jwz's idea: Freeze the advised definition into a dumpable
-       ;; defun/defmacro whose docs can be written to the DOC file:
-       (ad-make-freeze-definition function advice class position)
-        ;; the normal case:
-        `(progn
-          (ad-add-advice ',function ',advice ',class ',position)
-          ,@(if preactivation
-                `((ad-set-cache
-                   ',function
-                   ;; the function will get compiled:
-                   ,(cond ((ad-macro-p (car preactivation))
-                           `(ad-macrofy
-                             (function
-                              ,(ad-lambdafy
-                                (car preactivation)))))
-                          (t `(function
-                               ,(car preactivation))))
-                   ',(car (cdr preactivation)))))
-          ,@(if (memq 'activate flags)
-                `((ad-activate ',function
-                   ,(if (memq 'compile flags) t))))
-          ',function))))
+    `(progn
+       (ad-add-advice ',function ',advice ',class ',position)
+       ,@(if preactivation
+             `((ad-set-cache
+                ',function
+                ;; the function will get compiled:
+                ,(cond ((ad-macro-p (car preactivation))
+                        `(ad-macrofy
+                          (function
+                           ,(ad-lambdafy
+                             (car preactivation)))))
+                       (t `(function
+                            ,(car preactivation))))
+                ',(car (cdr preactivation)))))
+       ,@(if (memq 'activate flags)
+             `((ad-activate ',function
+                            ,(if (memq 'compile flags) t))))
+       ',function)))
 
 
 ;; @@ Tools:
@@ -3777,6 +3506,7 @@ usage: (defadvice FUNCTION (CLASS NAME [POSITION] [ARGLIST] FLAG...)
 For any members of FUNCTIONS that are not currently advised the rebinding will
 be a noop.  Any modifications done to the definitions of FUNCTIONS will be
 undone on exit of this macro."
+  (declare (indent 1))
   (let* ((index -1)
         ;; Make let-variables to store current definitions:
         (current-bindings
@@ -3793,38 +3523,24 @@ undone on exit of this macro."
                 ;; Make forms to redefine functions to their
                 ;; original definitions if they are advised:
                 (setq index -1)
-                (mapcar
-                 (function
-                  (lambda (function)
-                   (setq index (1+ index))
-                   `(ad-safe-fset
-                     ',function
-                     (or (ad-get-orig-definition ',function)
-                      ,(car (nth index current-bindings))))))
-                 functions))
+                (mapcar (lambda (function)
+                          (setq index (1+ index))
+                           `(fset ',function
+                            (or (ad-get-orig-definition ',function)
+                                ,(car (nth index current-bindings)))))
+                        functions))
              ,@body)
         ,@(progn
            ;; Make forms to back-define functions to the definitions
            ;; they had outside this macro call:
            (setq index -1)
-           (mapcar
-            (function
-             (lambda (function)
-              (setq index (1+ index))
-              `(ad-safe-fset
-                ',function
-                ,(car (nth index current-bindings)))))
-            functions))))))
-
-(if (not (get 'ad-with-originals 'lisp-indent-hook))
-    (put 'ad-with-originals 'lisp-indent-hook 1))
+           (mapcar (lambda (function)
+                     (setq index (1+ index))
+                       `(fset ',function
+                       ,(car (nth index current-bindings))))
+                   functions))))))
 
 
-;; @@ Advising `documentation':
-;; ============================
-;; Use the advice mechanism to advise `documentation' to make it
-;; generate proper documentation strings for advised definitions:
-
 ;; @@ Starting, stopping and recovering from the advice package magic:
 ;; ===================================================================
 
@@ -3833,7 +3549,7 @@ undone on exit of this macro."
   (interactive)
   ;; Advising `ad-activate-internal' means death!!
   (ad-set-advice-info 'ad-activate-internal nil)
-  (ad-safe-fset 'ad-activate-internal 'ad-activate))
+  (fset 'ad-activate-internal 'ad-activate))
 
 (defun ad-stop-advice ()
   "Stop the automatic advice handling magic.
@@ -3841,7 +3557,7 @@ You should only need this in case of Advice-related emergencies."
   (interactive)
   ;; Advising `ad-activate-internal' means death!!
   (ad-set-advice-info 'ad-activate-internal nil)
-  (ad-safe-fset 'ad-activate-internal 'ad-activate-internal-off))
+  (fset 'ad-activate-internal 'ad-activate-internal-off))
 
 (defun ad-recover-normality ()
   "Undo all advice related redefinitions and unadvises everything.
@@ -3849,9 +3565,11 @@ Use only in REAL emergencies."
   (interactive)
   ;; Advising `ad-activate-internal' means death!!
   (ad-set-advice-info 'ad-activate-internal nil)
-  (ad-safe-fset 'ad-activate-internal 'ad-activate-internal-off)
+  (fset 'ad-activate-internal 'ad-activate-internal-off)
   (ad-recover-all)
-  (setq ad-advised-functions nil))
+  (ad-do-advised-functions (function)
+    (message "Oops! Left over advised function %S" function)
+    (ad-pop-advised-function function)))
 
 (ad-start-advice)