From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Daniel Colascione Newsgroups: gmane.emacs.devel Subject: [PATCH] [RFC] C++1x support for cc-mode Date: Fri, 15 Jan 2010 11:24:54 -0500 Organization: Censorship Research Center Message-ID: <4B5096D6.2080302@censorshipresearch.org> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1263572774 2754 80.91.229.12 (15 Jan 2010 16:26:14 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Fri, 15 Jan 2010 16:26:14 +0000 (UTC) Cc: Emacs development discussions To: Alan Mackenzie Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jan 15 17:26:06 2010 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1NVozM-0006UA-3J for ged-emacs-devel@m.gmane.org; Fri, 15 Jan 2010 17:26:04 +0100 Original-Received: from localhost ([127.0.0.1]:41806 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NVozJ-0003Vq-O5 for ged-emacs-devel@m.gmane.org; Fri, 15 Jan 2010 11:25:29 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NVoyy-0003HK-60 for emacs-devel@gnu.org; Fri, 15 Jan 2010 11:25:08 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NVoyw-0003GT-O5 for emacs-devel@gnu.org; Fri, 15 Jan 2010 11:25:07 -0500 Original-Received: from [199.232.76.173] (port=45873 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NVoyw-0003GO-Km for emacs-devel@gnu.org; Fri, 15 Jan 2010 11:25:06 -0500 Original-Received: from mx20.gnu.org ([199.232.41.8]:28954) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NVoyv-00028y-S5 for emacs-devel@gnu.org; Fri, 15 Jan 2010 11:25:06 -0500 Original-Received: from haystack.austinheap.com ([70.32.98.68] helo=haystacknetwork.com) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NVoyu-0003Z4-6c for emacs-devel@gnu.org; Fri, 15 Jan 2010 11:25:04 -0500 User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.1.5) Gecko/20091204 Thunderbird/3.0 X-Enigmail-Version: 1.0 X-detected-operating-system: by mx20.gnu.org: Genre and OS details not recognized. X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:120055 Archived-At: -----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; + +extern template class std::vector; + +class SequenceClass +{ +public: + SequenceClass(std::initializer_list list); +}; + +SequenceClass someVar = {1, 4, 5, 6}; + +void FunctionName(std::initializer_list list); + +FunctionName({1.0f, -3.45f, -0.4f}); + +std::vector v = { "xyzzy", "plugh", "abracadabra" }; +std::vector 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 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::const_iterator itr = myvec.begin(); itr != myvec.end(); ++itr) +{} + +for (auto itr = myvec.begin(); itr != myvec.end(); ++itr) +{} + +#include +int main() +{ + const std::vector 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::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 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 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 class SomeType; +std::vector2>> x1 ; // Interpreted as a std::vector of SomeType 2>, +// which is not legal syntax. 1 is true. +std::vector2)>> x1 ; // Interpreted as std::vector of SomeType, +//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; + +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 class tuple; + +class tuple, std::map> > + someInstanceName; + +template class tuple; + +template 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 +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 +class ClassName : public BaseClasses... +{ + public: + ClassName (BaseClasses&& ... baseClasses) + : BaseClasses(baseClasses)... {} + +}; + + +template +struct SharedPtrAllocator +{ + template std::shared_ptr + ConstructWithSharedPtr(Args&& ...params) + { + return std::shared_ptr( + new TypeToConstruct(std::forward(params)..., int test)); + } +}; + + +template 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 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 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-----