Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions C++/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,5 @@ add_subdirectory(0050)
add_subdirectory(0051)
add_subdirectory(0052)
add_subdirectory(0053)
add_subdirectory(cxx17)
add_subdirectory(cxx20)
45 changes: 45 additions & 0 deletions C++/cxx17/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
set(cxx17_sources
aggregate_init_with_base.cpp
attr_namespace_enum.cpp
attribute_namespace_using.cpp
auto_non_type_template_param.cpp
# bool_increment_removed.cpp
class_template_argument_deduction.cpp
constexpr_if.cpp
constexpr_lambda.cpp
direct_list_init_auto.cpp
enum_direct_list_init.cpp
exception-spec-type.cpp
fallthrough_attr.cpp
fold_expression.cpp
guaranteed_copy_elision.cpp
has_include_preprocessor.cpp
hex_float_literal.cpp
if_switch_init_statement.cpp
ignore_unknown_attributes.cpp
inline_variables.cpp
lambda_capture_this_value.cpp
maybe_unused_attr.cpp
nested_namespace_definition.cpp
no_trigraphs.cpp
nodiscard_attr.cpp
non_type_template_consteval.cpp
overaligned_allocation.cpp
pack_expansion_using_declaration.cpp
range_for_sentinel.cpp
# remove_register_storage_class.cpp
removed_dynamic_exception_spec.cpp
static_assert_no_message.cpp
stricter_expression_evaluation_order.cpp
structured_bindings.cpp
template_template_compat.cpp
template_template_typename.cpp
u8_char_literals.cpp
)

foreach(src ${cxx17_sources})
set_property(SOURCE ${src}
APPEND PROPERTY COMPILE_OPTIONS "-std=c++17")
endforeach()

llvm_singlesource_fujitsu(PREFIX "Fujitsu-C++-")
74 changes: 74 additions & 0 deletions C++/cxx17/aggregate_init_with_base.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
FEATURE: Aggregate initialization of classes with base classes
SPEC: C++17 standard — aggregate initialization rules for classes with base classes (see C++17 draft / standard aggregate definition)
PURPOSE: Verify that a class deriving from a public non-virtual base with no user-provided constructors
is treated as an aggregate under C++17 and can be initialized via aggregate initialization,
including both braced base-subobject form and flat initializer-list form.
RUN: clang++ -std=c++17 -Wall -Wextra -Werror -Wno-missing-braces aggregate_init_with_base.cpp
*/

#include <cmath> // for std::fabs
#include <cstdint> // for std::int32_t
#include <cstdlib> // for EXIT_SUCCESS / EXIT_FAILURE

// Simple base and derived types that qualify as aggregates under C++17:
// - no user-provided constructors
// - no private or protected non-static data members
// - no virtual base classes
// - public (default for struct) inheritance
struct Base {
int a;
double b;
};

struct Derived : Base {
int c;
};

// Another example with two base classes and an own member to show order-of-initialization behavior.
struct Left {
int l;
};

struct Right {
int r;
};

struct MultiDerived : Left, Right {
int m;
};

// Helper for floating-point comparison
bool almost_equal(double x, double y, double eps = 1e-12) {
return std::fabs(x - y) <= eps;
}

int main() {
// 1) Initialize Derived by explicitly initializing the base subobject, then derived members.
// This form uses nested braces for the base subobject.
Derived d1{ { 1, 2.5 }, 3 };

if (d1.a != 1) return EXIT_FAILURE;
if (!almost_equal(d1.b, 2.5)) return EXIT_FAILURE;
if (d1.c != 3) return EXIT_FAILURE;

// 2) Initialize Derived using a flat initializer-list (C++17 allows the base's members
// to be initialized in declaration order without explicit nested braces).
Derived d2{ 10, 20.5, 30 };

if (d2.a != 10) return EXIT_FAILURE;
if (!almost_equal(d2.b, 20.5)) return EXIT_FAILURE;
if (d2.c != 30) return EXIT_FAILURE;

// 3) Multi-base example: initializer-list initializes base subobjects in declaration
// order (Left, then Right), then members of the most-derived class.
MultiDerived m{ 7, 8, 9 }; // maps to Left::l = 7, Right::r = 8, MultiDerived::m = 9

if (m.l != 7) return EXIT_FAILURE;
if (m.r != 8) return EXIT_FAILURE;
if (m.m != 9) return EXIT_FAILURE;

// If all checks passed, return success (0).
return EXIT_SUCCESS;
}

