Subject: bug#23792: 25.0.95; CEDET included in Emacs should be merged with upstream

From: Bastian Beischer <[email-masked]>
Date: Sat, 18 Jun 2016 12:19:42 +0200

Dear all,

This is a bug report for GNU Emacs, but I've cc'ed the CEDET devel
mailing list.

It appears that the development of CEDET inside Emacs and the upstream
development have diverged. There are various important fixes on both
sides and it is non trivial for me to port fixes in CEDET inside Emacs
to the upstream code or vice versa. Neither version is usable for me.

I find this rather frustratring so I would really love to see the code
synchronized once more. I think it would also be a good idea to work out
a forward plan: How can we avoid this kind of divergence in the future?

There's been some related talk on the CEDET devel mailing list recently:

https://sourceforge.net/p/cedet/mailman/cedet-devel/thread/1465745082.2627.29.camel%40yahoo.co.uk/#msg35153903

Anyway, I tried to port the fixes in the CEDET git repository:

http://git.code.sf.net/p/cedet/git

Since this commit:

commit 28ea46d99ee2ac35c3752511052bcd02b25a088b
Merge: 7c55a5e df226b6
Author: David Engster <[email-masked]>
Date:   Sun Nov 9 21:23:30 2014 +0100

    Merge from Emacs.

(which appears to be the point when the repos where last synchronized)
to the Emacs sources. The patch I came up with (attached!) is
_incomplete_ - it does not work yet, but maybe it's a start?! Note that
I really don't know well enough what I'm doing, which is why I'm asking
for help here. Hope we can work this out together :-)

Cheers
Bastian

diff --git a/admin/grammars/c.by b/admin/grammars/c.by
index be41bd8..1d78a3e 100644
--- a/admin/grammars/c.by
+++ b/admin/grammars/c.by
@@ -94,6 +94,7 @@
 %put STATIC summary "Declaration Modifier: static <type> <name> ..."
 %token CONST "const"
 %put CONST summary "Declaration Modifier: const <type> <name> ..."
+%token CONSTEXPR "constexpr"
 %token VOLATILE "volatile"
 %put VOLATILE summary "Declaration Modifier: volatile <type> <name> ..."
 %token REGISTER "register"
@@ -117,7 +118,7 @@
 %token UNION "union"
 %put UNION summary "Union Type Declaration: union [name] { ... };"
 %token ENUM "enum"
-%put ENUM summary "Enumeration Type Declaration: enum [name] { ... };"
+%put ENUM summary "Enumeration Type Declaration: enum [name] [: type] { ... };"
 %token TYPEDEF "typedef"
 %put TYPEDEF summary "Arbitrary Type Declaration: typedef <typedeclaration> <name>;"
 %token CLASS "class"
@@ -143,9 +144,14 @@
 %put THROW summary "<type> <methoddef> (<method args>) throw (<exception>) ..."
 %token REENTRANT "reentrant"
 %put REENTRANT summary "<type> <methoddef> (<method args>) reentrant ..."
+%token OVERRIDE "override"
+%put OVERRIDE summary "<type> <methoddef> (<method args>) override ..."
+%token FINAL "final"
+%put FINAL summary "<type> <methoddef> (<method args>) final ..."
 %token TRY "try"
 %token CATCH "catch"
 %put { TRY CATCH } summary "try { <body> } catch { <catch code> }"
+%token NOEXCEPT "noexcept"
 
 ;; Leave these alone for now.
 %token OPERATOR "operator"
@@ -240,20 +246,24 @@ extern-c-contents
   ;
 
 extern-c
-  : EXTERN C semantic-list
+  : EXTERN c-or-cpp opt-extern-c-contents
  ;; Extern C commands which contain a list need to have the
  ;; entries of the list extracted, and spliced into the main
  ;; list of entries.  This must be done via the function
  ;; that expands singular nonterminals, such as int x,y;
