summaryrefslogtreecommitdiff
path: root/lisp/cedet/semantic/bovine/c.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/cedet/semantic/bovine/c.el')
-rw-r--r--lisp/cedet/semantic/bovine/c.el277
1 files changed, 167 insertions, 110 deletions
diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el
index 3c991ea8555..1c25c7b0808 100644
--- a/lisp/cedet/semantic/bovine/c.el
+++ b/lisp/cedet/semantic/bovine/c.el
@@ -1,6 +1,6 @@
;;; semantic/bovine/c.el --- Semantic details for C
-;; Copyright (C) 1999-2013 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2015 Free Software Foundation, Inc.
;; Author: Eric M. Ludlam <zappo@gnu.org>
@@ -27,6 +27,7 @@
(require 'semantic)
(require 'semantic/analyze)
+(require 'semantic/analyze/refs)
(require 'semantic/bovine)
(require 'semantic/bovine/gcc)
(require 'semantic/idle)
@@ -224,7 +225,7 @@ to store your global macros in a more natural way."
)
(defcustom semantic-c-member-of-autocast 't
- "Non-nil means classes with a '->' operator will cast to its return type.
+ "Non-nil means classes with a `->' operator will cast to its return type.
For Examples:
@@ -269,7 +270,7 @@ Return the defined symbol as a special spp lex token."
(if (looking-back "/\\*.*" beginning-of-define)
(progn
(goto-char (match-beginning 0))
- (1- (point)))
+ (point))
(point)))))
)
@@ -497,13 +498,19 @@ code to parse."
(parsedtokelist
(condition-case nil
;; This is imperfect, so always assume on error.
- (hif-canonicalize)
+ (hif-canonicalize hif-ifx-regexp)
(error nil))))
- (let ((eval-form (eval parsedtokelist)))
+ (let ((eval-form (condition-case err
+ (eval parsedtokelist)
+ (error
+ (semantic-push-parser-warning
+ (format "Hideif forms produced an error. Assuming false.\n%S" err)
+ (point) (1+ (point)))
+ nil))))
(if (or (not eval-form)
(and (numberp eval-form)
- (equal eval-form 0)));; ifdefline resulted in false
+ (equal eval-form 0)));; ifdef line resulted in false
;; The if indicates to skip this preprocessor section
(let ((pt nil))
@@ -812,7 +819,7 @@ Use semantic-cpp-lexer for parsing text inside a CPP macro."
;; semantic-lex-spp-replace-or-symbol-or-keyword
semantic-lex-symbol-or-keyword
semantic-lex-charquote
- semantic-lex-paren-or-list
+ semantic-lex-spp-paren-or-list
semantic-lex-close-paren
semantic-lex-ignore-comments
semantic-lex-punctuation
@@ -1042,8 +1049,8 @@ now.
return-list))
(defun semantic-expand-c-extern-C (tag)
- "Expand TAG containing an 'extern \"C\"' statement.
-This will return all members of TAG with 'extern \"C\"' added to
+ "Expand TAG containing an `extern \"C\"' statement.
+This will return all members of TAG with `extern \"C\"' added to
the typemodifiers attribute."
(when (eq (semantic-tag-class tag) 'extern)
(let* ((mb (semantic-tag-get-attribute tag :members))
@@ -1058,7 +1065,7 @@ the typemodifiers attribute."
(defun semantic-expand-c-complex-type (tag)
"Check if TAG has a full :type with a name on its own.
If so, extract it, and replace it with a reference to that type.
-Thus, 'struct A { int a; } B;' will create 2 toplevel tags, one
+Thus, `struct A { int a; } B;' will create 2 toplevel tags, one
is type A, and the other variable B where the :type of B is just
a type tag A that is a prototype, and the actual struct info of A
is its own toplevel tag. This function will return (cons A B)."
@@ -1118,7 +1125,8 @@ is its own toplevel tag. This function will return (cons A B)."
(semantic-tag-new-variable
(car cur) ;name
ty ;type
- (if default
+ (if (and default
+ (listp (cdr default)))
(buffer-substring-no-properties
(car default) (car (cdr default))))
:constant-flag (semantic-tag-variable-constant-p tag)
@@ -1173,11 +1181,7 @@ is its own toplevel tag. This function will return (cons A B)."
(nth 1 (car names)) ; name
"typedef"
(semantic-tag-type-members tag)
- ;; parent is just the name of what
- ;; is passed down as a tag.
- (list
- (semantic-tag-name
- (semantic-tag-type-superclasses tag)))
+ nil
:pointer
(let ((stars (car (car (car names)))))
(if (= stars 0) nil stars))
@@ -1227,6 +1231,45 @@ or \"struct\".")
name
(delete "" ans))))
+(define-mode-local-override semantic-analyze-tag-references c-mode (tag &optional db)
+ "Analyze the references for TAG.
+Returns a class with information about TAG.
+
+Optional argument DB is a database. It will be used to help
+locate TAG.
+
+Use `semantic-analyze-current-tag' to debug this fcn."
+ (when (not (semantic-tag-p tag)) (signal 'wrong-type-argument (list 'semantic-tag-p tag)))
+ (let ((allhits nil)
+ (scope nil)
+ (refs nil))
+ (save-excursion
+ (semantic-go-to-tag tag db)
+ (setq scope (semantic-calculate-scope))
+
+ (setq allhits (semantic--analyze-refs-full-lookup tag scope t))
+
+ (when (or (zerop (semanticdb-find-result-length allhits))
+ (and (= (semanticdb-find-result-length allhits) 1)
+ (eq (car (semanticdb-find-result-nth allhits 0)) tag)))
+ ;; It found nothing or only itself - not good enough. As a
+ ;; last resort, let's remove all namespaces from the scope and
+ ;; search again.
+ (oset scope parents
+ (let ((parents (oref scope parents))
+ newparents)
+ (dolist (cur parents)
+ (unless (string= (semantic-tag-type cur) "namespace")
+ (push cur newparents)))
+ (reverse newparents)))
+ (setq allhits (semantic--analyze-refs-full-lookup tag scope t)))
+
+ (setq refs (semantic-analyze-references (semantic-tag-name tag)
+ :tag tag
+ :tagdb db
+ :scope scope
+ :rawsearchdata allhits)))))
+
(defun semantic-c-reconstitute-token (tokenpart declmods typedecl)
"Reconstitute a token TOKENPART with DECLMODS and TYPEDECL.
This is so we don't have to match the same starting text several times.
@@ -1258,7 +1301,8 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
(nth 10 tokenpart) ; initializers
)
(not (car (nth 3 tokenpart)))))
- (fcnpointer (string-match "^\\*" (car tokenpart)))
+ (fcnpointer (and (> (length (car tokenpart)) 0)
+ (= (aref (car tokenpart) 0) ?*)))
(fnname (if fcnpointer
(substring (car tokenpart) 1)
(car tokenpart)))
@@ -1266,70 +1310,80 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
nil
t))
)
- (if fcnpointer
- ;; Function pointers are really variables.
- (semantic-tag-new-variable
- fnname
- typedecl
- nil
- ;; It is a function pointer
- :functionpointer-flag t
- )
- ;; The function
- (semantic-tag-new-function
- fnname
- (or typedecl ;type
- (cond ((car (nth 3 tokenpart) )
- "void") ; Destructors have no return?
- (constructor
- ;; Constructors return an object.
- (semantic-tag-new-type
- ;; name
- (or (car semantic-c-classname)
- (let ((split (semantic-analyze-split-name-c-mode
- (car (nth 2 tokenpart)))))
- (if (stringp split) split
- (car (last split)))))
- ;; type
- (or (cdr semantic-c-classname)
- "class")
- ;; members
- nil
- ;; parents
- nil
- ))
- (t "int")))
- (nth 4 tokenpart) ;arglist
- :constant-flag (if (member "const" declmods) t nil)
- :typemodifiers (delete "const" declmods)
- :parent (car (nth 2 tokenpart))
- :destructor-flag (if (car (nth 3 tokenpart) ) t)
- :constructor-flag (if constructor t)
- :pointer (nth 7 tokenpart)
- :operator-flag operator
- ;; Even though it is "throw" in C++, we use
- ;; `throws' as a common name for things that toss
- ;; exceptions about.
- :throws (nth 5 tokenpart)
- ;; Reentrant is a C++ thingy. Add it here
- :reentrant-flag (if (member "reentrant" (nth 6 tokenpart)) t)
- ;; A function post-const is funky. Try stuff
- :methodconst-flag (if (member "const" (nth 6 tokenpart)) t)
- ;; prototypes are functions w/ no body
- :prototype-flag (if (nth 8 tokenpart) t)
- ;; Pure virtual
- :pure-virtual-flag (if (eq (nth 8 tokenpart) :pure-virtual-flag) t)
- ;; Template specifier.
- :template-specifier (nth 9 tokenpart)
- )))
- )
- ))
+ ;; The function
+ (semantic-tag-new-function
+ fnname
+ (or typedecl ;type
+ (cond ((car (nth 3 tokenpart) )
+ "void") ; Destructors have no return?
+ (constructor
+ ;; Constructors return an object.
+ (semantic-tag-new-type
+ ;; name
+ (or (car semantic-c-classname)
+ (let ((split (semantic-analyze-split-name-c-mode
+ (car (nth 2 tokenpart)))))
+ (if (stringp split) split
+ (car (last split)))))
+ ;; type
+ (or (cdr semantic-c-classname)
+ "class")
+ ;; members
+ nil
+ ;; parents
+ nil
+ ))
+ (t "int")))
+ ;; Argument list can contain things like function pointers
+ (semantic-c-reconstitute-function-arglist (nth 4 tokenpart))
+ :constant-flag (if (member "const" declmods) t nil)
+ :typemodifiers (delete "const" declmods)
+ :parent (car (nth 2 tokenpart))
+ :destructor-flag (if (car (nth 3 tokenpart) ) t)
+ :constructor-flag (if constructor t)
+ :function-pointer fcnpointer
+ :pointer (nth 7 tokenpart)
+ :operator-flag operator
+ ;; Even though it is "throw" in C++, we use
+ ;; `throws' as a common name for things that toss
+ ;; exceptions about.
+ :throws (nth 5 tokenpart)
+ ;; Reentrant is a C++ thingy. Add it here
+ :reentrant-flag (if (member "reentrant" (nth 6 tokenpart)) t)
+ ;; A function post-const is funky. Try stuff
+ :methodconst-flag (if (member "const" (nth 6 tokenpart)) t)
+ ;; prototypes are functions w/ no body
+ :prototype-flag (if (nth 8 tokenpart) t)
+ ;; Pure virtual
+ :pure-virtual-flag (if (eq (nth 8 tokenpart) :pure-virtual-flag) t)
+ ;; Template specifier.
+ :template-specifier (nth 9 tokenpart))))))
(defun semantic-c-reconstitute-template (tag specifier)
"Reconstitute the token TAG with the template SPECIFIER."
(semantic-tag-put-attribute tag :template (or specifier ""))
tag)
+(defun semantic-c-reconstitute-function-arglist (arglist)
+ "Reconstitute the argument list of a function.
+This currently only checks if the function expects a function
+pointer as argument."
+ (let (result)
+ (dolist (arg arglist)
+ ;; Names starting with a '*' denote a function pointer
+ (if (and (> (length (semantic-tag-name arg)) 0)
+ (= (aref (semantic-tag-name arg) 0) ?*))
+ (setq result
+ (append result
+ (list
+ (semantic-tag-new-function
+ (substring (semantic-tag-name arg) 1)
+ (semantic-tag-type arg)
+ (cadr (semantic-tag-attributes arg))
+ :function-pointer t))))
+ (setq result (append result (list arg)))))
+ result))
+
;;; Override methods & Variables
;;
@@ -1338,7 +1392,7 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
"Convert TAG to a string that is the print name for TAG.
Optional PARENT and COLOR are ignored."
(let ((name (semantic-format-tag-name-default tag parent color))
- (fnptr (semantic-tag-get-attribute tag :functionpointer-flag))
+ (fnptr (semantic-tag-get-attribute tag :function-pointer))
)
(if (not fnptr)
name
@@ -1546,7 +1600,7 @@ Optional PARENT and COLOR as specified with
"Return non-nil if TAG is considered abstract.
PARENT is tag's parent.
In C, a method is abstract if it is `virtual', which is already
-handled. A class is abstract iff its destructor is virtual."
+handled. A class is abstract only if its destructor is virtual."
(cond
((eq (semantic-tag-class tag) 'type)
(require 'semantic/find)
@@ -1602,7 +1656,7 @@ SPEC-LIST is the template specifier of the datatype instantiated."
(defun semantic-c--template-name-1 (spec-list)
"Return a string used to compute template class name.
-Based on SPEC-LIST, for ref<Foo,Bar> it will return 'Foo,Bar'."
+Based on SPEC-LIST, for ref<Foo,Bar> it will return `Foo,Bar'."
(when (car spec-list)
(let* ((endpart (semantic-c--template-name-1 (cdr spec-list)))
(separator (and endpart ",")))
@@ -1611,7 +1665,7 @@ Based on SPEC-LIST, for ref<Foo,Bar> it will return 'Foo,Bar'."
(defun semantic-c--template-name (type spec-list)
"Return a template class name for TYPE based on SPEC-LIST.
For a type `ref' with a template specifier of (Foo Bar) it will
-return 'ref<Foo,Bar>'."
+return `ref<Foo,Bar>'."
(concat (semantic-tag-name type)
"<" (semantic-c--template-name-1 (cdr spec-list)) ">"))
@@ -1639,7 +1693,7 @@ instantiated as specified in TYPE-DECLARATION."
;;; Patch here by "Raf" for instantiating templates.
(defun semantic-c-dereference-member-of (type scope &optional type-declaration)
"Dereference through the `->' operator of TYPE.
-Uses the return type of the '->' operator if it is contained in TYPE.
+Uses the return type of the `->' operator if it is contained in TYPE.
SCOPE is the current local scope to perform searches in.
TYPE-DECLARATION is passed through."
(if semantic-c-member-of-autocast
@@ -1655,8 +1709,8 @@ TYPE-DECLARATION is passed through."
;; tests 5 and following.
(defun semantic-c-dereference-namespace (type scope &optional type-declaration)
- "Dereference namespace which might hold an 'alias' for TYPE.
-Such an alias can be created through 'using' statements in a
+ "Dereference namespace which might hold an `alias' for TYPE.
+Such an alias can be created through `using' statements in a
namespace declaration. This function checks the namespaces in
SCOPE for such statements."
(let ((scopetypes (oref scope scopetypes))
@@ -1772,7 +1826,7 @@ or nil if it cannot be found."
(define-mode-local-override semantic-analyze-dereference-metatype
c-mode (type scope &optional type-declaration)
"Dereference TYPE as described in `semantic-analyze-dereference-metatype'.
-Handle typedef, template instantiation, and '->' operator."
+Handle typedef, template instantiation, and `->' operator."
(let* ((dereferencer-list '(semantic-c-dereference-typedef
semantic-c-dereference-template
semantic-c-dereference-member-of
@@ -1823,31 +1877,31 @@ DO NOT return the list of tags encompassing point."
(let ((idx 0)
(len (semanticdb-find-result-length tmp)))
(while (< idx len)
- (setq tagreturn (cons (semantic-tag-type (car (semanticdb-find-result-nth tmp idx))) tagreturn))
- (setq idx (1+ idx)))
- )
- ;; Use the encompassed types around point to also look for using statements.
- ;;(setq tagreturn (cons "bread_name" tagreturn))
- (while (cdr tagsaroundpoint) ; don't search the last one
- (setq tmp (semantic-find-tags-by-class 'using (semantic-tag-components (car tagsaroundpoint))))
- (dolist (T tmp)
- (setq tagreturn (cons (semantic-tag-type T) tagreturn))
- )
- (setq tagsaroundpoint (cdr tagsaroundpoint))
- )
- ;; If in a function...
- (when (and (semantic-tag-of-class-p (car tagsaroundpoint) 'function)
- ;; ...search for using statements in the local scope...
- (setq tmp (semantic-find-tags-by-class
- 'using
- (semantic-get-local-variables))))
- ;; ... and add them.
- (setq tagreturn
- (append tagreturn
- (mapcar 'semantic-tag-type tmp))))
+ (setq tagreturn
+ (append tagreturn (list (semantic-tag-type
+ (car (semanticdb-find-result-nth tmp idx))))))
+ (setq idx (1+ idx))))
+ ;; Use the encompassed types around point to also look for using
+ ;; statements. If we deal with types, search inside members; for
+ ;; functions, we have to call `semantic-get-local-variables' to
+ ;; parse inside the function's body.
+ (dolist (cur tagsaroundpoint)
+ (cond
+ ((and (eq (semantic-tag-class cur) 'type)
+ (setq tmp (semantic-find-tags-by-class
+ 'using
+ (semantic-tag-components (car tagsaroundpoint)))))
+ (dolist (T tmp)
+ (setq tagreturn (cons (semantic-tag-type T) tagreturn))))
+ ((and (semantic-tag-of-class-p (car (last tagsaroundpoint)) 'function)
+ (setq tmp (semantic-find-tags-by-class
+ 'using
+ (semantic-get-local-variables))))
+ (setq tagreturn
+ (append tagreturn
+ (mapcar 'semantic-tag-type tmp))))))
;; Return the stuff
- tagreturn
- ))
+ tagreturn))
(define-mode-local-override semantic-ctxt-imported-packages c++-mode (&optional point)
"Return the list of using tag types in scope of POINT."
@@ -2122,7 +2176,8 @@ actually in their parent which is not accessible.")
(princ "\n\nInclude Path Summary:\n")
(when (and (boundp 'ede-object) ede-object)
- (princ "\n This file's project include is handled by:\n")
+ (princ (substitute-command-keys
+ "\n This file's project include is handled by:\n"))
(let ((objs (if (listp ede-object)
ede-object
(list ede-object))))
@@ -2140,14 +2195,16 @@ actually in their parent which is not accessible.")
)
(when semantic-dependency-include-path
- (princ "\n This file's generic include path is:\n")
+ (princ (substitute-command-keys
+ "\n This file's generic include path is:\n"))
(dolist (dir semantic-dependency-include-path)
(princ " ")
(princ dir)
(princ "\n")))
(when semantic-dependency-system-include-path
- (princ "\n This file's system include path is:\n")
+ (princ (substitute-command-keys
+ "\n This file's system include path is:\n"))
(dolist (dir semantic-dependency-system-include-path)
(princ " ")
(princ dir)