40 changes: 40 additions & 0 deletions C++/cxx17/attr_namespace_enum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
FEATURE: Attributes for namespaces and enumerators
SPEC: N4266 §7.6.1 [dcl.attr.grammar]
PURPOSE: Verify that C++17 allows applying attributes to namespaces and individual enumerators,
and that the compiler emits appropriate warnings for deprecated elements.
RUN: clang++ -std=c++17 -Wall -Wextra attr_namespace_enum.cpp
*/

#include <iostream>

// Apply an attribute to a namespace
namespace
[[deprecated("use new_namespace instead")]]
old_namespace {
inline int get_value() { return 42; }
}

// Apply an attribute to an enumerator
enum class Color {
Red,
Green,
Blue [[deprecated("Blue is deprecated")]]
};

int main() {
int result = 0;

// Accessing deprecated namespace should trigger a warning
int val = old_namespace::get_value();
if (val != 42)
result = 1;

// Using deprecated enumerator should trigger a warning
Color c = Color::Blue;
if (c != Color::Blue)
result = 2;

// Return 0 if all runtime checks are OK
return result;
}
46 changes: 46 additions & 0 deletions C++/cxx17/attribute_namespace_using.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
FEATURE: Using attribute namespaces without repetition
SPEC: N4266 §7 (C++17 attribute namespace grouping)
PURPOSE: Verify that the compiler correctly accepts the C++17 syntax
`[[using ns: attr1, attr2]]` where an attribute namespace is
specified once and reused for multiple attributes without repetition.
RUN: clang++ -std=c++17 -Wall -Wextra -Werror attribute_namespace_using.cpp
*/

#include <iostream>
#include <cstdlib> // for EXIT_SUCCESS / EXIT_FAILURE

// Define a custom attribute namespace for testing
namespace vendor {
// GNU-style attribute handling for testing; actual effect is irrelevant.
// These do nothing but allow syntax checking.
#if defined(__clang__)
// Using clang's vendor-specific attribute handling mechanism
[[clang::syntax_only]] // No-op to ensure the namespace is recognized
inline void dummy() {}
#endif
}

// Apply attributes using the C++17 grouping syntax
[[using vendor: unused]]
void func1() {
// This function intentionally left blank
}

// Apply multiple attributes in the same namespace
[[using vendor: unused, unused]]
void func2() {
// This function intentionally left blank
}

int main() {
// The purpose of the test is strictly syntactic.
// If the compiler accepts the grouped attribute syntax, this test passes.
// If compilation fails, the test framework will treat it as a failure.

func1();
func2();

return EXIT_SUCCESS;
}

49 changes: 49 additions & 0 deletions C++/cxx17/auto_non_type_template_param.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
FEATURE: Non-type template parameters with auto type
SPEC: ISO/IEC 14882:2017 (C++17) [temp.param] (see also P0127R2)
PURPOSE: Verify that non-type template parameters can use 'auto' so that
the parameter type is deduced from the provided constant expression.
RUN: clang++ -std=c++17 -Wall -Wextra -Werror auto_non_type_template_param.cpp
*/

#include <type_traits>
#include <cstddef>
#include <cstdlib> // for EXIT_SUCCESS / EXIT_FAILURE

// A template with a non-type template parameter using auto.
template <auto Value>
struct Holder {
static constexpr auto value = Value;
};

