diff --git a/CHANGES.md b/CHANGES.md index a5ba4a83d8..e63d360e9f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -61,6 +61,7 @@ CAVEATS / POTENTIALLY BREAKING CHANGES Core Grammars: +- fix(cpp) Keywords followed by parens are treated as built_in [Md Saad Akhtar][] - enh(typescript) add support for `satisfies` operator [Kisaragi Hiu][] - enc(c) added more C23 keywords [Melkor-1][] - enh(json) added jsonc as an alias [BackupMiles][] @@ -186,7 +187,6 @@ New Grammars: - added 3rd party Ballerina grammar to SUPPORTED_LANGUAGES [Yasith Deelaka][] Core Grammars: - - fix(cpp) fixed highlighter break state [Md Saad Akhtar][] - fix(rust) added negative-lookahead for callable keywords `if` `while` `for` [Omar Hussein][] - enh(armasm) added `x0-x30` and `w0-w30` ARMv8 registers [Nicholas Thompson][] diff --git a/src/languages/cpp.js b/src/languages/cpp.js index 64aee1d44e..891bb82e5f 100644 --- a/src/languages/cpp.js +++ b/src/languages/cpp.js @@ -415,6 +415,14 @@ export default function(hljs) { _type_hints: TYPE_HINTS }; + const allKeywords = [ + ...CPP_KEYWORDS.type, + ...CPP_KEYWORDS.keyword, + ...CPP_KEYWORDS.literal, + ...CPP_KEYWORDS.built_in, + ...CPP_KEYWORDS._type_hints + ]; + const FUNCTION_DISPATCH = { className: 'function.dispatch', relevance: 0, @@ -423,15 +431,11 @@ export default function(hljs) { _hint: FUNCTION_HINTS }, begin: regex.concat( /\b/, - /(?!decltype)/, - /(?!if)/, - /(?!for)/, - /(?!switch)/, - /(?!while)/, + // adds all keywords dynamically + ...allKeywords.map(keyword => new RegExp(`(?!${keyword})`)), hljs.IDENT_RE, regex.lookahead(/(<[^<>]+>|)\s*\(/)) }; - const EXPRESSION_CONTAINS = [ FUNCTION_DISPATCH, PREPROCESSOR, diff --git a/test/markup/cpp/keywords-with-parentheses.expect.txt b/test/markup/cpp/keywords-with-parentheses.expect.txt new file mode 100644 index 0000000000..a4d21c9e5f --- /dev/null +++ b/test/markup/cpp/keywords-with-parentheses.expect.txt @@ -0,0 +1,93 @@ +<span class="hljs-keyword">alignas</span>(<span class="hljs-number">16</span>) <span class="hljs-type">char</span> aligned_buffer[<span class="hljs-number">1024</span>]; +<span class="hljs-keyword">alignof</span>(<span class="hljs-keyword">decltype</span>(aligned_buffer)) +<span class="hljs-keyword">asm</span>(<span class="hljs-string">"movl $1, %eax"</span>); +<span class="hljs-keyword">try</span> { + <span class="hljs-keyword">throw</span> std::<span class="hljs-built_in">runtime_error</span>(<span class="hljs-string">"An exception occurred"</span>); +} <span class="hljs-keyword">catch</span> (<span class="hljs-type">const</span> std::exception& e) { + std::cout << <span class="hljs-string">"Caught exception: "</span> << e.<span class="hljs-built_in">what</span>() << std::endl; +} +<span class="hljs-type">const</span> <span class="hljs-type">int</span>* p = <span class="hljs-literal">nullptr</span>; +<span class="hljs-type">int</span>* mutable_p = <span class="hljs-keyword">const_cast</span><<span class="hljs-type">int</span>*>(p); +<span class="hljs-type">int</span> x = <span class="hljs-number">5</span>; +<span class="hljs-keyword">decltype</span>(x) y = <span class="hljs-number">10</span>; +Animal* animal = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Dog</span>(); +<span class="hljs-keyword">if</span> (Dog* dog = <span class="hljs-keyword">dynamic_cast</span><Dog*>(animal)) { + std::cout << <span class="hljs-string">"Dynamic cast successful"</span> << std::endl; +} <span class="hljs-keyword">else</span> { + std::cout << <span class="hljs-string">"Dynamic cast failed"</span> << std::endl; +} +<span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-type">int</span> a, <span class="hljs-type">int</span> b)</span> <span class="hljs-keyword">noexcept</span> </span>{ + <span class="hljs-keyword">return</span> a + b; +} +<span class="hljs-keyword">if</span> (<span class="hljs-keyword">noexcept</span>(<span class="hljs-built_in">add</span>(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>))) { + <span class="hljs-comment">// The add function will not throw an exception.</span> +} <span class="hljs-keyword">else</span> { + <span class="hljs-comment">// The add function may throw an exception.</span> +} +<span class="hljs-type">int</span> value = <span class="hljs-number">10</span>; +<span class="hljs-type">double</span>* ptr = <span class="hljs-keyword">reinterpret_cast</span><<span class="hljs-type">double</span>*>(&value); +std::cout << <span class="hljs-string">"Size of int: "</span> << <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>) << <span class="hljs-string">" bytes"</span> << std::endl; +<span class="hljs-keyword">static_assert</span>(<span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>) == <span class="hljs-number">4</span>, <span class="hljs-string">"int must be 4 bytes"</span>); +<span class="hljs-type">float</span> z = <span class="hljs-keyword">static_cast</span><<span class="hljs-type">float</span>>(<span class="hljs-number">10</span>); +<span class="hljs-type">int</span> choice = <span class="hljs-number">2</span>; +<span class="hljs-keyword">switch</span>(choice) { + <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>: + std::cout << <span class="hljs-string">"Choice is 1"</span> << std::endl; + <span class="hljs-keyword">break</span>; + <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>: + std::cout << <span class="hljs-string">"Choice is 2"</span> << std::endl; + <span class="hljs-keyword">break</span>; + <span class="hljs-keyword">default</span>: + std::cout << <span class="hljs-string">"Choice is not 1 or 2"</span> << std::endl; +} +std::cout << <span class="hljs-string">"Type of x: "</span> << <span class="hljs-keyword">typeid</span>(x).<span class="hljs-built_in">name</span>() << std::endl; +<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; +<span class="hljs-keyword">while</span>(i < <span class="hljs-number">5</span>) { + std::cout << <span class="hljs-string">"Iteration "</span> << i << std::endl; + i++; +} +<span class="hljs-comment">// requires</span> +<span class="hljs-keyword">template</span><<span class="hljs-keyword">class</span> <span class="hljs-title class_">T</span>> +<span class="hljs-keyword">concept</span> dereferenceable = + <span class="hljs-keyword">requires</span> { <span class="hljs-keyword">typename</span> <span class="hljs-type">iter_value_t</span><I>; } <span class="hljs-function"><span class="hljs-keyword">and</span> + <span class="hljs-title">requires</span><span class="hljs-params">(I i)</span> </span>{ + *i; + }; + +<span class="hljs-comment">// explicit</span> +<span class="hljs-keyword">template</span><<span class="hljs-keyword">class</span> <span class="hljs-title class_">T</span>> +<span class="hljs-keyword">struct</span> <span class="hljs-title class_">S</span> { + <span class="hljs-keyword">explicit</span>(weakly_incrementable<T>) <span class="hljs-built_in">S</span>(); +}; + +<span class="hljs-comment">// auto, operators</span> +<span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> +</span>{ + <span class="hljs-keyword">auto</span> x = <span class="hljs-keyword">auto</span>(<span class="hljs-number">0</span>); + x bitand_eq x; <span class="hljs-comment">// needs to be added too</span> + <span class="hljs-function">x <span class="hljs-title">bitand_eq</span> <span class="hljs-params">(x)</span></span>; + x bitor_eq x; <span class="hljs-comment">// needs to be added too</span> + <span class="hljs-function">x <span class="hljs-title">bitor_eq</span> <span class="hljs-params">(x)</span></span>; + x <span class="hljs-keyword">xor</span> x; + <span class="hljs-function">x <span class="hljs-title">xor</span> <span class="hljs-params">(x)</span></span>; + x <span class="hljs-keyword">and</span> x; + <span class="hljs-function">x <span class="hljs-title">and</span> <span class="hljs-params">(x)</span></span>; + x <span class="hljs-keyword">or</span> x; + <span class="hljs-function">x <span class="hljs-title">or</span> <span class="hljs-params">(x)</span></span>; + x <span class="hljs-keyword">bitand</span> x; + <span class="hljs-function">x <span class="hljs-title">bitand</span> <span class="hljs-params">(x)</span></span>; + x <span class="hljs-keyword">bitor</span> x; + <span class="hljs-function">x <span class="hljs-title">bitor</span> <span class="hljs-params">(x)</span></span>; + x <span class="hljs-keyword">not_eq</span> x; + <span class="hljs-function">x <span class="hljs-title">not_eq</span> <span class="hljs-params">(x)</span></span>; + <span class="hljs-keyword">not</span> x; + <span class="hljs-keyword">not</span> (x); + <span class="hljs-keyword">compl</span> x; + <span class="hljs-keyword">compl</span> (x); + <span class="hljs-keyword">co_await</span> x; + <span class="hljs-keyword">co_await</span> (x); + <span class="hljs-keyword">co_return</span> x; + <span class="hljs-keyword">co_return</span> (x); + <span class="hljs-keyword">co_yield</span> x; + <span class="hljs-keyword">co_yield</span> (x); +} diff --git a/test/markup/cpp/keywords-with-parentheses.txt b/test/markup/cpp/keywords-with-parentheses.txt new file mode 100644 index 0000000000..f2b30e6715 --- /dev/null +++ b/test/markup/cpp/keywords-with-parentheses.txt @@ -0,0 +1,93 @@ +alignas(16) char aligned_buffer[1024]; +alignof(decltype(aligned_buffer)) +asm("movl $1, %eax"); +try { + throw std::runtime_error("An exception occurred"); +} catch (const std::exception& e) { + std::cout << "Caught exception: " << e.what() << std::endl; +} +const int* p = nullptr; +int* mutable_p = const_cast<int*>(p); +int x = 5; +decltype(x) y = 10; +Animal* animal = new Dog(); +if (Dog* dog = dynamic_cast<Dog*>(animal)) { + std::cout << "Dynamic cast successful" << std::endl; +} else { + std::cout << "Dynamic cast failed" << std::endl; +} +int add(int a, int b) noexcept { + return a + b; +} +if (noexcept(add(1, 2))) { + // The add function will not throw an exception. +} else { + // The add function may throw an exception. +} +int value = 10; +double* ptr = reinterpret_cast<double*>(&value); +std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl; +static_assert(sizeof(int) == 4, "int must be 4 bytes"); +float z = static_cast<float>(10); +int choice = 2; +switch(choice) { + case 1: + std::cout << "Choice is 1" << std::endl; + break; + case 2: + std::cout << "Choice is 2" << std::endl; + break; + default: + std::cout << "Choice is not 1 or 2" << std::endl; +} +std::cout << "Type of x: " << typeid(x).name() << std::endl; +int i = 0; +while(i < 5) { + std::cout << "Iteration " << i << std::endl; + i++; +} +// requires +template<class T> +concept dereferenceable = + requires { typename iter_value_t<I>; } and + requires(I i) { + *i; + }; + +// explicit +template<class T> +struct S { + explicit(weakly_incrementable<T>) S(); +}; + +// auto, operators +int main() +{ + auto x = auto(0); + x bitand_eq x; // needs to be added too + x bitand_eq (x); + x bitor_eq x; // needs to be added too + x bitor_eq (x); + x xor x; + x xor (x); + x and x; + x and (x); + x or x; + x or (x); + x bitand x; + x bitand (x); + x bitor x; + x bitor (x); + x not_eq x; + x not_eq (x); + not x; + not (x); + compl x; + compl (x); + co_await x; + co_await (x); + co_return x; + co_return (x); + co_yield x; + co_yield (x); +} \ No newline at end of file diff --git a/test/markup/cpp/template-complexity.expect.txt b/test/markup/cpp/template-complexity.expect.txt index 92b83178b6..3f2a72f10d 100644 --- a/test/markup/cpp/template-complexity.expect.txt +++ b/test/markup/cpp/template-complexity.expect.txt @@ -10,7 +10,7 @@ <span class="hljs-keyword">template</span><<span class="hljs-keyword">class</span> <span class="hljs-title class_">T</span>, <span class="hljs-keyword">class</span> = std::<span class="hljs-type">enable_if_t</span><!impl::is_streamable_v<<span class="hljs-type">const</span> T &> && std::is_convertible_v<<span class="hljs-type">const</span> T &, std::wstring_view>>> std::wostream &<span class="hljs-keyword">operator</span> <<(std::wostream &stream, <span class="hljs-type">const</span> T &thing) { - <span class="hljs-keyword">return</span> stream << <span class="hljs-built_in">static_cast</span><std::wstring_view>(thing); + <span class="hljs-keyword">return</span> stream << <span class="hljs-keyword">static_cast</span><std::wstring_view>(thing); } <span class="hljs-keyword">enum struct</span> <span class="hljs-title class_">DataHolder</span> { };