cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[BUG] clang-cl compiler error with generated c++ code for swap member function with 'that' parameter

Open inflooper opened this issue 4 months ago • 0 comments

Describe the bug Defining a swap member function with a that parameter causes compiler error with clang-cl. The code emitted by a swap member function with a that parameter looks like the following:

 public: auto swap(test&& that) noexcept && -> void;

The compiler is not happy with noexcept followed by &&. It only compiles when && precedes noexcept.

To Reproduce Steps to reproduce the behavior:

  1. Sample code - distilled down to minimal essentials please
test: type = {
	a: int = 0;

	swap: (move this, move that) = {
		temp_a: int = this.a;
		a = that.a;
		that.a = temp_a;
	}
}
  1. Command lines including which C++ compiler you are using
clang version 19.1.5
Target: x86_64-pc-windows-msvc
cppfront compiler v0.8.2 Build A828:0952

.\cppfront\bin\cppfront.exe .\member_func_rvalue_qualifier_bug.cpp2 -p clang-cl .\member_func_rvalue_qualifier_bug.cpp -std:c++20 -EHsc -I .\cppfront\include\

  1. Expected result - what you expected to happen Either: A. The noexcept and && function qualifiers are swapped during code generation B. cppfront compiler error stating that is not allowed in swap function

  2. Actual result/error

.\member_func_rvalue_qualifier_bug.cpp2(4,41): error: expected ';' at end of declaration list
    4 |  public: auto swap(test&& that) noexcept && -> void;
      |                                         ^
      |                                         ;
.\member_func_rvalue_qualifier_bug.cpp2(4,40): error: expected function body after function declarator
    4 |  auto test::swap(test&& that) noexcept && -> void{
      |                                        ^

Additional context cpp code emitted by the cppfront compiler

#define CPP2_IMPORT_STD          Yes

#include "cpp2util.h"

class test;

class test {
 private: int a {0}; 

 public: auto swap(test&& that) noexcept && -> void;
 public: test() = default;
 public: test(test const&) = delete; /* No 'that' constructor, suppress copy */
 public: auto operator=(test const&) -> void = delete;
};

 auto test::swap(test&& that) noexcept && -> void{
  int temp_a {(*this).a}; 
  a = cpp2::move(that).a;
  that.a = cpp2::move(temp_a);
 }

inflooper avatar Sep 18 '25 22:09 inflooper