int main()
{
// Integer constant: type should be deduced as int.
Holder<42> h_int;
static_assert(std::is_same<decltype(h_int.value), const int>::value,
"Type of Value should be int");

// Size-related constant: type should be deduced as std::size_t.
Holder<sizeof(int)> h_size;
static_assert(std::is_same<decltype(h_size.value), const std::size_t>::value,
"Type of Value should be std::size_t");

// Pointer constant: type should be deduced as a pointer type.
static int global = 0;
Holder<&global> h_ptr;
static_assert(std::is_same<decltype(h_ptr.value), int *const>::value,
"Type of Value should be int* const");

// Runtime check to ensure the values are usable.
if (h_int.value != 42) {
return EXIT_FAILURE;
}
if (h_size.value != sizeof(int)) {
return EXIT_FAILURE;
}
if (h_ptr.value != &global) {
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}
25 changes: 25 additions & 0 deletions C++/cxx17/bool_increment_removed.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
FEATURE: Remove deprecated bool increment
SPEC: N4296 §4.5; P0001R1
PURPOSE: Confirm that increment/decrement operators applied to bool are removed in C++17 and must produce a compile-time error.
RUN: clang++ -std=c++17 -Wall -Wextra bool_increment_removed.cpp
*/

// This program is a negative test. It is expected to fail to compile on a
// conforming C++17 compiler because incrementing a bool is removed in C++17.

bool test_bool_increment() {
bool b = false;
// The following line must produce a compile error in C++17.
++b; // expected-error: increment of bool is removed in C++17
return b;
}

int main() {
// This function would never be reached in a correct C++17 implementation
// because the translation must fail before linking.
int ret = 0; // A value other than 0 indicates that the test failed.
if (test_bool_increment() == false) ret= 1;
return ret;
}

62 changes: 62 additions & 0 deletions C++/cxx17/class_template_argument_deduction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
FEATURE: Template argument deduction for class templates
SPEC: ISO/IEC 14882:2017 (C++17), §17.8.2 [temp.deduct.guide]
PURPOSE: Verify that class template arguments can be deduced from constructor arguments (CTAD),
including standard library templates and a user-defined template with a deduction guide.
RUN: clang++ -std=c++17 -Wall -Wextra -Werror class_template_argument_deduction.cpp
*/

#include <utility>
#include <vector>
#include <type_traits>
#include <cstddef>
#include <cstdlib> // for EXIT_SUCCESS / EXIT_FAILURE

/*
A simple user-defined class template.
*/
template <typename T, typename U>
struct Box {
T first;
U second;

Box(T a, U b) : first(a), second(b) {}
};

/*
A deduction guide that forces the second template argument to be std::size_t
when the second constructor argument is an integer literal.
*/
template <typename T>
Box(T, int) -> Box<T, std::size_t>;

int main()
{
// --- Standard library examples ---

// CTAD for std::pair
std::pair p(1, 2.5); // deduced as std::pair<int, double>
static_assert(std::is_same_v<decltype(p), std::pair<int, double>>,
"CTAD failed for std::pair");

// CTAD for std::vector
std::vector v{1, 2, 3}; // deduced as std::vector<int>
static_assert(std::is_same_v<decltype(v), std::vector<int>>,
"CTAD failed for std::vector");

// --- User-defined class template example ---

// Basic CTAD without an explicit deduction guide
Box b1(10, 3.14); // deduced as Box<int, double>
static_assert(std::is_same_v<decltype(b1), Box<int, double>>,
"CTAD failed for user-defined template (default deduction)");

// CTAD with an explicit deduction guide
Box b2(42, 7); // deduced as Box<int, std::size_t> due to the deduction guide
static_assert(std::is_same_v<decltype(b2), Box<int, std::size_t>>,
"CTAD failed for user-defined template with deduction guide");

// If all static assertions pass, the test succeeds.
return EXIT_SUCCESS;
}

43 changes: 43 additions & 0 deletions C++/cxx17/constexpr_if.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
FEATURE: C++17 constexpr if-statements
SPEC: ISO/IEC 14882:2017 (C++17) §8.5.2 [stmt.if]
PURPOSE: Verify that if constexpr evaluates conditions at compile time and discards
non-selected branches so that ill-formed code in discarded branches does
not cause compilation errors.
RUN: clang++ -std=c++17 -Wall -Wextra -Werror constexpr_if.cpp
*/

#include <type_traits>
#include <cstddef>
#include <cstdlib> // for EXIT_SUCCESS / EXIT_FAILURE

// This template uses if constexpr to select code paths depending on the type.
// The discarded branch intentionally contains code that would be ill-formed
// if it were instantiated.
template <typename T>
constexpr std::size_t type_dependent_size()
{
if constexpr (std::is_integral<T>::value) {
// Valid branch for integral types
return sizeof(T);
} else {
// This code would be ill-formed if instantiated, because T does not
// have a member named non_existent_member.
// It must not be compiled when the condition is false.
return T::non_existent_member;
}
}

int main()
{
// For int, the integral branch must be selected at compile time.
constexpr std::size_t s = type_dependent_size<int>();

// Basic runtime check to confirm expected behavior.
if (s != sizeof(int)) {
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

Loading