GNU bug report logs - #5457
[PATCH] [RFC] C++1x support for cc-mode

Previous Next

Packages: emacs, cc-mode;

Reported by: Daniel Colascione <daniel <at> censorshipresearch.org>

Date: Sat, 23 Jan 2010 00:56:02 UTC

Severity: wishlist

Tags: patch

Done: Lars Ingebrigtsen <larsi <at> gnus.org>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 5457 in the body.
You can then email your comments to 5457 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Message #1 received at quiet <at> debbugs.gnu.org (full text, mbox):

From: Daniel Colascione <daniel <at> censorshipresearch.org>
To: quiet <at> debbugs.gnu.org
Subject: [PATCH] [RFC] C++1x support for cc-mode
Date: Fri, 15 Jan 2010 11:24:54 -0500
Severity: wishlist
Package: emacs,cc-mode
Tags: patch

[ resent from
  http://lists.gnu.org/archive/html/emacs-devel/2010-01/msg00868.html ]

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Here is a *very* rough patch that halfway implements most of the new
language constructs. I've also included a small test file, though
I'm sure there are some cases, especially around vararg-template and
attribute syntax, that don't work yet.

The test file is marked with 'XXX' to indicate things that don't yet work.

A few questions:

- - How can I get this to be recognized as a function definition?

    foo() -> int { return 42; }

- - How can I fontify static_assert only when there are parens?

    GOOD: static_assert(true)
     BAD: static_assert true

  (In this respect, static_assert is unlike sizeof.)

- - Angle bracket rule has changed. What's the best way to effect that?

- - Raw strings ?! The best thing I can think of is an entirely separate
fontification pass for them.

- - operator "" (yes, really). I'm having a hard time figuring
  out where I need to special-case it though. It looks like this:

  some_type operator"" special_suffix()

diff --unidirectional-new-file -wur
/Users/danielcolascione/software/emacs/lisp/progmodes/c++0x-test.cpp
./c++0x-test.cpp
- ---
/Users/danielcolascione/software/emacs/lisp/progmodes/c++0x-test.cpp
1969-12-31 19:00:00.000000000 -0500
+++ ./c++0x-test.cpp	2010-01-15 11:20:26.000000000 -0500
@@ -0,0 +1,436 @@
+/* Examples (mostly) from Wikipedia */
+
+int GetFive() {return 5;}
+
+int some_value[GetFive() + 7]; //create an array of 12 integers.
illegal C++
+
+constexpr int GetFive() {return 5;}
+
+int some_value[GetFive() + 7]; //create an array of 12 integers. legal
C++0x
+
+constexpr double accelerationOfGravity = 9.8;
+constexpr double moonGravity = accelerationOfGravity / 6;
+
+template class std::vector<MyClass>;
+
+extern template class std::vector<MyClass>;
+
+class SequenceClass
+{
+public:
+  SequenceClass(std::initializer_list<int> list);
+};
+
+SequenceClass someVar = {1, 4, 5, 6};
+
+void FunctionName(std::initializer_list<float> list);
+
+FunctionName({1.0f, -3.45f, -0.4f});
+
+std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
+std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" };
+
+struct BasicStruct
+{
+ int x;
+ double y;
+};
+
+struct AltStruct
+{
+  AltStruct(int x, double y) : x_{x}, y_{y} {}
+
+private:
+  int x_;
+  double y_;
+};
+
+BasicStruct var1(5,
+                 3.2);
+
+BasicStruct var1{5,
+        // XXX: should be arglist-cont-nonempty because this is
+        // actually a function call
+        3.2};
+AltStruct var2{2, 4.3};
+
+struct IdString
+{
+  std::string name;
+  int identifier;
+};
+
+IdString GetString()
+{
+  return {"SomeName", 4}; //Note the lack of explicit type.
+}
+
+std::vector<int> theVec{4};
+
+auto someStrangeCallableType = boost::bind(&SomeFunction, _2, _1,
someObject);
+auto otherVariable = 5;
+
+int someInt;
+
+// XXX: otherIntegerVariable should be fontified as a variable
+decltype(someInt) otherIntegerVariable = 5;
+
+// longstanding GNU extension
+typeof(blah(sda[a])) f = 5;
+
+for (vector<int>::const_iterator itr = myvec.begin(); itr !=
myvec.end(); ++itr)
+{}
+
+for (auto itr = myvec.begin(); itr != myvec.end(); ++itr)
+{}
+
+#include <vector>
+int main()
+{
+  const std::vector<int> v(1);
+  auto a = v[0];        // a has type int
+  decltype(v[0]) b = 1; // b has type const int&, the return type of
+                        // std::vector<int>::operator[](size_type) const
+  auto c = 0;           // c has type int
+  auto d = c;           // d has type int
+  decltype(c) e;        // e has type int, the type of the entity named
by c
+  decltype((c)) f = c;  // f has type int&, because (c) is an lvalue
+  decltype(0) g;        // g has type int, because 0 is an rvalue
+  //           ^ - XXX fontify as variable
+}
+
+int&& x = 5;
+
+int my_array[5] = {1, 2, 3, 4, 5};
+for(int &x : my_array)
+{
+  x *= 2;
+}
+
+void lambra_functions_here() {
+    [](int x, int y) { return x + y; }
+
+    [](int x, int y) -> int {
+        int z = x + y;
+        return z + x;
+    }
+
+    std::vector<int> someList;
+    int total = 0;
+    //      XXX XXX       Fontify as function param ----+
+    //                                                  |
+    //                                                  V
+    std::for_each(someList.begin(), someList.end(), [&total](int x) {
+            total += x;
+        });
+    std::cout << total;
+
+    std::vector<int> someList;
+    int total = 0;
+    std::for_each(someList.begin(), someList.end(), [&](int x) {
+            total += x;
+        });
+
+    int total = 0;
+    int value = 5;
+    [&, value](int x) { total += (x * value); };
+
+    //       XXX --+-- fontify as function parameter
+    //             |
+    //             V
+    [](SomeType *typePtr) { typePtr->SomePrivateMemberFunction(); }
+
+    auto myLambdaFunc = [this]() { this->SomePrivateMemberFunction(); };
+}
+
+/* Alternative function syntax */
+
+template< typename LHS, typename RHS>
+Ret AddingFunc(const LHS &lhs, const RHS &rhs) {return lhs + rhs;}
+//Ret must be the type of lhs+rhs
+
+template< typename LHS, typename RHS>
+auto AddingFunc(const LHS &lhs, const RHS &rhs) ->
+    decltype(lhs+rhs) {return lhs + rhs;}
+
+auto foo() -> int { return 42; }
+
+auto SomeType() -> blarg() {}
+
+class SomeType
+{
+    int number;
+
+    public:
+    SomeType(int newNumber) : number(newNumber) {}
+    SomeType() : SomeType(42) {}
+};
+
+class BaseClass
+{
+    public:
+    BaseClass(int iValue);
+};
+
+class DerivedClass : public BaseClass
+{
+    public:
+    using BaseClass::BaseClass;
+};
+
+class SomeClass
+{
+public:
+  SomeClass() {}
+  explicit SomeClass(int iNewValue) : iValue(iNewValue) {}
+
+private:
+  int iValue = 5;
+};
+
+
+
+struct Test {};
+
+class B : public Test
+{
+  typedef B self;
+  virtual void some_func1();
+  virtual void some_func2(float);
+  virtual void some_func3() const;
+  virtual long some_func4(int);
+  virtual void f();
+  virtual void h(int);
+  void j(int);
+  void k(int);
+};
+
+// XXX: Why isn't B fontified? We're skipping the attribute.
+//                              |
+//                              V
+class D [[base_check]] : public B
+{
+  using B::j;
+  void sone_func1 [[override]] ();  // ill-formed: mis-spelled name
+  void some_func2 [[override]] (double); // ill-formed: bad argument type
+  void some_func3 [[override]] (); // ill-formed: missing cv-qualification
+  int some_func4 [[override]] (int); // ill-formed: return type does
not match B::some_func4
+  virtual void f [[override]] (); // OK: overrides B::f
+  virtual void g(long);      // new virtual function introduced
+  void h(int);               // ill-formed: overriding without [[override]]
+  virtual void h(double);    // ill-formed: new virtual function hides
void h(int)
+  virtual void h [[hiding]] (char *);  // OK, new virtual function
hides base
+  virtual   int j( double );           // OK, using declaration
prevents hiding
+  int k( double );           // ill-formed: name hiding and no using
declaration
+  double k [[hiding]] ( char * ); // OK, hiding is clearly indicated
+  double m [[hiding]] ( char * ); // ill-formed, hiding is requested,
but not present
+  typedef D self; // ill-formed, new type definition hides the
definition in B
+};
+
+[[ vendor()::crap[] ]] int x;
+
+char* pc = nullptr;     // OK
+int * pi = nullptr;     // OK
+bool   b = nullptr;     // OK. b is false.
+int    i = nullptr;     // error
+
+foo(nullptr);           // calls foo(char *), not foo(int);
+
+enum class Enumeration
+{
+  Val1,
+  Val2,
+  Val3 = 100,
+  Val4 /* = 101 */
+};
+
+enum class Enum2 : unsigned int {Val1, Val2};
+
+enum Enum3 : unsigned long {Val1 = 1, Val2};
+
+enum Enum2 : unsigned int;    //Legal in C++0x.
+enum class Enum3;             //Legal in C++0x, because enum class
+                              //declarations have a default type of
+                              //"int".
+enum class Enum4: unsigned int; //Legal C++0x.
+
+/*
+ * XXX: doesn't work. Commented out to avoid breakage
+ *
+template<bool bTest> class SomeType;
+std::vector<SomeType<1>2>> x1 ;  // Interpreted as a std::vector of
SomeType<true> 2>,
+// which is not legal syntax. 1 is true.
+std::vector<SomeType<(1>2)>> x1 ;  // Interpreted as std::vector of
SomeType<false>,
+//which is legal C++0x syntax. (1>2) is false.
+*/
+
+
+template< typename first, typename second, int third>
+class SomeType;
+
+template< typename second>
+using TypedefName = SomeType<OtherType, second, 5>;
+
+typedef void (*PFD)(double);		// Old style
+using PF = void (*)(double);		// New introduced syntax
+
+struct point
+{
+  point() {}
+  point(int x, int y): x_(x), y_(y) {}
+  int x_, y_;
+};
+union
+{
+  int z;
+  double w;
+  point p;  // Illegal in C++; point has a non-trivial constructor.
+            // However, this is legal in C++0x.
+};
+
+
+template<typename... Values> class tuple;
+
+class tuple<int, std::vector<int>, std::map<std::string,
std::vector<int>> >
+    someInstanceName;
+
+template<typename First, typename... Rest> class tuple;
+
+template<typename... Params> void printf(const std::string &strFormat,
+                                         Params... parameters);
+
+
+void printf(const char *s)
+{
+  while (*s)
+  {
+    if (*s == '%' && *(++s) != '%')
+      throw std::runtime_error("invalid format string: missing arguments");
+    std::cout << *s++;
+  }
+}
+
+template<typename T, typename... Args>
+void printf(const char* s, T value, Args&&... args)
+{
+  while (*s)
+  {
+    if (*s == '%' && *(++s) != '%')
+    {
+      std::cout << value;
+      printf(s, args...); // call even when *s == 0 to detect extra
arguments
+      return;
+    }
+    std::cout << *s++;
+  }
+  throw std::logic_error("extra arguments provided to printf");
+}
+
+template <typename... BaseClasses>
+class ClassName : public BaseClasses...
+{
+    public:
+    ClassName (BaseClasses&& ... baseClasses)
+        : BaseClasses(baseClasses)... {}
+
+};
+
+
+template<typename ...TypeToConstruct>
+struct SharedPtrAllocator
+{
+    template<typename... Args> std::shared_ptr<TypeToConstruct>
+    ConstructWithSharedPtr(Args&& ...params)
+    {
+        return std::shared_ptr<TypeToConstruct>(
+            new TypeToConstruct(std::forward<Args>(params)..., int test));
+    }
+};
+
+
+template<typename ...Args> struct SomeStruct
+{
+  static const int size = sizeof...(Args);
+}
+
+u8"I'm a UTF-8 string."
+u"This is a UTF-16 string."
+U"This is a UTF-32 string."
+
+u8"This is a Unicode Character: \u2018."
+u"This is a bigger Unicode Character: \u2018."
+U"This is a Unicode Character: \u2018."
+
+/* XXX hopelessly broken */
+
+/*
+R"[The String Data \ Stuff " ]"
+R"delimiter[The String Data \ Stuff " ]delimiter"
+
+u8R"XXX[I'm a "raw UTF-8" string.]XXX"
+uR"*@[This is a "raw UTF-16" string.]*@"
+UR"[This is a "raw UTF-32" string.]"
+*/
+
+//* XXX: probably needs special treatment to override default string
+//* syntax
+//                  |
+//                  V
+OutputType operator "" _Suffix(const char *literal_string);
+
+OutputType someVariable = "1234"_Suffix;
+
+template<char...> OutputType operator "" _Suffix();
+
+OutputType someVariable = "1234"_Suffix;
+
+OutputType operator "" _Suffix(unsigned long long);
+OutputType operator "" _Suffix(long double);
+
+OutputType someVariable    = 1234_Suffix;   // uses the first function
+OutputType anotherVariable = 3.1416_Suffix; // uses the second function
+
+
+OutputType operator "" _Suffix(unsigned long long);
+OutputType operator "" _Suffix(long double);
+
+OutputType someVariable    = 1234_Suffix;   // uses the first function
+OutputType anotherVariable = 3.1416_Suffix; // uses the second function
+
+struct SomeType
+{
+  SomeType() = default; //The default constructor is explicitly stated.
+  SomeType(OtherType value);
+};
+
+struct NonCopyable
+{
+  NonCopyable & operator=(const NonCopyable&) = delete;
+  NonCopyable(const NonCopyable&) = delete;
+  NonCopyable() = default;
+};
+
+struct NonNewable
+{
+  void *operator new(std::size_t) = delete;
+};
+
+struct NoDouble
+{
+  void f(int i);
+  void f(double) = delete;
+};
+
+struct OnlyInt
+{
+  void f(int i);
+  template<class T> void f(T) = delete;
+};
+
+
+struct SomeType { OtherType member; };
+
+sizeof(SomeType::member); //Does not work with C++03. Okay with C++0x
+
+/* End test file */
+
diff --unidirectional-new-file -wur
/Users/danielcolascione/software/emacs/lisp/progmodes/c++0x-test2.cpp
./c++0x-test2.cpp
- ---
/Users/danielcolascione/software/emacs/lisp/progmodes/c++0x-test2.cpp
1969-12-31 19:00:00.000000000 -0500
+++ ./c++0x-test2.cpp	2010-01-15 11:01:17.000000000 -0500
@@ -0,0 +1,3 @@
+void printf(const char* s, int& *p, int x,
+            Args&& ...args, int ss);
+
diff --unidirectional-new-file -wur
/Users/danielcolascione/software/emacs/lisp/progmodes/cc-engine.el
./cc-engine.el
- --- /Users/danielcolascione/software/emacs/lisp/progmodes/cc-engine.el
2010-01-14 18:06:46.000000000 -0500
+++ ./cc-engine.el	2010-01-15 11:05:50.000000000 -0500
@@ -4664,6 +4664,7 @@
 	  (when (and cfd-match-pos (< cfd-match-pos syntactic-pos))
 	    (goto-char syntactic-pos)
 	    (c-forward-syntactic-ws)
+            (c-skip-c++-attributes)
 	    (and cfd-continue-pos
 		 (< cfd-continue-pos (point))
 		 (setq cfd-token-pos (point))))
@@ -5238,8 +5239,8 @@
       (forward-char)
       (unless (looking-at c-<-op-cont-regexp)
 	(while (and
- -		(progn

+		(progn
 		  (when c-record-type-identifiers
 		    (if all-types

@@ -5454,6 +5455,42 @@

       (/= (point) start))))

+(defun c-skip-variadic-dots ()
+  ;; Move forward over a C++ three-dot form if point is at one.
+  ;;
+  ;; Return true off we found and skipped a variadic template dots.
+  (when (and (c-lang-const c-dots-everywhere)
+             (looking-at "\\.\\.\\."))
+    (goto-char (match-end 0))
+    (c-forward-syntactic-ws)
+    t))
+
+(defun c-skip-c++-attributes ()
+  ;; Skip one N2761 C++1x attribute declaration if point is at one,
+  ;; returning true iff we actually found and skipped one.
+  (and (c-major-mode-is 'c++-mode)
+       (eq (char-after) ?\[)
+       (save-excursion
+         (forward-char)
+         (c-forward-syntactic-ws)
+         (eq (char-after) ?\[))
+       (or (ignore-errors
+             (c-forward-sexp)
+             (c-forward-syntactic-ws))
+           ;; DTRT on failure?
+           (end-of-line))))
+
+(defun c-skip-c++-crud ()
+  ;; Skip declarational C++ crud that doesn't matter for
+  ;; our parsing.
+  ;;
+  ;; XXX sometimes we shouldn't accept ... before a type intro, but
+  ;; that requires detecting whether we're in a header.
+  ;;
+  (while (or (c-skip-c++-attributes)
+             (c-skip-variadic-dots))))
+
+
 (defun c-forward-name ()
   ;; Move forward over a complete name if at the beginning of one,
   ;; stopping at the next following token.  If the point is not at
@@ -5482,6 +5519,9 @@
 	;; the caller only wants the top level type that it finds to
 	;; be promoted.
 	c-promote-possible-types)
+
+    (c-skip-c++-crud)
+
     (while
 	(and
 	 (looking-at c-identifier-key)
@@ -5528,7 +5568,7 @@
 			  ;; '*', '&' or a name followed by ":: *",
 			  ;; where each can be followed by a sequence
 			  ;; of `c-opt-type-modifier-key'.
- -			  (while (cond ((looking-at "[*&]")
+			  (while (cond ((looking-at "[*&]\\|&&")
 					(goto-char (match-end 0))
 					t)
 				       ((looking-at c-identifier-start)
@@ -5617,6 +5657,9 @@
 	      )))))

     (goto-char pos)
+
+    (c-skip-c++-crud)
+
     res))

 (defun c-forward-type ()
@@ -5642,6 +5685,8 @@

   (let ((start (point)) pos res name-res id-start id-end id-range)

+    (c-skip-c++-attributes)
+
     ;; Skip leading type modifiers.  If any are found we know it's a
     ;; prefix of a type.
     (when c-opt-type-modifier-key
@@ -5656,6 +5701,8 @@
       ;; e.g. "class".
       (goto-char (match-end 1))
       (c-forward-syntactic-ws)
+      (c-skip-c++-crud)
+
       (setq pos (point))
       (if (memq (setq name-res (c-forward-name)) '(t template))
 	  (progn
@@ -5671,6 +5718,23 @@
 	(goto-char start)
 	(setq res nil)))

+     ((and (c-major-mode-is 'c++-mode)
+           (looking-at "\\(typeof\\|decltype\\)\\_>"))
+      (goto-char (match-end 0))
+      (c-forward-syntactic-ws)
+      (c-skip-c++-crud)
+      (if (not (eq (char-after) ?\())
+          ;; Invalid syntax
+          (progn
+            (goto-char start)
+            (setq res nil))
+
+        ;; We found a type, but there's nothing to record
+        (c-forward-sexp)
+        (c-forward-syntactic-ws)
+        (c-skip-c++-crud)
+        (setq res t)))
+
      ((progn
 	(setq pos nil)
 	(if (looking-at c-identifier-start)
@@ -5830,6 +5894,8 @@

 	    (goto-char pos))))

+      (c-skip-c++-crud)
+
       (when (and c-record-found-types (memq res '(known found)) id-range)
 	(setq c-record-found-types
 	      (cons id-range c-record-found-types))))
@@ -6219,7 +6285,8 @@
 	    (setq got-prefix-before-parens (= paren-depth 0)))
 	  (setq got-prefix t)
 	  (goto-char (match-end 1)))
- -	(c-forward-syntactic-ws))
+	(c-forward-syntactic-ws)
+        (c-skip-c++-crud))

       (setq got-parens (> paren-depth 0))

@@ -7027,6 +7094,7 @@
   (c-with-syntax-table c++-template-syntax-table
     (c-backward-token-2 0 t lim)
     (while (and (or (looking-at c-symbol-start)
+                    (looking-at "\\.\\.\\.")
 		    (looking-at "[<,]\\|::"))
 		(zerop (c-backward-token-2 1 t lim))))))

diff --unidirectional-new-file -wur
/Users/danielcolascione/software/emacs/lisp/progmodes/cc-fonts.el
./cc-fonts.el
- --- /Users/danielcolascione/software/emacs/lisp/progmodes/cc-fonts.el
2009-12-04 00:44:40.000000000 -0500
+++ ./cc-fonts.el	2010-01-15 11:06:26.000000000 -0500
@@ -876,7 +876,8 @@
 		      (setq paren-depth (1+ paren-depth))
 		      (forward-char))
 		  (goto-char (match-end 1)))
- -		(c-forward-syntactic-ws))
+		(c-forward-syntactic-ws)
+                (c-skip-c++-crud))

 	      ;; If we didn't pass the identifier above already, do it now.
 	      (unless got-identifier
@@ -893,8 +894,11 @@
 	    (<= (point) limit)

 	    (progn
+              (c-skip-c++-crud)
+	
 	      (when (looking-at c-decl-hangon-key)
 		(c-forward-keyword-clause 1))
+              (c-skip-c++-crud)
 	      (<= (point) limit))

 	    ;; Search syntactically to the end of the declarator (";",
@@ -1217,6 +1221,21 @@

       nil)))

+(defun c-font-lock-c++-attributes (limit)
+  ;; fontify new C++ attributes syntax. Need a function instead of a
+  ;; declaration because the things can have arbitrarily nested
+  ;; parenthesis
+  (while (and
+          (c-syntactic-re-search-forward "\\[\\s-*\\[" limit t nil t)
+          (ignore-errors
+            (goto-char (match-beginning 0))
+            (setq beg (point))
+            (c-forward-sexp)
+            (c-put-font-lock-face (match-beginning 0) (point)
+                                  'font-lock-keyword-face)
+            t)))
+  nil)
+
 (c-lang-defconst c-simple-decl-matchers
   "Simple font lock matchers for types and declarations.  These are used
 on level 2 only and so aren't combined with `c-complex-decl-matchers'."
@@ -1320,6 +1339,9 @@
 				       'c-type 'c-decl-end)))
 	      c-font-lock-objc-methods))

+      ,(if (c-major-mode-is 'c++-mode)
+           'c-font-lock-c++-attributes)
+
       ;; Fontify all declarations, casts and normal labels.
       c-font-lock-declarations

diff --unidirectional-new-file -wur
/Users/danielcolascione/software/emacs/lisp/progmodes/cc-langs.el
./cc-langs.el
- --- /Users/danielcolascione/software/emacs/lisp/progmodes/cc-langs.el
2009-12-04 00:44:40.000000000 -0500
+++ ./cc-langs.el	2010-01-15 11:08:57.000000000 -0500
@@ -849,7 +849,8 @@

       ;; Unary.
       (prefix "++" "--" "+" "-" "!" "~"
- -	      ,@(when (c-major-mode-is 'c++-mode) '("not" "compl"))
+	      ,@(when (c-major-mode-is 'c++-mode)
+                  '("not" "compl" "static_assert" "&&"))
 	      ,@(when (c-major-mode-is '(c-mode c++-mode))
 		  '("*" "&" "sizeof" "??-"))
 	      ,@(when (c-major-mode-is 'objc-mode)
@@ -1009,7 +1010,7 @@
 			 "::" "...")
 		       (c-lang-const c-other-op-syntax-tokens))
   (c c++) (append '("*") (c-lang-const c-other-op-syntax-tokens))
- -  c++  (append '("&" "<%" "%>" "<:" ":>" "%:" "%:%:")
+  c++  (append '("&" "&&"  "<%" "%>" "<:" ":>" "%:" "%:%:")
 	       (c-lang-const c-other-op-syntax-tokens))
   objc (append '("#" "##"		; Used by cpp.
 		 "+" "-") (c-lang-const c-other-op-syntax-tokens))
@@ -1492,7 +1493,7 @@
 	'("_Bool" "_Complex" "_Imaginary") ; Conditionally defined in C99.
 	(c-lang-const c-primitive-type-kwds))
   c++  (append
- -	'("bool" "wchar_t")
+	'("auto" "bool" "wchar_t")
 	(c-lang-const c-primitive-type-kwds))
   ;; Objective-C extends C, but probably not the new stuff in C99.
   objc (append
@@ -1551,7 +1552,7 @@
 not the type face."
   t    nil
   c    '("const" "restrict" "volatile")
- -  c++  '("const" "volatile" "throw")
+  c++  '("const" "volatile" "throw" "constexpr" )
   objc '("const" "volatile"))

 (c-lang-defconst c-opt-type-modifier-key
@@ -1727,9 +1728,10 @@
 `c-<>-type-kwds', or `c-<>-arglist-kwds' then the associated clauses
 will be handled."
   t    nil
- -  (c c++) '("auto" "extern" "inline" "register" "static")
- -  c++  (append '("explicit" "friend" "mutable" "template" "using"
"virtual")
- -	       (c-lang-const c-modifier-kwds))
+  c    '("extern" "inline" "register" "static" "auto")
+  c++  '("extern" "inline" "register" "static"
+         "explicit" "friend" "mutable" "template"
+         "using" "virtual")
   objc '("auto" "bycopy" "byref" "extern" "in" "inout" "oneway" "out"
"static")
   ;; FIXME: Some of those below ought to be on `c-other-decl-kwds' instead.
   idl  '("abstract" "attribute" "const" "consumes" "custom" "emits"
"import"
@@ -1800,7 +1802,9 @@
   (c c++) '(;; GCC extension.
 	    "__attribute__"
 	    ;; MSVC extension.
- -	    "__declspec"))
+            "__declspec"
+            ;; Standard C++ attributes handled elsewhere
+            ))

 (c-lang-defconst c-decl-hangon-key
   ;; Adorned regexp matching `c-decl-hangon-kwds'.
@@ -1970,8 +1974,11 @@
   "Keywords that may be followed by a parenthesis expression that doesn't
 contain type identifiers."
   t       nil
- -  (c c++) '(;; GCC extension.
+  (c c++) '(;; C++0x
+            "decltype"
+            ;; GCC extension.
 	    "__attribute__"
+            "typeof"
 	    ;; MSVC extension.
 	    "__declspec"))

@@ -2148,6 +2155,7 @@
   "Keywords for constants."
   t       nil
   (c c++) '("NULL" ;; Not a keyword, but practically works as one.
+            "nullptr"
 	    "false" "true")		; Defined in C99.
   objc    '("nil" "Nil" "YES" "NO" "NS_DURING" "NS_HANDLER"
"NS_ENDHANDLER")
   idl     '("TRUE" "FALSE")
@@ -2588,7 +2596,13 @@

   ;; Allow '"' for extern clauses (e.g. extern "C" {...}).
   (c c++ objc) (set-difference (c-lang-const
c-block-prefix-disallowed-chars)
- -			       '(?\" ?')))
+			       '(?\" ?'))
+
+  ;; Allow '.' for variadic templates and '[' and ']' for the new fun
+  ;; attribute syntax.
+  (c++) (set-difference (c-lang-const c-block-prefix-disallowed-chars)
+			       '(?. ?\[ ?\])))
+

 (c-lang-defconst c-block-prefix-charset
   ;; `c-block-prefix-disallowed-chars' as an inverted charset suitable
@@ -2616,6 +2630,8 @@
 		   "\\)"
 		   "\\([^=]\\|$\\)")
   c++  (concat "\\("
+               "&&"
+               "\\|"
 	       "[*\(&]"
 	       "\\|"
 	       (concat "\\("	; 2
@@ -2954,6 +2970,12 @@
   objc t)
 (c-lang-defvar c-type-decl-end-used (c-lang-const c-type-decl-end-used))

+(c-lang-defconst c-dots-everywhere
+  ;; t if '...' should be allowed in most declarations and expressions.
+  ;; Used for C++ variadic templates.
+  t nil
+  c++ t)
+
 
 ;;; Wrap up the `c-lang-defvar' system.


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (Darwin)

iEYEARECAAYFAktQltYACgkQ17c2LVA10VvIyQCgx3niOg2lThacbnmC4vqtOGsl
Z90An15sJlaGeWf3L6Q2QxN5bszBksLx
=NNpm
-----END PGP SIGNATURE-----




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#5457; Package emacs,cc-mode. (Sun, 28 Feb 2016 06:13:01 GMT) Full text and rfc822 format available.

Message #4 received at 5457 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Daniel Colascione <daniel <at> censorshipresearch.org>
Cc: 5457 <at> debbugs.gnu.org
Subject: Re: [PATCH] [RFC] C++1x support for cc-mode
Date: Sun, 28 Feb 2016 17:12:22 +1100
Daniel Colascione <daniel <at> censorshipresearch.org> writes:

> Here is a *very* rough patch that halfway implements most of the new
> language constructs. I've also included a small test file, though
> I'm sure there are some cases, especially around vararg-template and
> attribute syntax, that don't work yet.

I see that there is some code in cc-mode now that talks about C++1x
constructs, but I don't know whether they cover the dialects
satisfactorily.  Is this still an issue?

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#5457; Package emacs,cc-mode. (Thu, 27 Jun 2019 17:26:01 GMT) Full text and rfc822 format available.

Message #7 received at 5457 <at> debbugs.gnu.org (full text, mbox):

From: Lars Ingebrigtsen <larsi <at> gnus.org>
To: Daniel Colascione <daniel <at> censorshipresearch.org>
Cc: 5457 <at> debbugs.gnu.org
Subject: Re: bug#5457: [PATCH] [RFC] C++1x support for cc-mode
Date: Thu, 27 Jun 2019 19:25:43 +0200
Lars Ingebrigtsen <larsi <at> gnus.org> writes:

> Daniel Colascione <daniel <at> censorshipresearch.org> writes:
>
>> Here is a *very* rough patch that halfway implements most of the new
>> language constructs. I've also included a small test file, though
>> I'm sure there are some cases, especially around vararg-template and
>> attribute syntax, that don't work yet.
>
> I see that there is some code in cc-mode now that talks about C++1x
> constructs, but I don't know whether they cover the dialects
> satisfactorily.  Is this still an issue?

That was three years ago, so I'm closing this bug report.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no




bug closed, send any further explanations to 5457 <at> debbugs.gnu.org and Daniel Colascione <daniel <at> censorshipresearch.org> Request was from Lars Ingebrigtsen <larsi <at> gnus.org> to control <at> debbugs.gnu.org. (Thu, 27 Jun 2019 17:26:03 GMT) Full text and rfc822 format available.

bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Fri, 26 Jul 2019 11:24:09 GMT) Full text and rfc822 format available.

This bug report was last modified 4 years and 247 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.