blob: 809c1fc864618d55a82bb755669184fabfca0099 [file] [edit]
// RUN: %clang_cc1 -triple x86_64-unknown-linux -std=c++20 -emit-llvm -o - %s | FileCheck %s
// CHECK-DAG: define {{.*}} @_ZeqRK6TargetS1_({{.*}}) [[NORMAL_ATTRS:#[0-9]+]]
// CHECK-DAG: define {{.*}} @_ZeqRK12StrictTargetS1_({{.*}}) [[STRICT_ATTRS:#[0-9]+]]
// CHECK-DAG: define {{.*}} @_ZN12AssignTargetaSERKS_({{.*}}) [[NORMAL_ATTRS]]
// CHECK-DAG: define {{.*}} @_ZN18StrictAssignTargetaSERKS_({{.*}}) [[STRICT_ATTRS]]
// Templates
// CHECK-DAG: define {{.*}} @_ZeqRK14TemplateTargetIdES2_({{.*}}) [[NORMAL_ATTRS]]
// CHECK-DAG: define {{.*}} @_ZeqRK14TemplateTargetIfES2_({{.*}}) [[NORMAL_ATTRS]]
// CHECK-DAG: define {{.*}} @_ZeqRK20StrictTemplateTargetIdES2_({{.*}}) [[STRICT_ATTRS]]
// --- NON-STRICT DECLARATIONS (at top of file, default FP is non-strict) ---
struct Target {
double d;
friend bool operator==(const Target&, const Target&) = default;
};
struct Member {
double d;
Member& operator=(const Member& Other) {
d = Other.d + 1.0;
return *this;
}
};
struct AssignTarget {
Member m;
};
template <typename T>
struct TemplateTarget {
T d;
friend bool operator==(const TemplateTarget&, const TemplateTarget&) = default;
};
// Trigger instantiation of TemplateTarget<double>::operator== in non-strict context.
bool test_template_non_strict(TemplateTarget<double> a, TemplateTarget<double> b) {
return a == b;
}
// --- STRICT CONTEXT (pragmas enabled) ---
#pragma STDC FENV_ACCESS ON
// Use-sites triggering synthesis of non-strict defaulted functions in strict context.
bool test_non_strict_cmp(Target a, Target b) {
return a == b;
}
void test_non_strict_assign(AssignTarget& a, AssignTarget& b) {
a = b;
}
// Trigger instantiation of TemplateTarget<float>::operator== in strict context.
// It should still be non-strict because the template was defined in non-strict context.
bool test_template_strict(TemplateTarget<float> a, TemplateTarget<float> b) {
return a == b;
}
// Strict declarations (must get strictfp)
struct StrictTarget {
double d;
friend bool operator==(const StrictTarget&, const StrictTarget&) = default;
};
bool test_strict_cmp(StrictTarget a, StrictTarget b) {
return a == b;
}
struct StrictAssignTarget {
Member m;
};
void test_strict_assign(StrictAssignTarget& a, StrictAssignTarget& b) {
a = b;
}
template <typename T>
struct StrictTemplateTarget {
T d;
friend bool operator==(const StrictTemplateTarget&, const StrictTemplateTarget&) = default;
};
// --- NON-STRICT CONTEXT AGAIN ---
#pragma STDC FENV_ACCESS OFF
// Trigger instantiation of StrictTemplateTarget<double>::operator== in non-strict context.
// It should be strict because the template was defined in strict context.
bool test_strict_template_non_strict(StrictTemplateTarget<double> a, StrictTemplateTarget<double> b) {
return a == b;
}
// CHECK-DAG: attributes [[STRICT_ATTRS]] = { {{.*}}strictfp{{.*}} }
// CHECK-DAG: attributes [[NORMAL_ATTRS]] = { {{.*}} }
// CHECK-NOT: attributes [[NORMAL_ATTRS]] = { {{.*}}strictfp