-    (TAG "C" 'extern :members (EXPANDFULL $3 extern-c-contents) )
-  | EXTERN CPP semantic-list
-    (TAG "C" 'extern :members (EXPANDFULL $3 extern-c-contents) )
-  | EXTERN C
- ;; A plain extern "C" call should add something to the token,
- ;; but just strip it from the buffer here for now.
-    ( nil )
-  | EXTERN CPP
-    ( nil )
+    (TAG (car $2) 'extern :members $3)
+  ;
+
+c-or-cpp
+  : C
+  | CPP
+  ;
+
+opt-extern-c-contents
+  : semantic-list
+    (EXPANDFULL $1 extern-c-contents)
+  | ;; EMPTY
+    ()
   ;
 
 macro
@@ -309,10 +319,14 @@ classsubparts
  ;; For QT, they may put a `slot' keyword between the protection
  ;; and the COLON.  @todo - Have the QT stuff use macros.
     (TAG (car $1) 'label)
+  | FRIEND symbol SEMICOLON
+ ;; Like class, but w/out the CLASS symbol.  Add this to avoid
+ ;; it being detected as a variable with undeclared int type.
+    (TAG $2 'friend)
   | var-or-fun
-  | FRIEND func-decl
+  | FRIEND func-decl SEMICOLON
     (TAG (car $2) 'friend)
-  | FRIEND CLASS symbol
+  | FRIEND CLASS symbol SEMICOLON
     (TAG $3 'friend)
   | type
   | define
@@ -411,27 +425,29 @@ opt-name
     ( "" )
   ;
 
+opt-enum-type
+  : COLON typeformbase
+    ( ,$2 )
+  | ;; EMPTY
+  ;
+
 typesimple
   : struct-or-class opt-class opt-name opt-template-specifier
-    opt-class-parents semantic-list
+    opt-class-parents typesimple-opt-subparts
     (TYPE-TAG (car $3) (car $1)
-          (let ((semantic-c-classname (cons (car ,$3) (car ,$1))))
-            (EXPANDFULL $6 classsubparts))
-          $5
-          :template-specifier $4
-          :parent (car ,$2))
-  | struct-or-class opt-class opt-name opt-template-specifier
-    opt-class-parents
-    (TYPE-TAG (car $3) (car $1) nil $5
-              :template-specifier $4
-	      :prototype t
-              :parent (car ,$2))
+	      (let ((semantic-c-classname (cons (car ,$3) (car ,$1))))
+		(when $6 (EXPANDFULL (car $6) classsubparts)))
+	      $5
+	      :template-specifier $4
+	      :prototype (not (car $6))
+	      :parent (car ,$2))
   | UNION opt-class opt-name unionparts
     (TYPE-TAG (car $3) $1 $4 nil
               :parent (car ,$2))
-  | ENUM opt-class opt-name enumparts
-    (TYPE-TAG (car $3) $1 $4 nil
-              :parent (car ,$2))
+  | ENUM opt-class opt-name opt-enum-type enumparts
+    (TYPE-TAG (car $3) $1 $5 nil
+              :parent (car ,$2)
+              :enum-type (car ,$4))
  ;; Klaus Berndl: a typedef can be a typeformbase with all this
  ;; declmods stuff.
   | TYPEDEF declmods typeformbase cv-declmods typedef-symbol-list
@@ -440,18 +456,29 @@ typesimple
     (TYPE-TAG $5 $1 nil (list $3) )
   ;
 
-typedef-symbol-list
-  : typedefname COMA typedef-symbol-list
-    ( ,(cons $1 $3) )
-  | typedefname
+typesimple-opt-subparts
+  : semantic-list
     ( $1 )
+  | ;; EMPTY
+    ()
+  ;
+
+typedef-symbol-list
+  : typedefname typedef-symbol-list-opt-comma
+    ( ,(cons $1 $2) )
+  ;
+
+typedef-symbol-list-opt-comma
+  : COMA typedef-symbol-list
+    ( ,$2 )
+  | ;; EMPTY
   ;
 
 ;; TODO: Klaus Berndl: symbol -> namespace-symbol?!  Answer: Probably
 ;; symbol is correct here!
 typedefname
-  : opt-stars symbol opt-bits opt-array
-    ( $1 $2 )
+  : opt-stars opt-ref symbol opt-bits opt-array
+    ( $1 $2 $3 )
   ;
 
 struct-or-class
@@ -462,15 +489,20 @@ struct-or-class
 type
   : typesimple SEMICOLON
     ( ,$1 )
+  | NAMESPACE type-namespace
+    ( ,$2 )
+  ;
+
+type-namespace
  ;; named namespaces like "namespace XXX {"
-  | NAMESPACE symbol namespaceparts
-    (TYPE-TAG $2 $1 $3 nil )
+  : symbol namespaceparts
+    (TYPE-TAG $1 "namespace" $2 nil )
  ;; unnamed namespaces like "namespace {"
-  | NAMESPACE namespaceparts
-    (TYPE-TAG "unnamed" $1 $2 nil )
+  | namespaceparts
+    (TYPE-TAG "unnamed" "namespace" $1 nil )
  ;; David Engster: namespace alias like "namespace foo = bar;"
-  | NAMESPACE symbol EQUAL typeformbase SEMICOLON
-    (TYPE-TAG $2 $1 (list (TYPE-TAG (car $4) $1 nil nil)) nil :kind 'alias )
+  | symbol EQUAL typeformbase SEMICOLON
+    (TYPE-TAG $1 "namespace" (list (TYPE-TAG (car $3) "namespace" nil nil)) nil :kind 'alias )
   ;
 
 ;; Klaus Berndl: We must parse "using namespace XXX" too
@@ -628,8 +660,6 @@ STARMOD
 declmods
   : DECLMOD declmods
     ( ,(cons ,(car ,$1) $2 ) )
-  | DECLMOD
-    ( ,$1 )
   | ;;EMPTY
     ()
   ;
@@ -663,6 +693,7 @@ metadeclmod
 
 CVDECLMOD
   : CONST
+  | CONSTEXPR
   | VOLATILE
   ;
 
@@ -678,6 +709,7 @@ cv-declmods
 METADECLMOD
   : VIRTUAL
   | MUTABLE
+  | EXPLICIT
   ;
 
 ;; C++: A type can be modified into a reference by "&"
@@ -699,11 +731,7 @@ typeformbase
     (TYPE-TAG $2 $1 nil nil )
   | builtintype
     ( ,$1 )
-  | symbol template-specifier
-    (TYPE-TAG $1 "class" nil nil :template-specifier $2)
- ;;| namespace-symbol opt-stars opt-template-specifier
- ;;| namespace-symbol opt-template-specifier
-  | namespace-symbol-for-typeformbase opt-template-specifier
+  | namespace-symbol opt-template-specifier
     (TYPE-TAG (car $1) "class" nil nil
 	      :template-specifier $2)
   | symbol
@@ -843,6 +871,9 @@ opt-post-fcn-modifiers
 post-fcn-modifiers
   : REENTRANT
   | CONST
+  | OVERRIDE
+  | FINAL
+  | NOEXCEPT
   ;
 
 opt-throw
@@ -930,10 +961,15 @@ varname-opt-initializer
   ;
 
 varnamelist
-  : opt-ref varname varname-opt-initializer COMA varnamelist
-    ( ,(cons (append $2 $3) $5) )
-  | opt-ref varname varname-opt-initializer
-    ( (append $2 $3) )
+  : opt-ref varname varname-opt-initializer opt-varnamelist-more
+    ( ,(cons (append $2 $3) (car $4) ))
+  ;
+
+opt-varnamelist-more
+  : COMA varnamelist
+    ( $2 )
+  | ;; EMPTY
+    ()
   ;
 
 ;; Klaus Berndl: Is necessary to parse stuff like
@@ -944,26 +980,18 @@ varnamelist
 ;;     symbol<template-spec>::symbol1<template-spec1>::test_iterator
 ;; but better parsing too much than to less
 namespace-symbol
-  : symbol opt-template-specifier COLON COLON namespace-symbol
-    ( (concat $1 "::" (car $5)) )
-  | symbol opt-template-specifier
+  : symbol opt-template-specifier opt-namespace-symbol-more
+    ( (concat $1 (car $3) ) )
+ ;; Don't accept template specifiers at the end.
+  | symbol
     ( $1 )
   ;
 
-;; Don't pull an optional template specifier at the end of the
-;; namespace symbol so that it can be picked up by the type.
-namespace-symbol-for-typeformbase
-  : symbol opt-template-specifier COLON COLON namespace-symbol-for-typeformbase
-    ( (concat $1 "::" (car $5)) )
-  | symbol
-    ( $1 )
+opt-namespace-symbol-more
+  : COLON COLON namespace-symbol
+    ( (concat "::" (car $3)) )
   ;
-;; namespace-symbol
-;;   : symbol COLON COLON namespace-symbol
-;;     ( (concat $1 "::" (car $4)) )
-;;   | symbol
-;;     ( $1 )
-;;   ;
+
 
 namespace-opt-class
   : symbol COLON COLON namespace-opt-class
@@ -1191,6 +1219,7 @@ expr-start
   | PLUS
   | STAR
   | AMPERSAND
+  | ;; EMPTY
   ;
 
 expr-binop
@@ -1209,12 +1238,14 @@ expr-binop
 ;; Use expression for parsing only.  Don't actually return anything
 ;; for now.  Hopefully we can fix this later.
 expression
-  : unaryexpression QUESTION unaryexpression COLON unaryexpression
-    ( (identity start) (identity end) )
-  | unaryexpression expr-binop unaryexpression
-    ( (identity start) (identity end) )
-  | unaryexpression
-    ( (identity start) (identity end) )
+  : expr-start unaryexpression opt-more-expression
+    ( (identity start) (- end 1) )
+  ;
+
+opt-more-expression
+  : QUESTION unaryexpression COLON unaryexpression
+  | expr-binop unaryexpression
+  | ;; EMPTY
   ;
 
 unaryexpression
@@ -1228,9 +1259,9 @@ unaryexpression
   | string-seq
   | type-cast expression  ;; A cast to some other type
  ;; Casting the results of one expression to something else.
-  | semantic-list expression
+  | semantic-list unaryexpression
   | semantic-list
-  | expr-start expression
+ ;;| expr-start expression
   ;
 
 ;;; c.by ends here
diff --git a/lisp/cedet/ede.el b/lisp/cedet/ede.el
index f013d43..bfa7c6a 100644
--- a/lisp/cedet/ede.el
+++ b/lisp/cedet/ede.el
@@ -63,6 +63,7 @@
 (declare-function ede-toplevel-project "ede/files")
 (declare-function ede-up-directory "ede/files")
 (declare-function semantic-lex-make-spp-table "semantic/lex-spp")
+(declare-function ede-directory-project-cons  "ede/files")
 
 (defconst ede-version "2.0"
   "Current version of the Emacs EDE.")
@@ -1096,22 +1097,6 @@ Flush the dead projects from the project cache."
 
 (defvar ede--disable-inode)             ;Defined in ede/files.el.
 
-(defun ede-global-list-sanity-check ()
-  "Perform a sanity check to make sure there are no duplicate projects."
-  (interactive)
-  (let ((scanned nil))
-    (dolist (P ede-projects)
-      (if (member (oref P directory) scanned)
-	  (error "Duplicate project (by dir) found in %s!" (oref P directory))
-	(push (oref P directory) scanned)))
-    (unless ede--disable-inode
-      (setq scanned nil)
-      (dolist (P ede-projects)
-	(if (member (ede--project-inode P) scanned)
-	  (error "Duplicate project (by inode) found in %s!" (ede--project-inode P))
-	  (push (ede--project-inode P) scanned))))
-    (message "EDE by directory %sis still sane." (if ede--disable-inode "" "& inode "))))
-
 (defun ede-load-project-file (dir &optional detectin rootreturn)
   "Project file independent way to read a project in from DIR.
 Optional DETECTIN is an autoload cons from `ede-detect-directory-for-project'
diff --git a/lisp/cedet/ede/auto.el b/lisp/cedet/ede/auto.el
index 5b3befe..c9eea57 100644
--- a/lisp/cedet/ede/auto.el
+++ b/lisp/cedet/ede/auto.el
@@ -63,74 +63,62 @@ location is varied dependent on other complex criteria, this class
 can be used to define that match without loading the specific project
 into memory.")
 
-(cl-defmethod ede-dirmatch-installed ((dirmatch ede-project-autoload-dirmatch))
-  "Return non-nil if the tool DIRMATCH might match is installed on the system."
-  (let ((fc (oref dirmatch fromconfig)))
-
-    (cond
-     ;; If the thing to match is stored in a config file.
-     ((stringp fc)
-      (file-exists-p fc))
-
-     ;; Add new types of dirmatches here.
+(cl-defmethod ede-calc-fromconfig ((dirmatch ede-project-autoload-dirmatch))
+  "Calculate the value of :fromconfig from DIRMATCH."
+  (let* ((fc (oref dirmatch fromconfig))
+	 (found (cond ((stringp fc) fc)
+		      ((functionp fc) (funcall fc))
+		      (t (error "Unknown dirmatch object match style.")))))
+    (expand-file-name found)
+    ))
 
-     ;; Error for weird stuff
-     (t (error "Unknown dirmatch type.")))))
 
+(cl-defmethod ede-dirmatch-installed ((dirmatch ede-project-autoload-dirmatch))
+  "Return non-nil if the tool DIRMATCH might match is installed on the system."
+  (file-exists-p (ede-calc-fromconfig dirmatch)))
 
 (cl-defmethod ede-do-dirmatch ((dirmatch ede-project-autoload-dirmatch) file)
   "Does DIRMATCH match the filename FILE."
-  (let ((fc (oref dirmatch fromconfig)))
-
-    (cond
-     ;; If the thing to match is stored in a config file.
-     ((stringp fc)
-      (when (file-exists-p fc)
-	(let ((matchstring
-	       (if (slot-boundp dirmatch 'configdatastash)
-		   (oref dirmatch configdatastash)
-		 nil)))
-	  (when (and (not matchstring) (not (slot-boundp dirmatch 'configdatastash)))
-	    (save-current-buffer
-	      (let* ((buff (get-file-buffer fc))
-		     (readbuff
-		      (let ((find-file-hook nil)) ;; Disable ede from recursing
-			(find-file-noselect fc))))
-		(set-buffer readbuff)
-		(save-excursion
-		  (goto-char (point-min))
-		  (when (re-search-forward (oref dirmatch configregex) nil t)
-		    (setq matchstring
-			  (match-string (or (oref dirmatch configregexidx) 0)))))
-		(if (not buff) (kill-buffer readbuff))))
-	    (when matchstring
-	      ;; If this dirmatch only finds subdirs of matchstring, then
-	      ;; force matchstring to be a directory.
-	      (when (oref dirmatch subdir-only)
-		(setq matchstring (file-name-as-directory matchstring)))
-	      ;; Convert matchstring to a regexp
-	      (setq matchstring (concat "^" (regexp-quote matchstring)))
-	      ;; Stash it for later.
-	      (oset dirmatch configdatastash matchstring))
-	    ;; Debug
-	    ;;(message "Stashing config data for dirmatch %S as %S" (eieio-object-name dirmatch) matchstring)
-	    )
-	  ;;(message "dirmatch %s against %s" matchstring (expand-file-name file))
-	  ;; Match against our discovered string
-	  (setq file (file-name-as-directory (expand-file-name file)))
-	  (and matchstring (string-match matchstring (expand-file-name file))
-	       (or (not (oref dirmatch subdir-only))
-		   (not (= (match-end 0) (length file))))
-	       )
-	  )))
-
-     ;; Add new matches here
-     ;; ((stringp somenewslot ...)
-     ;;   )
-
-     ;; Error if none others known
-     (t
-      (error "Unknown dirmatch object match style.")))
+  (let ((fc (ede-calc-fromconfig dirmatch)))
+
+    (when (file-exists-p fc)
+      (let ((matchstring 
+	     (if (slot-boundp dirmatch 'configdatastash)
+		 (oref dirmatch configdatastash)
+	       nil)))
+	(when (and (not matchstring) (not (slot-boundp dirmatch 'configdatastash)))
+	  (save-current-buffer
+	    (let* ((buff (get-file-buffer fc))
+		   (readbuff
+		    (let ((find-file-hook nil)) ;; Disable ede from recursing
+		      (find-file-noselect fc))))
+	      (set-buffer readbuff)
+	      (save-excursion
+		(goto-char (point-min))
+		(when (re-search-forward (oref dirmatch configregex) nil t)
+		  (setq matchstring
+			(match-string (or (oref dirmatch configregexidx) 0)))))
+	      (if (not buff) (kill-buffer readbuff))))
+	  (when matchstring
+	    ;; If this dirmatch only finds subdirs of matchstring, then
+	    ;; force matchstring to be a directory.
+	    (when (oref dirmatch subdir-only)
+	      (setq matchstring (file-name-as-directory matchstring)))
+	    ;; Convert matchstring to a regexp
+	    (setq matchstring (concat "^" (regexp-quote matchstring)))
+	    ;; Stash it for later.
+	    (oset dirmatch configdatastash matchstring))
+	  ;; Debug
+	  ;;(message "Stashing config data for dirmatch %S as %S" (eieio-object-name dirmatch) matchstring)
+	  )
+	;;(message "dirmatch %s against %s" matchstring (expand-file-name file))
+	;; Match against our discovered string
+	(setq file (file-name-as-directory (expand-file-name file)))
+	(and matchstring (string-match matchstring (expand-file-name file))
+	     (or (not (oref dirmatch subdir-only))
+		 (not (= (match-end 0) (length file))))
+	     )
+	))
     ))
 
 (declare-function ede-directory-safe-p "ede")
@@ -225,15 +213,8 @@ type is required and the load function used.")
 (defun ede-show-supported-projects ()
   "Display all the project types registered with EDE."
   (interactive)
-  (let ((b (get-buffer-create "*EDE Autodetect Projects*")))
-    (set-buffer b)
-    (setq buffer-read-only nil)
-    (erase-buffer)
-    (dolist (prj ede-project-class-files)
-      (insert (oref prj name))
-      (newline))
-    (display-buffer b)
- ))
+  (data-debug-new-buffer (concat "*EDE Autodetect*"))
+  (data-debug-insert-stuff-list ede-project-class-files "* "))
 
 (defun ede-add-project-autoload (projauto &optional flag)
   "Add PROJAUTO, an EDE autoload definition to `ede-project-class-files'.
@@ -288,7 +269,7 @@ added.  Possible values are:
 	 (pf (oref this proj-file))
 	 (f (when (stringp pf) (expand-file-name pf d))))
     (if f
-	(and f (file-exists-p f))
+	(file-exists-p f)
       (let ((dirmatch (oref this proj-root-dirmatch)))
 	(cond
 	 ((stringp dirmatch)
diff --git a/lisp/cedet/ede/config.el b/lisp/cedet/ede/config.el
index a9042e5..a7ca80e 100644
--- a/lisp/cedet/ede/config.el
+++ b/lisp/cedet/ede/config.el
@@ -55,6 +55,11 @@
 
 ;;; Code:
 (require 'ede)
+(require 'ede/shell)
+
+(declare-function semanticdb-file-table-object "semantic/db")
+(declare-function semanticdb-needs-refresh-p "semantic/db")
+(declare-function semanticdb-refresh-table "semantic/db")
 
 ;;; CONFIG
 ;;
@@ -401,7 +406,14 @@ the preprocessor map, and include paths.")
   "Class to mix into a configuration for compilation.")
 
 (defclass ede-project-with-config-java ()
-  ()
+  ((classpath :initarg :classpath
+	      :initform nil
+	      :type list
+	      :group java
+	      :custom (repeat (string :tag "Classpath"))
+	      :documentation
+	      "The default classpath used within a project.
+ All files listed in the local path are full paths to files."))
   "Class to mix into a project to support java.
 This brings in methods to support Semantic querying the
 java class path.")
diff --git a/lisp/cedet/ede/detect.el b/lisp/cedet/ede/detect.el
index 2b92fc1..392b187 100644
--- a/lisp/cedet/ede/detect.el
+++ b/lisp/cedet/ede/detect.el
@@ -35,15 +35,10 @@
 
 (require 'ede/auto) ;; Autoload settings.
 
-(when (or (<= emacs-major-version 23)
-	  ;; predicate as name added in Emacs 24.2
-	  (and (= emacs-major-version 24)
-	       (< emacs-minor-version 2)))
-  (message "Loading CEDET fallback autoload library.")
-  (require 'cedet/dominate
-	   (expand-file-name "../../../etc/fallback-libraries/dominate.el"
-			     (file-name-directory load-file-name))))
-
+;; `locate-dominating-file' is wrapped for older Emacsen, which miss
+;; the predicate feature.
+(unless (fboundp 'cedet-locate-dominating-file)
+  (defalias 'cedet-locate-dominating-file 'locate-dominating-file))
 
 ;;; BASIC PROJECT SCAN
 ;;
@@ -83,8 +78,8 @@ Return a cons cell:
   (let* ((ede--detect-found-project nil)
 	 (root
 	  (catch 'stopscan
-	    (locate-dominating-file directory
-				    'ede--detect-ldf-predicate))))
+	    (cedet-locate-dominating-file directory
+					  'ede--detect-ldf-predicate))))
     (when root
       (cons root ede--detect-found-project))))
 
@@ -119,8 +114,8 @@ Return a cons cell:
   (let* ((ede--detect-found-project nil)
 	 (root
 	  (catch 'stopscan
-	    (locate-dominating-file directory
-				    'ede--detect-ldf-rootonly-predicate))))
+	    (cedet-locate-dominating-file directory
+					  'ede--detect-ldf-rootonly-predicate))))
     (when root
       (cons root ede--detect-found-project))))
 
@@ -143,7 +138,8 @@ Return a cons cell:
 	    ;; If it didn't change, then obviously this must be the top.
 	    t
 	  ;; If it is different, check updir for the file.
-	  (not (ede-auto-detect-in-dir ede--detect-nomatch-auto updir))))))
+	  (or (null updir)
+	      (not (ede-auto-detect-in-dir ede--detect-nomatch-auto updir)))))))
 
 (defun ede--detect-scan-directory-for-project-root (directory auto)
   "If DIRECTORY has already been detected with AUTO, find the root.
@@ -151,8 +147,8 @@ Some projects have their dominating file in all their directories, such
 as Project.ede.  In that case we will detect quickly, but then need
 to scan upward to find the topmost occurrence of that file."
   (let* ((ede--detect-nomatch-auto auto)
-	 (root (locate-dominating-file directory
-				       'ede--detect-ldf-root-predicate)))
+	 (root (cedet-locate-dominating-file directory
+					     'ede--detect-ldf-root-predicate)))
     root))
 
 ;;; TOP LEVEL SCAN
diff --git a/lisp/cedet/ede/emacs.el b/lisp/cedet/ede/emacs.el
index 427f1a4..a418c75 100644
--- a/lisp/cedet/ede/emacs.el
+++ b/lisp/cedet/ede/emacs.el
@@ -136,6 +136,11 @@ All directories need at least one target.")
   "EDE Emacs Project target for Emacs Lisp code.
 All directories need at least one target.")
 
+(defclass ede-emacs-target-texi (ede-target)
+  ()
+  "EDE Emacs Project target for Emacs Lisp code.
+All directories need at least one target.")
+
 (defclass ede-emacs-target-misc (ede-target)
   ()
   "EDE Emacs Project target for Misc files.
@@ -186,6 +191,8 @@ If one doesn't exist, create a new one for this directory."
 		     'ede-emacs-target-c)
 		    ((string-match "elc?" ext)
 		     'ede-emacs-target-el)
+		    ((string-match "texi" ext)
+		     'ede-emacs-target-texi)
 		    (t 'ede-emacs-target-misc)))
 	 (targets (oref proj targets))
 	 (dir default-directory)
@@ -282,6 +289,40 @@ Knows about how the Emacs source tree is organized."
     (oset this version (cdr ver))
     ))
 
+;;; Compile Support
+;;
+(defmethod project-compile-project ((proj ede-emacs-project) &optional command)
+  "Compile the Emacs project.
+Argument COMMAND is the command to use when compiling."
+  (let ((default-directory (ede-project-root-directory proj)))
+    (require 'compile)
+    (compile "make all")))
+
+(defmethod project-compile-target ((proj ede-emacs-target-texi) &optional command)
+  "Compile the doc target for Emacs.
+Argument COMMAND is the command to use for compiling the target."
+  (let* ((default-directory (ede-project-root-directory (ede-current-project)))
+	 (command "make docs"))
+    (require 'compile)
+    (compile command)))
+
+(defmethod project-compile-target ((proj ede-emacs-target-el) &optional command)
+  "Compile the doc target for Emacs.
+Argument COMMAND is the command to use for compiling the target."
+  (let* ((default-directory (ede-project-root-directory (ede-current-project)))
+	 (command "make lisp"))
+    (require 'compile)
+    (compile command)))
+
+(defmethod project-compile-target ((proj ede-emacs-target-c) &optional command)
+  "Compile the doc target for Emacs.
+Argument COMMAND is the command to use for compiling the target."
+  (let* ((default-directory (ede-project-root-directory (ede-current-project)))
+	 (command "make src"))
+    (require 'compile)
+    (compile command)))
+
+
 (provide 'ede/emacs)
 
 ;; Local variables:
diff --git a/lisp/cedet/ede/files.el b/lisp/cedet/ede/files.el
index 3f23bfc..d288c65 100644
--- a/lisp/cedet/ede/files.el
+++ b/lisp/cedet/ede/files.el
@@ -67,6 +67,22 @@ the current EDE project."
     (when loc
       (ede-locate-flush-hash loc))))
 
+(defun ede-global-list-sanity-check ()
+  "Perform a sanity check to make sure there are no duplicate projects."
+  (interactive)
+  (let ((scanned nil))
+    (dolist (P ede-projects)
+      (if (member (oref P directory) scanned)
+	  (error "Duplicate project (by dir) found in %s!" (oref P directory))
+	(push (oref P directory) scanned)))
+    (unless ede--disable-inode
+      (setq scanned nil)
+      (dolist (P ede-projects)
+	(if (member (ede--project-inode P) scanned)
+	  (error "Duplicate project (by inode) found in %s!" (ede--project-inode P))
+	  (push (ede--project-inode P) scanned))))
+    (message "EDE by directory %sis still sane." (if ede--disable-inode "" "& inode "))))
+
 ;;; Placeholders for ROOT directory scanning on base objects
 ;;
 (cl-defmethod ede-project-root ((this ede-project-placeholder))
diff --git a/lisp/cedet/ede/linux.el b/lisp/cedet/ede/linux.el
index 010bfde..73efe4d 100644
--- a/lisp/cedet/ede/linux.el
+++ b/lisp/cedet/ede/linux.el
@@ -118,7 +118,8 @@ If DIR has not been used as a build directory, fall back to
    ;; use configuration
    (case project-linux-build-directory-default
      (same dir)
-     (ask (read-directory-name "Select Linux' build directory: " dir)))))
+     (ask (read-directory-name "Select Linux' build directory: " dir))
+     (t project-linux-build-directory-default))))

 (defun ede-linux--get-archs (dir)
diff --git a/lisp/cedet/ede/proj.el b/lisp/cedet/ede/proj.el
index d6f5210..a856509 100644
--- a/lisp/cedet/ede/proj.el
+++ b/lisp/cedet/ede/proj.el
@@ -184,7 +184,7 @@ Target variables are always renamed such as foo_CFLAGS, then included into
 commands where the variable would usually appear.")
    (rules :initarg :rules
 	  :initform nil
-	  :type list
+	  :type ede-makefile-rule-list
 	  :custom (repeat (object :objecttype ede-makefile-rule))
 	  :label "Additional Rules"
 	  :group (make)
@@ -251,6 +251,7 @@ in targets.")
 These variables are used in the makefile when a configuration becomes active.")
    (inference-rules :initarg :inference-rules
 		    :initform nil
+		    :type ede-makefile-rule-list
 		    :custom (repeat
 			     (object :objecttype ede-makefile-rule))
 		    :documentation "Inference rules to add to the makefile.")
diff --git a/lisp/cedet/semantic/analyze.el b/lisp/cedet/semantic/analyze.el
index 68f5c82..ec7d834 100644
--- a/lisp/cedet/semantic/analyze.el
+++ b/lisp/cedet/semantic/analyze.el
@@ -219,6 +219,23 @@ Optional argument DESIRED-TYPE may be a non-type tag to analyze."
   "Try the base, and if that fails, return what we are assigning into."
   (or (cl-call-next-method) (car-safe (oref context :assignee))))
 
+;;; TYPE MEMBERS
+;;
+;; When analyzing tag sequences, we dive through structured data
+;; such as structs, classes, unions, etc.  The raw member list
+;; is sometimes insufficient for generating completions, so each
+;; language nees an opportunity to get the type members that are
+;; accessable via a code snippet.  A key example is anonymous
+;; unions in C/C++, whose members are completable in the parent
+;; member list, but are structured in the tag as a single item.
+(define-overloadable-function semantic-analyze-tag-type-members (tag)
+  "Return a list of members of TAG, where TAG is a type.
+By default, call `semantic-tag-type-members'.")
+
+(defun semantic-analyze-tag-type-members-default (tag)
+  "Return a list of members of TAG, where TAG is a type."
+  (semantic-tag-type-members tag))
+
 ;;; ANALYSIS
 ;;
 ;; Start out with routines that will calculate useful parts of
@@ -345,7 +362,7 @@ This function knows of flags:
 	(when miniscope
 	  (let ((rawscope
 		 (apply 'append
-			(mapcar 'semantic-tag-type-members tagtype))))
+			(mapcar 'semantic-analyze-tag-type-members tagtype))))
 	    (oset miniscope fullscope rawscope)))
 	)
       (setq s (cdr s)))
@@ -589,7 +606,7 @@ Returns an object based on symbol `semantic-analyze-context'."
 		;; the found datatype.
 		(setq fcn (semantic-find-tags-by-name
 			   (semantic-tag-name (car ty))
-			   (semantic-tag-type-members (car ty))))
+			   (semantic-analyze-tag-type-members (car ty))))
 		(if fcn
 		    (let ((lp fcn))
 		      (while lp
@@ -787,7 +804,8 @@ Use BUFF as a source of override methods."
   (semantic-analyze-princ-sequence (oref context prefix) "Prefix: " )
   (semantic-analyze-princ-sequence (oref context prefixclass) "Prefix Classes: ")
   (semantic-analyze-princ-sequence (oref context prefixtypes) "Prefix Types: ")
-  (semantic-analyze-princ-sequence (oref context errors) "Encountered Errors: ")
+  (semantic-analyze-princ-sequence (when (slot-boundp context 'errors) (oref context errors))
+				   "Encountered Errors: ")
   (princ "--------\n")
   ;(semantic-analyze-princ-sequence (oref context scopetypes) "Scope Types: ")
   ;(semantic-analyze-princ-sequence (oref context scope) "Scope: ")
diff --git a/lisp/cedet/semantic/analyze/complete.el b/lisp/cedet/semantic/analyze/complete.el
index 698fce8..6d24013 100644
--- a/lisp/cedet/semantic/analyze/complete.el
+++ b/lisp/cedet/semantic/analyze/complete.el
@@ -235,7 +235,7 @@ FLAGS can be any number of:
 	   ((semantic-tag-type (car loopc))
 	    (let ((att (semantic-analyze-tag-type (car loopc) scope))
 		)
-	      (if (and att (semantic-tag-type-members att))
+	      (if (and att (semantic-analyze-tag-type-members att))
 		  (setq c (cons (car loopc) c))))
 	    )
 
diff --git a/lisp/cedet/semantic/analyze/debug.el b/lisp/cedet/semantic/analyze/debug.el
index 03979f5..13bd66a 100644
--- a/lisp/cedet/semantic/analyze/debug.el
+++ b/lisp/cedet/semantic/analyze/debug.el
@@ -35,7 +35,7 @@
 (declare-function ede-get-locator-object "ede/files")
 
 ;;; Code:
-
+;;;###autoload
 (defun semantic-analyze-debug-assist ()
   "Debug semantic analysis at the current point."
   (interactive)
@@ -307,7 +307,7 @@ possible completions for \"")
 	(princ "\nKnown members of ")
 	(princ (semantic-tag-name dt))
 	(princ ":\n")
-	(dolist (M (semantic-tag-type-members dt))
+	(dolist (M (semantic-analyze-tag-type-members dt))
 	  (princ "  ")
 	  ;;(princ (semantic-format-tag-prototype M))
 	  (semantic-analyzer-debug-insert-tag M)
diff --git a/lisp/cedet/semantic/analyze/fcn.el b/lisp/cedet/semantic/analyze/fcn.el
index 1337f19..de487f1 100644
--- a/lisp/cedet/semantic/analyze/fcn.el
+++ b/lisp/cedet/semantic/analyze/fcn.el
@@ -183,7 +183,16 @@ Optional SCOPE represents a calculated scope in which the
 types might be found.  This can be nil.
 If NOMETADEREF, then do not dereference metatypes.  This is
 used by the analyzer debugger."
-  (semantic-analyze-type (semantic-tag-type tag) scope nometaderef))
+  (or 
+   (semantic-analyze-type (semantic-tag-type tag) scope nometaderef)
+   ;; If we didn't find it the 'quick' way with the passed in scope,
+   ;; perhaps the type is using a shorthand only available from the
+   ;; location of TAG, which might be a member of some struct far away
+   ;; from the original source that spawed the search.
+   (let ((tagscope (semantic-calculate-scope-for-tag tag)))
+     (when tagscope
+       (semantic-analyze-type (semantic-tag-type tag)
+			      tagscope nometaderef)))))
 
 (defun semantic-analyze-type (type-declaration &optional scope nometaderef)
   "Return the semantic tag for TYPE-DECLARATION.
diff --git a/lisp/cedet/semantic/bovine/c.el b/lisp/cedet/semantic/bovine/c.el
index 821f05a..d13a7dd 100644
--- a/lisp/cedet/semantic/bovine/c.el
+++ b/lisp/cedet/semantic/bovine/c.el
@@ -1022,6 +1022,15 @@ now.
       (setq return-list (car tag))
       (setq tag (cdr tag)))
 
+    ;; Check if we have a typed enum, and if so, apply its type to all
+    ;; members.
+    (when (and (semantic-tag-of-type-p tag "enum")
+	       (semantic-tag-get-attribute tag :enum-type))
+      (let ((enumtype (semantic-tag-get-attribute tag :enum-type))
+	    (members (semantic-tag-get-attribute tag :members)))
+	(dolist (cur members)
+	  (semantic-tag-put-attribute cur :type enumtype))))
+
     ;; Name of the tag is a list, so expand it.  Tag lists occur
     ;; for variables like this: int var1, var2, var3;
     ;;
@@ -1178,13 +1187,16 @@ is its own toplevel tag.  This function will return (cons A B)."
 	   (while names
 
 	     (setq vl (cons (semantic-tag-new-type
-			     (nth 1 (car names)) ; name
+			     (nth 2 (car names)) ; name
 			     "typedef"
 			     (semantic-tag-type-members tag)
 			     nil
 			     :pointer
 			     (let ((stars (car (car (car names)))))
 			       (if (= stars 0) nil stars))
+			     :reference
+			     (let ((refs (car (nth 1 (car names)))))
+			       (when (> refs 0) refs))
 			     ;; This specifies what the typedef
 			     ;; is expanded out as.  Just the
 			     ;; name shows up as a parent of this
@@ -1301,14 +1313,15 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
 			  (nth 10 tokenpart) ; initializers
 			  )
 		      (not (car (nth 3 tokenpart)))))
-		(fcnpointer (and (> (length (car tokenpart)) 0)
+		(operator (if (string-match "[a-zA-Z]" (car tokenpart))
+			      nil
+			    t))
+		(fcnpointer (and (not operator)
+				 (> (length (car tokenpart)) 1)
 				 (= (aref (car tokenpart) 0) ?*)))
 		(fnname (if fcnpointer
 			    (substring (car tokenpart) 1)
 			  (car tokenpart)))
-		(operator (if (string-match "[a-zA-Z]" fnname)
-			      nil
-			    t))
 		)
 	   ;; The function
 	   (semantic-tag-new-function
@@ -1348,8 +1361,10 @@ Optional argument STAR and REF indicate the number of * and & in the typedef."
 	    ;; `throws' as a common name for things that toss
 	    ;; exceptions about.
 	    :throws (nth 5 tokenpart)
-	    ;; Reentrant is a C++ thingy.  Add it here
+	    ;; Reentrant, override, final are a C++ things.  Add it here.
 	    :reentrant-flag (if (member "reentrant" (nth 6 tokenpart)) t)
+	    :override-flag (if (member "override" (nth 6 tokenpart)) t)
+	    :final-flag (if (member "final" (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
@@ -1406,8 +1421,18 @@ PARENT specifies a parent class.
 COLOR indicates that the text should be type colorized.
 Enhances the base class to search for the entire parent
 tree to make the name accurate."
-  (semantic-format-tag-canonical-name-default tag parent color)
-  )
+  (cond 
+   ((and (semantic-tag-of-class-p tag 'type)
+	 (semantic-tag-get-attribute tag :parent))
+    ;; We nee to combine the :parent into the tag name and continue on.
+    (let* ((par (semantic-tag-get-attribute tag :parent))
+	   (parstr (if (stringp par) par
+		     (mapconcat 'identity par "::")))
+	   (clone (semantic-tag-clone 
+		   tag (concat parstr "::" (semantic-tag-name tag)))))
+      (semantic-format-tag-canonical-name-default clone parent color)))
+   (t (semantic-format-tag-canonical-name-default tag parent color))
+  ))
 
 (define-mode-local-override semantic-format-tag-type c-mode (tag color)
   "Convert the data type of TAG to a string usable in tag formatting.
@@ -1637,6 +1662,8 @@ SCOPE is not used, and TYPE-DECLARATION is used only if TYPE is not a typedef."
 	       (let* ((fname (semantic-tag-file-name type))
 		      (def (semantic-tag-copy dt nil fname)))
 		 (list def def)))
+	      ((semantic-tag-p dt)
+	       (list (semantic-format-tag-canonical-name dt) dt))
               ((stringp dt) (list dt (semantic-tag dt 'type)))
               ((consp dt) (list (car dt) dt))))
 
@@ -1858,6 +1885,23 @@ These are constants which are of type TYPE."
   "Assemble the list of names NAMELIST into a namespace name."
   (mapconcat 'identity namelist "::"))
 
+(define-mode-local-override semantic-analyze-tag-type-members c-mode (tag)
+  "Return a list of :members of TAG.
+Merges in all members of anonymous unions that are :members of TAG."
+  (let ((raw (semantic-tag-type-members tag))
+	(ans nil))
+    (dolist (T raw)
+      (cond ((and (semantic-tag-of-class-p T 'type)
+	    	  (semantic-tag-of-type-p T "union")
+	    	  (string= (semantic-tag-name T) ""))
+	     ;; Merge in all the union members.
+	     (dolist (Ts (semantic-analyze-tag-type-members T))
+	       (setq ans (cons Ts ans))))
+	    ;; Be default, just push the tag.
+	    (t
+	     (setq ans (cons T ans)))))
+    (nreverse ans)))
+
 (define-mode-local-override semantic-ctxt-scoped-types c++-mode (&optional point)
   "Return a list of tags of CLASS type based on POINT.
 DO NOT return the list of tags encompassing point."
@@ -2028,10 +2072,12 @@ have to be wrapped in that namespace."
 	    (setq sv (cdr sv)))
 
 	  ;; This is optional, and potentially fraught w/ errors.
-	  (condition-case nil
-	      (dolist (lt sv)
-		(setq txt (concat txt " " (semantic-lex-token-text lt))))
-	    (error (setq txt (concat txt "  #error in summary fcn"))))
+	  (if (stringp sv)
+	      (setq txt (concat txt " " sv))
+	    (condition-case nil
+		(dolist (lt sv)
+		  (setq txt (concat txt " " (semantic-lex-token-text lt))))
+	      (error (setq txt (concat txt "  #error in summary fcn")))))
 
 	  txt)
       (semantic-idle-summary-current-symbol-info-default))))
diff --git a/lisp/cedet/semantic/bovine/el.el b/lisp/cedet/semantic/bovine/el.el
index 6f41ba3..c97d53c 100644
--- a/lisp/cedet/semantic/bovine/el.el
+++ b/lisp/cedet/semantic/bovine/el.el
@@ -921,6 +921,9 @@ See `semantic-format-tag-prototype' for Emacs Lisp for more details."
 (defvar-mode-local emacs-lisp-mode semantic-function-argument-separation-character
   " ")
 
+(defvar-mode-local emacs-lisp-mode semantic-type-relation-separator-character
+  nil)
+
 (defvar-mode-local emacs-lisp-mode semantic-symbol->name-assoc-list
   '(
     (type     . "Types")
diff --git a/lisp/cedet/semantic/bovine/make.el b/lisp/cedet/semantic/bovine/make.el
index b550f50..2859491 100644
--- a/lisp/cedet/semantic/bovine/make.el
+++ b/lisp/cedet/semantic/bovine/make.el
@@ -175,9 +175,10 @@ This is the same as a regular prototype."
   (semantic-format-tag-prototype tag parent color))
 
 (define-mode-local-override semantic-analyze-possible-completions
-  makefile-mode (context)
+  makefile-mode (context &rest flags)
   "Return a list of possible completions in a Makefile.
-Uses default implementation, and also gets a list of filenames."
+Uses default implementation, and also gets a list of filenames.
+Any extra FLAGS are ignored."
   (require 'semantic/analyze/complete)
   (with-current-buffer (oref context buffer)
     (let* ((normal (semantic-analyze-possible-completions-default context))
diff --git a/lisp/cedet/semantic/bovine/scm.el b/lisp/cedet/semantic/bovine/scm.el
index 3e9b118..2d7d6a6 100644
--- a/lisp/cedet/semantic/bovine/scm.el
+++ b/lisp/cedet/semantic/bovine/scm.el
@@ -106,6 +106,10 @@ syntax as specified by the syntax table."
         imenu-create-index-function 'semantic-create-imenu-index
         )
   (setq semantic-lex-analyzer #'semantic-scheme-lexer)
+  (setq semantic-lex-syntax-modifications '((?/ "w")
+                                            (?@ "_")
+                                            )
+        )
   )
 
 (provide 'semantic/bovine/scm)
diff --git a/lisp/cedet/semantic/complete.el b/lisp/cedet/semantic/complete.el
index de76232..abdd5de 100644
--- a/lisp/cedet/semantic/complete.el
+++ b/lisp/cedet/semantic/complete.el
@@ -209,7 +209,8 @@ HISTORY is a symbol representing a variable to story the history in."
 	 (semantic-completion-display-engine displayor)
 	 (semantic-complete-active-default nil)
 	 (semantic-complete-current-matched-tag nil)
-	 (default-as-tag (semantic-complete-default-to-tag default-tag))
+	 (default-as-tag (save-current-buffer
+			   (semantic-complete-default-to-tag default-tag)))
 	 (default-as-string (when (semantic-tag-p default-as-tag)
 			      (semantic-tag-name default-as-tag)))
 	 )
@@ -1026,14 +1027,19 @@ Output must be in semanticdb Find result format."
 		      (eq (compare-strings
 			   prefix 0 nil
 			   last-prefix 0 (length prefix)) t))
-		   ;; The new prefix is a substring of the old
-		   ;; prefix, and it's longer than one character.
-		   ;; Perform a full search to pull in additional
-		   ;; matches.
-		 (let ((context (semantic-analyze-current-context (point))))
-		   ;; Set new context and make first-pass-completions
-		   ;; unbound so that they are newly calculated.
-		   (oset obj context context)
+		 ;; The new prefix is a substring of the old
+		 ;; prefix, and it's longer than one character.
+		 ;; Perform a full search to pull in additional
+		 ;; matches.
+		 (when (slot-exists-p obj 'context)
+		   ;; If this collector wants an analyzed context,
+		   ;; then restart here.
+		   (save-current-buffer
+		     (set-buffer (oref obj buffer))
+		     (let ((context (semantic-analyze-current-context (point))))
+		       ;; Set new context and make first-pass-completions
+		       ;; unbound so that they are newly calculated.
+		       (oset obj context context)))
 		   (when (slot-boundp obj 'first-pass-completions)
 		     (slot-makeunbound obj 'first-pass-completions)))
 		 nil)))
diff --git a/lisp/cedet/semantic/ctxt.el b/lisp/cedet/semantic/ctxt.el
index d24cfe6..899546e 100644
--- a/lisp/cedet/semantic/ctxt.el
+++ b/lisp/cedet/semantic/ctxt.el
@@ -454,7 +454,8 @@ This will include a list of type/field names when applicable.
 Depends on `semantic-type-relation-separator-character'."
   (save-excursion
     (if point (goto-char point))
-    (let* ((fieldsep1 (mapconcat (lambda (a) (regexp-quote a))
+    (let* ((dosequence (not (null semantic-type-relation-separator-character)))
+	   (fieldsep1 (mapconcat (lambda (a) (regexp-quote a))
 				 semantic-type-relation-separator-character
 				 "\\|"))
 	   ;; NOTE: The [ \n] expression below should used \\s-, but that
@@ -491,9 +492,11 @@ Depends on `semantic-type-relation-separator-character'."
 
 	  ;; Now that we have gotten started, let's do the rest.
 	  (condition-case nil
-	      (while (save-excursion
-		       (forward-char -1)
-		       (looking-at "\\w\\|\\s_"))
+	      (while (and 
+		      (or dosequence (not symlist))
+		      (save-excursion
+			(forward-char -1)
+			(looking-at "\\w\\|\\s_")))
 		;; We have a symbol.. Do symbol things
 		(forward-sexp -1)
 		(setq symlist (cons (buffer-substring-no-properties (point) end)
@@ -610,6 +613,8 @@ Depends on `semantic-function-argument-separation-character'."
 	  (let ((p (point))
 		(idx 1))
 	    (semantic-up-context)
+	    ;; TODO: myfun3(fun_for_arg1(i,j), arg2 !, arg3)
+	    ;; at ! it thinks it's arg 3.
 	    (while (re-search-forward
 		    (regexp-quote semantic-function-argument-separation-character)
 		    p t)
diff --git a/lisp/cedet/semantic/db-global.el b/lisp/cedet/semantic/db-global.el
index 03a21b0..5ebe8c4 100644
--- a/lisp/cedet/semantic/db-global.el
+++ b/lisp/cedet/semantic/db-global.el
@@ -90,7 +90,8 @@ MODE is the major mode to support."
 When GNU Global is not available for this directory, display a message
 if optional DONT-ERR-IF-NOT-AVAILABLE is non-nil; else throw an error."
   (interactive "P")
-  (if (cedet-gnu-global-root)
+  (if (and (file-exists-p default-directory)
+	   (cedet-gnu-global-root))
       (setq
        ;; Add to the system database list.
        semanticdb-project-system-databases
diff --git a/lisp/cedet/semantic/db-typecache.el b/lisp/cedet/semantic/db-typecache.el
index 366af60..470f347 100644
--- a/lisp/cedet/semantic/db-typecache.el
+++ b/lisp/cedet/semantic/db-typecache.el
@@ -499,7 +499,9 @@ found tag to be loaded."
       ;; the next set of members.
       (if (not ans)
 	  (setq notdone nil)
-	(setq stream (semantic-tag-type-members ans)))
+	;; When pulling the next stream, only get the members we
+	;; are supposed to complete on.
+	(setq stream (semantic-analyze-tag-type-members ans)))
 
       (setq lastans ans
 	    ans nil
diff --git a/lisp/cedet/semantic/db.el b/lisp/cedet/semantic/db.el
index a72e784..094aca7 100644
--- a/lisp/cedet/semantic/db.el
+++ b/lisp/cedet/semantic/db.el
@@ -60,7 +60,7 @@ mechanism.")
 (defvar semanticdb-default-find-index-class 'semanticdb-find-search-index
   "The default type of search index to use for a `semanticdb-table's.
 This can be changed to try out new types of search indices.")
-(make-variable-buffer-local 'semanticdb-default-find=index-class)
+(make-variable-buffer-local 'semanticdb-default-find-index-class)
 
 ;;;###autoload
 (defvar semanticdb-current-database nil
diff --git a/lisp/cedet/semantic/ede-grammar.el b/lisp/cedet/semantic/ede-grammar.el
index 60b6fef..68c1b67 100644
--- a/lisp/cedet/semantic/ede-grammar.el
+++ b/lisp/cedet/semantic/ede-grammar.el
@@ -44,8 +44,8 @@
 		       (semantic-ede-grammar-compiler-wisent
 			semantic-ede-grammar-compiler-bovine
 			))
-   (aux-packages :initform '("semantic" "cedet-compat"))
-   (pre-load-packages :initform '("cedet-compat" "semantic/grammar" "semantic/bovine/grammar" "semantic/wisent/grammar"))
+   (aux-packages :initform '("semantic"))
+   (pre-load-packages :initform '("semantic/grammar" "semantic/bovine/grammar" "semantic/wisent/grammar"))
    )
   "This target consists of a group of grammar files.
 A grammar target consists of grammar files that build Emacs Lisp programs for
@@ -134,6 +134,7 @@ Lays claim to all -by.el, and -wy.el files."
     (cl-call-next-method) ; The usual thing.
     ))
 
+
 (cl-defmethod project-compile-target ((obj semantic-ede-proj-target-grammar))
   "Compile all sources in a Lisp target OBJ."
   (let* ((cb (current-buffer))
@@ -177,7 +178,7 @@ Lays claim to all -by.el, and -wy.el files."
   "Insert variables needed by target THIS."
   (ede-proj-makefile-insert-loadpath-items
    (ede-proj-elisp-packages-to-loadpath
-    (list "eieio" "semantic" "inversion" "ede")))
+    (list "semantic" "inversion" "ede")))
   ;; eieio for object system needed in ede
   ;; semantic because it is
   ;; Inversion for versioning system.
@@ -187,7 +188,7 @@ Lays claim to all -by.el, and -wy.el files."
     (insert
      (mapconcat (lambda (src)
 		  (with-current-buffer (find-file-noselect src)
-		    (concat (semantic-grammar-package) ".el")))
+		    (concat (semantic-grammar-package t) ".el")))
 		(oref this source)
 		" ")))
   )
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 0a259f0..4228b50 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -266,17 +266,19 @@ That is tag names plus names defined in tag attribute `:rest'."
 No argument or nil as argument means use the current buffer."
   (file-name-nondirectory (buffer-file-name buffer)))
 
-(defun semantic-grammar-package ()
+(defun semantic-grammar-package (&optional fromfile)
   "Return the %package value as a string.
-If there is no %package statement in the grammar, return a default
-package name derived from the grammar file name.  For example, the
-default package name for the grammar file foo.wy is foo-wy, and for
-foo.by it is foo-by."
-  (or (semantic-grammar-first-tag-name 'package)
+If there is no %package statement in the grammar, or if FROMFILE
+is non-nil, return a default package name derived from the
+grammar file name.  For example, the default package name for the
+grammar file foo.wy is foo-wy, and for foo.by it is foo-by."
+  (let ((pkgtoken (semantic-grammar-first-tag-name 'package)))
+    (if (and (not fromfile) pkgtoken)
+	pkgtoken
       (let* ((file (semantic-grammar-buffer-file))
              (ext  (file-name-extension file))
              (i    (string-match (format "\\([.]\\)%s\\'" ext) file)))
-        (concat (substring file 0 i) "-" ext))))
+        (concat (substring file 0 i) "-" ext)))))
 
 (defsubst semantic-grammar-languagemode ()
   "Return the %languagemode value as a list of symbols or nil."
@@ -940,29 +942,32 @@ Lisp code."
                 (make-backup-files t)
                 (vc-make-backup-files t))
             (kill-buffer (current-buffer)))
-        ;; If running interactively, eval declarations and epilogue
-        ;; code, then pop to the buffer visiting the generated file.
-        (eval-region (point) (point-max))
-	;; Loop over the defvars and eval them explicitly to force
-	;; them to be evaluated and ready to use.
-        (goto-char (point-min))
-	(while (re-search-forward "(defvar " nil t)
-	  (eval-defun nil))
-	;; Move cursor to a logical spot in the generated code.
-        (goto-char (point-min))
-        (pop-to-buffer (current-buffer))
-        ;; The generated code has been evaluated and updated into
-        ;; memory.  Now find all buffers that match the major modes we
-        ;; have created this language for, and force them to call our
-        ;; setup function again, refreshing all semantic data, and
-        ;; enabling them to work with the new code just created.
-;;;; FIXME?
-        ;; At this point, I don't know any user's defined setup code :-(
-        ;; At least, what I can do for now, is to run the generated
-        ;; parser-install function.
-        (semantic-map-mode-buffers
-         (semantic-grammar-setupfunction)
-         (semantic-grammar-languagemode)))
+
+	(let ((setupfcn (with-current-buffer semantic--grammar-input-buffer
+			  (intern (semantic-grammar-setupfunction))))
+	      (mode (with-current-buffer semantic--grammar-input-buffer
+		      (semantic-grammar-languagemode))))
+	  ;; If running interactively, eval declarations and epilogue
+	  ;; code, then pop to the buffer visiting the generated file.
+	  (eval-region (point) (point-max))
+	  ;; Move cursor to a logical spot in the generated code.
+	  (goto-char (point-min))
+	  (pop-to-buffer (current-buffer))
+	  ;; The generated code has been evaluated and updated into
+	  ;; memory.  Now find all buffers that match the major modes we
+	  ;; have created this language for, and force them to call our
+	  ;; setup function again, refreshing all semantic data, and
+	  ;; enabling them to work with the new code just created.
+
+	  ;; At this point, I don't know any user's defined setup code :-(
+	  ;; At least, what I can do for now, is to run the generated
+	  ;; parser-install function.
+	  (semantic-map-mode-buffers 
+	   (lambda ()
+	     (semantic-clear-toplevel-cache)
+	     (funcall setupfcn))
+	   mode)
+	  ))
       )
     ;; Return the name of the generated package file.
     output))
@@ -1201,10 +1206,9 @@ END is the limit of the search."
     (define-key km ":" 'semantic-grammar-electric-punctuation)
 
     (define-key km "\t"       'semantic-grammar-indent)
-    (define-key km "\M-\t"    'semantic-grammar-complete)
     (define-key km "\C-c\C-c" 'semantic-grammar-create-package)
-    (define-key km "\C-cm"    'semantic-grammar-find-macro-expander)
-    (define-key km "\C-cik"    'semantic-grammar-insert-keyword)
+    (define-key km "\C-c\C-m"    'semantic-grammar-find-macro-expander)
+    (define-key km "\C-c\C-k"    'semantic-grammar-insert-keyword)
 ;;  (define-key km "\C-cc"    'semantic-grammar-generate-and-load)
 ;;  (define-key km "\C-cr"    'semantic-grammar-generate-one-rule)
 
@@ -1214,7 +1218,7 @@ END is the limit of the search."
 (defvar semantic-grammar-menu
   '("Grammar"
     ["Indent Line" semantic-grammar-indent]
-    ["Complete Symbol" semantic-grammar-complete]
+    ["Complete Symbol" completion-at-point]
     ["Find Macro" semantic-grammar-find-macro-expander]
     "--"
     ["Insert %keyword" semantic-grammar-insert-keyword]
@@ -1322,7 +1326,7 @@ the change bounds to encompass the whole nonterminal tag."
   (semantic-grammar-wy--install-parser)
   (setq semantic-lex-comment-regex ";;"
         semantic-lex-analyzer 'semantic-grammar-lexer
-        semantic-type-relation-separator-character '(":")
+        semantic-type-relation-separator-character '()
         semantic-symbol->name-assoc-list
         '(
           (code         . "Setup Code")
@@ -1490,39 +1494,6 @@ Use the Lisp or grammar indenter depending on point location."
   (save-excursion
     (semantic-grammar-indent)))
 
-(defun semantic-grammar-complete ()
-  "Attempt to complete the symbol under point.
-Completion is position sensitive.  If the cursor is in a match section of
-a rule, then nonterminals symbols are scanned.  If the cursor is in a Lisp
-expression then Lisp symbols are completed."
-  (interactive)
-  (if (semantic-grammar-in-lisp-p)
-      ;; We are in lisp code.  Do lisp completion.
-      (let ((completion-at-point-functions
-             (append '(lisp-completion-at-point)
-                     completion-at-point-functions)))
-        (completion-at-point))
-    ;; We are not in lisp code.  Do rule completion.
-    (let* ((nonterms (semantic-find-tags-by-class 'nonterminal (current-buffer)))
-           (sym (car (semantic-ctxt-current-symbol)))
-           (ans (try-completion sym nonterms)))
-      (cond ((eq ans t)
-             ;; All done
-             (message "Symbols is already complete"))
-            ((and (stringp ans) (string= ans sym))
-             ;; Max matchable.  Show completions.
-	     (with-output-to-temp-buffer "*Completions*"
-	       (display-completion-list (all-completions sym nonterms)))
-	     )
-            ((stringp ans)
-             ;; Expand the completions
-             (forward-sexp -1)
-             (delete-region (point) (progn (forward-sexp 1) (point)))
-             (insert ans))
-            (t (message "No Completions."))
-            ))
-    ))
-
 (defun semantic-grammar-insert-keyword (name)
   "Insert a new %keyword declaration with NAME.
 Assumes it is typed in with the correct casing."
@@ -1546,6 +1517,16 @@ Return the tag found or nil if not found."
                  semanticdb-current-database
                  (cdar (semanticdb-find-tags-by-name name nil t)))))))
 
+(defun semantic--grammar-find-macro-symbol-library (def)
+  "Return the library the macro defined by DEF is in."
+  (let ((lib (symbol-file (cdr def) 'defun)))
+    (if (not (string-match "\\.elc" lib))
+	lib
+      (setq lib2 (replace-match ".el" t t lib 0))
+      (if (file-exists-p lib2)
+	  lib2
+	lib))))
+
 (defsubst semantic--grammar-macro-lib-part (def)
   "Return the library part of the grammar macro defined by DEF."
   (let ((suf (format "-%s\\'" (regexp-quote (symbol-name (car def)))))
@@ -1774,7 +1755,7 @@ Only tags of type 'nonterminal will be so marked."
     (if (semantic-grammar-in-lisp-p)
         (with-mode-local emacs-lisp-mode
           (semantic-ctxt-current-class-list))
-      '(nonterminal keyword))))
+      '(nonterminal token keyword))))
 
 (define-mode-local-override semantic-ctxt-current-mode
   semantic-grammar-mode (&optional point)
@@ -1914,14 +1895,15 @@ Optional argument COLOR determines if color is added to the text."
       context-return)))
 
 (define-mode-local-override semantic-analyze-possible-completions
-  semantic-grammar-mode (context)
-  "Return a list of possible completions based on CONTEXT."
+  semantic-grammar-mode (context &rest flags)
+  "Return a list of possible completions based on CONTEXT.
+Optional FLAGS are ignored."
   (require 'semantic/analyze/complete)
   (if (semantic-grammar-in-lisp-p)
       (with-mode-local emacs-lisp-mode
 	(semantic-analyze-possible-completions context))
     (with-current-buffer (oref context buffer)
-      (let* ((prefix (car (oref context :prefix)))
+      (let* ((prefix (car (reverse (oref context :prefix))))
 	     (completetext (cond ((semantic-tag-p prefix)
 				  (semantic-tag-name prefix))
 				 ((stringp prefix)
diff --git a/lisp/cedet/semantic/ia.el b/lisp/cedet/semantic/ia.el
index 214fbb5..81fb0b4 100644
--- a/lisp/cedet/semantic/ia.el
+++ b/lisp/cedet/semantic/ia.el
@@ -123,7 +123,7 @@ Completion options are calculated with `semantic-analyze-possible-completions'."
 	      ;; the smart completion engine sometimes fails.
 	      (semantic-complete-symbol))
 	;; Use try completion to seek a common substring.
-	(let* ((completion-ignore-case (string= (downcase pre) pre))
+	(let* ((completion-ignore-case (and pre (string= (downcase pre) pre)))
 	       (tc (try-completion (or pre "")  syms)))
 	  (if (and (stringp tc) (not (string= tc (or pre ""))))
 	      (let ((tok (semantic-find-first-tag-by-name
@@ -188,7 +188,11 @@ Completion options are calculated with `semantic-analyze-possible-completions'."
 	(when ans
 	  (if (not (semantic-tag-p ans))
 	      (setq ans (aref (cdr ans) 0)))
-	  (delete-region (car (oref a bounds)) (cdr (oref a bounds)))
+	  (with-slots ((bnds bounds)) a
+            ;; bounds could be nil if we are completing an empty prefix string
+            ;; (e.g. type constrained within a function argument list)
+            (when (and (car bnds) (cdr bnds))
+              (delete-region (car bnds) (cdr bnds))))
 	  (semantic-ia-insert-tag ans))
 	))))
 
diff --git a/lisp/cedet/semantic/idle.el b/lisp/cedet/semantic/idle.el
index 549a30a..18e7aa0 100644
--- a/lisp/cedet/semantic/idle.el
+++ b/lisp/cedet/semantic/idle.el
@@ -837,8 +837,11 @@ turned on in every Semantic-supported buffer."
   :group 'semantic-faces)
 (defvar semantic-idle-symbol-highlight-face 'semantic-idle-symbol-highlight
   "Face used for highlighting local symbols.")
-(make-obsolete-variable 'semantic-idle-symbol-highlight-face
-    "customize the face `semantic-idle-symbol-highlight' instead" "24.4" 'set)
+(if (version< emacs-version "24.2")
+    (make-obsolete-variable 'semantic-idle-symbol-highlight-face
+			    "customize the face `semantic-idle-symbol-highlight' instead" "24.4")
+  (make-obsolete-variable 'semantic-idle-symbol-highlight-face
+			  "customize the face `semantic-idle-symbol-highlight' instead" "24.4" 'set))
 
 (defun semantic-idle-symbol-maybe-highlight (tag)
   "Perhaps add highlighting to the symbol represented by TAG.
diff --git a/lisp/cedet/semantic/scope.el b/lisp/cedet/semantic/scope.el
index ddef510..e1938e5 100644
--- a/lisp/cedet/semantic/scope.el
+++ b/lisp/cedet/semantic/scope.el
@@ -415,7 +415,8 @@ implicit \"object\"."
     ;; the names in typelist.
     (while typelist
       (let ((tt (semantic-tag-type (car typelist))))
-	(when (and (stringp tt) (string= tt "namespace"))
+	(when (and (stringp tt) (or (string= tt "namespace")
+				    (string= tt "enum")) )
 	  ;; By using the typecache, our namespaces are pre-merged.
 	  (setq typelist2 (cons (car typelist) typelist2))
 	  ))
@@ -508,7 +509,9 @@ the access would be 'protected.  Otherwise, access is 'public")
   "Return a list of slots that are valid completions from the list of SLOTS.
 If a tag in SLOTS has a named parent, then that implies that the
 tag is not something you can complete from within TYPE."
-  (let ((allslots (semantic-tag-components type))
+  ;; Pull in analyzed type members.
+  ;; For C, this strips out anon unions, and merges in anon union members.
+  (let ((allslots (semantic-analyze-tag-type-members type))
 	(leftover nil)
 	)
     (dolist (S allslots)
@@ -767,6 +770,17 @@ The class returned from the scope calculation is variable
 	;; can reset the scope cache without affecting others.
 	(clone scopecache)))))
 
+(defun semantic-calculate-scope-for-tag (tag)
+  "Calculate the current scope that is around TAG.
+Return nil if TAG has no position, or we cannot otherwise find a scope.
+Use this when pulling a datatype off TAG so when it is looked up
+it has the right context around it."
+  (save-excursion
+    (save-current-buffer
+      (when (semantic-tag-with-position-p tag)
+	(semantic-go-to-tag tag)
+	(semantic-calculate-scope (point)))) ))
+
 (defun semantic-scope-find (name &optional class scope-in)
   "Find the tag with NAME, and optional CLASS in the current SCOPE-IN.
 Searches various elements of the scope for NAME.  Return ALL the
@@ -809,7 +823,7 @@ hits in order, with the first tag being in the closest scope."
 		  (if (not ans)
 		      (setq typescoperaw nil)
 		    (when (cdr namesplit)
-		      (setq typescoperaw (semantic-tag-type-members
+		      (setq typescoperaw (semantic-analyze-tag-type-members
 					  (car ans)))))
 
 		  (setq namesplit (cdr namesplit)))
diff --git a/lisp/cedet/semantic/symref.el b/lisp/cedet/semantic/symref.el
index 516a4f3..cca3912 100644
--- a/lisp/cedet/semantic/symref.el
+++ b/lisp/cedet/semantic/symref.el
@@ -65,6 +65,7 @@
 ;; Your tool should then create an instance of `semantic-symref-result'.
 
 (require 'semantic)
+(require 'semantic/find)
 
 (defvar ede-minor-mode)
 (declare-function data-debug-new-buffer "data-debug")
diff --git a/lisp/cedet/semantic/texi.el b/lisp/cedet/semantic/texi.el
index cbb7705..9d7f73a 100644
--- a/lisp/cedet/semantic/texi.el
+++ b/lisp/cedet/semantic/texi.el
@@ -412,12 +412,13 @@ Optional argument POINT is where to look for the environment."
   "List of commands that we might bother completing.")
 
 (define-mode-local-override semantic-analyze-possible-completions
-  texinfo-mode (context)
+  texinfo-mode (context &rest flags)
   "List smart completions at point.
 Since texinfo is not a programming language the default version is not
 useful.  Instead, look at the current symbol.  If it is a command
 do primitive texinfo built ins.  If not, use ispell to lookup words
-that start with that symbol."
+that start with that symbol.
+Any extra FLAGS are currently ignored."
   (let ((prefix (car (oref context :prefix)))
 	)
     (cond ((member 'function (oref context :prefixclass))
diff --git a/lisp/cedet/semantic/wisent/python.el b/lisp/cedet/semantic/wisent/python.el
index 939086b..2402442 100644
--- a/lisp/cedet/semantic/wisent/python.el
+++ b/lisp/cedet/semantic/wisent/python.el
@@ -511,6 +511,10 @@ Shortens `code' tags, but passes through for others."
   ;; Give python modes the possibility to overwrite this:
   (if (not comment-start-skip)
       (set (make-local-variable 'comment-start-skip) "#+\\s-*"))
+  ;; Fix up some syntax for the lexer.
+  (setq semantic-lex-syntax-modifications '((?. ".")
+                                            )
+        )
   (setq
   ;; Character used to separation a parent/child relationship
    semantic-type-relation-separator-character '(".")
diff --git a/lisp/cedet/semantic/wisent/wisent.el b/lisp/cedet/semantic/wisent/wisent.el
index 9eab860..cddeb21 100644
--- a/lisp/cedet/semantic/wisent/wisent.el
+++ b/lisp/cedet/semantic/wisent/wisent.el
@@ -376,7 +376,7 @@ automaton has only one entry point."
          (wisent-parse-lexer-function lexer)
          (wisent-recovering nil)
          (wisent-input (wisent-parse-start start starts))
-         state tokid choices choice)
+         state tokid choices choice wisent-lookahead-save)
     (setq wisent-nerrs     0 ;; Reset parse error counter
           wisent-lookahead nil) ;; and lookahead token
     (aset stack 0 0) ;; Initial state
@@ -468,7 +468,12 @@ automaton has only one entry point."
        ;; Reduce by rule (call semantic action)
        ;; -------------------------------------
        (t
+        ;; save the global variable wisent-lookahead,
+        ;; as the semantic action might be an expand or expandfull
+        ;; which calls this function recursively
+        (setq wisent-lookahead-save wisent-lookahead)
         (setq sp (funcall wisent-loop stack sp gotos))
+        (setq wisent-lookahead wisent-lookahead-save)
         (or wisent-input (setq wisent-input (wisent-lexer))))))
     (run-hooks 'wisent-post-parse-hook)
     (car (aref stack 1))))
diff --git a/lisp/cedet/srecode/srt-mode.el b/lisp/cedet/srecode/srt-mode.el
index be252c2..504e261 100644
--- a/lisp/cedet/srecode/srt-mode.el
+++ b/lisp/cedet/srecode/srt-mode.el
@@ -625,8 +625,9 @@ section or ? for an ask variable."
 	context-return)))
 
 (define-mode-local-override semantic-analyze-possible-completions
-  srecode-template-mode (context)
-  "Return a list of possible completions based on NONTEXT."
+  srecode-template-mode (context &rest flags)
+  "Return a list of possible completions based on NONTEXT.
+Any extra FLAGS are ignored."
   (with-current-buffer (oref context buffer)
     (let* ((prefix (car (last (oref context :prefix))))
 	   (prefixstr (cond ((stringp prefix)