| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,241 @@ | ||
| // RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: {bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: true, bugprone-sizeof-expression.WarnOnSizeOfPointer: true}}" -- | ||
|
|
||
| class C { | ||
| int size() { return sizeof(this); } | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(this)' | ||
| }; | ||
|
|
||
| #define LEN 8 | ||
|
|
||
| int X; | ||
| extern int A[10]; | ||
| extern short B[10]; | ||
|
|
||
| #pragma pack(1) | ||
| struct S { char a, b, c; }; | ||
|
|
||
| enum E { E_VALUE = 0 }; | ||
| enum class EC { VALUE = 0 }; | ||
|
|
||
| bool AsBool() { return false; } | ||
| int AsInt() { return 0; } | ||
| E AsEnum() { return E_VALUE; } | ||
| EC AsEnumClass() { return EC::VALUE; } | ||
| S AsStruct() { return {}; } | ||
|
|
||
| struct M { | ||
| int AsInt() { return 0; } | ||
| E AsEnum() { return E_VALUE; } | ||
| S AsStruct() { return {}; } | ||
| }; | ||
|
|
||
| int Test1(const char* ptr) { | ||
| int sum = 0; | ||
| sum += sizeof(LEN); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)' | ||
| sum += sizeof(LEN + 1); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)' | ||
| sum += sizeof(sum, LEN); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(..., ...)' | ||
| sum += sizeof(AsBool()); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer | ||
| sum += sizeof(AsInt()); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer | ||
| sum += sizeof(AsEnum()); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer | ||
| sum += sizeof(AsEnumClass()); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer | ||
| sum += sizeof(M{}.AsInt()); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer | ||
| sum += sizeof(M{}.AsEnum()); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer | ||
| sum += sizeof(sizeof(X)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' | ||
| sum += sizeof(LEN + sizeof(X)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' | ||
| sum += sizeof(LEN + LEN + sizeof(X)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' | ||
| sum += sizeof(LEN + (LEN + sizeof(X))); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' | ||
| sum += sizeof(LEN + -sizeof(X)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' | ||
| sum += sizeof(LEN + - + -sizeof(X)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' | ||
| sum += sizeof(char) / sizeof(char); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)' | ||
| sum += sizeof(A) / sizeof(S); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator | ||
| sum += sizeof(char) / sizeof(int); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator | ||
| sum += sizeof(char) / sizeof(A); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator | ||
| sum += sizeof(B[0]) / sizeof(A); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator | ||
| sum += sizeof(ptr) / sizeof(char); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(ptr) / sizeof(ptr[0]); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(ptr) / sizeof(char*); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(ptr) / sizeof(void*); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(ptr) / sizeof(const void volatile*); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(ptr) / sizeof(char); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(int) * sizeof(char); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication | ||
| sum += sizeof(ptr) * sizeof(ptr[0]); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication | ||
| sum += sizeof(int) * (2 * sizeof(char)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication | ||
| sum += (2 * sizeof(char)) * sizeof(int); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious 'sizeof' by 'sizeof' multiplication | ||
| if (sizeof(A) < 0x100000) sum += 42; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant | ||
| if (sizeof(A) <= 0xFFFFFFFEU) sum += 42; | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant | ||
| return sum; | ||
| } | ||
|
|
||
| int Test5() { | ||
| typedef int Array10[10]; | ||
| typedef C ArrayC[10]; | ||
|
|
||
| struct MyStruct { | ||
| Array10 arr; | ||
| Array10* ptr; | ||
| }; | ||
| typedef const MyStruct TMyStruct; | ||
| typedef const MyStruct *PMyStruct; | ||
| typedef TMyStruct *PMyStruct2; | ||
|
|
||
| static TMyStruct kGlocalMyStruct = {}; | ||
| static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct; | ||
|
|
||
| MyStruct S; | ||
| PMyStruct PS; | ||
| PMyStruct2 PS2; | ||
| Array10 A10; | ||
| C *PtrArray[10]; | ||
| C *PC; | ||
|
|
||
| char *PChar; | ||
| int *PInt, **PPInt; | ||
| MyStruct **PPMyStruct; | ||
|
|
||
| int sum = 0; | ||
| sum += sizeof(&S.arr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(&kGlocalMyStruct.arr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(&kGlocalMyStructPtr->arr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(S.arr + 0); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(+ S.arr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof((int*)S.arr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
|
|
||
| sum += sizeof(S.ptr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(kGlocalMyStruct.ptr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(kGlocalMyStructPtr->ptr); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
|
|
||
| sum += sizeof(&kGlocalMyStruct); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(&S); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(MyStruct*); | ||
| sum += sizeof(PMyStruct); | ||
| sum += sizeof(PS); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(PS2); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(&A10); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(PtrArray) / sizeof(PtrArray[1]); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(A10) / sizeof(PtrArray[0]); | ||
| sum += sizeof(PC) / sizeof(PtrArray[0]); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)' | ||
| sum += sizeof(ArrayC) / sizeof(PtrArray[0]); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator | ||
|
|
||
| sum += sizeof(PChar); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(PInt); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(PPInt); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(PPMyStruct); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
|
|
||
| return sum; | ||
| } | ||
|
|
||
| void some_generic_function(const void *arg, int argsize); | ||
| int *IntP, **IntPP; | ||
| C *ClassP, **ClassPP; | ||
|
|
||
| void GenericFunctionTest() { | ||
| // The `sizeof(pointer)` checks ignore situations where the pointer is | ||
| // produced by dereferencing a pointer-to-pointer, because this is unlikely | ||
| // to be an accident and can appear in legitimate code that tries to call | ||
| // a generic function which emulates dynamic typing within C. | ||
| some_generic_function(IntPP, sizeof(*IntPP)); | ||
| some_generic_function(ClassPP, sizeof(*ClassPP)); | ||
| // Using `...[0]` instead of the dereference operator is another common | ||
| // variant, which is also widespread in the idiomatic array-size calculation: | ||
| // `sizeof(array) / sizeof(array[0])`. | ||
| some_generic_function(IntPP, sizeof(IntPP[0])); | ||
| some_generic_function(ClassPP, sizeof(ClassPP[0])); | ||
| // FIXME: There is a third common pattern where the generic function is | ||
| // called with `&Variable` and `sizeof(Variable)`. Right now these are | ||
| // reported by the `sizeof(pointer)` checks, but this causes some false | ||
| // positives, so it would be good to create an exception for them. | ||
| some_generic_function(&IntPP, sizeof(IntP)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| some_generic_function(&ClassPP, sizeof(ClassP)); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| } | ||
|
|
||
| int ValidExpressions() { | ||
| int A[] = {1, 2, 3, 4}; | ||
| static const char str[] = "hello"; | ||
| static const char* ptr[] { "aaa", "bbb", "ccc" }; | ||
| typedef C *CA10[10]; | ||
| C *PtrArray[10]; | ||
| CA10 PtrArray1; | ||
|
|
||
| int sum = 0; | ||
| if (sizeof(A) < 10) | ||
| sum += sizeof(A); | ||
| sum += sizeof(int); | ||
| sum += sizeof(AsStruct()); | ||
| sum += sizeof(M{}.AsStruct()); | ||
| sum += sizeof(A[sizeof(A) / sizeof(int)]); | ||
| // Here the outer sizeof is reported, but the inner ones are accepted: | ||
| sum += sizeof(&A[sizeof(A) / sizeof(int)]); | ||
| // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer | ||
| sum += sizeof(sizeof(0)); // Special case: sizeof size_t. | ||
| sum += sizeof(void*); | ||
| sum += sizeof(void const *); | ||
| sum += sizeof(void const *) / 4; | ||
| sum += sizeof(str); | ||
| sum += sizeof(str) / sizeof(char); | ||
| sum += sizeof(str) / sizeof(str[0]); | ||
| sum += sizeof(ptr) / sizeof(ptr[0]); | ||
| sum += sizeof(ptr) / sizeof(*(ptr)); | ||
| sum += sizeof(PtrArray) / sizeof(PtrArray[0]); | ||
| // Canonical type of PtrArray1 is same as PtrArray. | ||
| sum = sizeof(PtrArray) / sizeof(PtrArray1[0]); | ||
| // There is no warning for 'sizeof(T*)/sizeof(Q)' case. | ||
| sum += sizeof(PtrArray) / sizeof(A[0]); | ||
| return sum; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // RUN: %clang_cc1 -std=c++26 -fsyntax-only -fcxx-exceptions -verify=ref,both %s | ||
| // RUN: %clang_cc1 -std=c++26 -fsyntax-only -fcxx-exceptions -verify=expected,both %s -fexperimental-new-constant-interpreter | ||
|
|
||
| // both-no-diagnostics | ||
|
|
||
| namespace VoidCast { | ||
| constexpr void* p = nullptr; | ||
| constexpr int* q = static_cast<int*>(p); | ||
| static_assert(q == nullptr); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| // Test triple manipulations. | ||
|
|
||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=i386-apple-darwin10 -mappletvsimulator-version-min=9.0 -arch x86_64 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=x86_64 -DOS=tvos9.0.0-simulator | ||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=armv7s-apple-darwin10 -mappletvos-version-min=9.0 -arch arm64 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=arm64 -DOS=tvos9.0.0 | ||
| // RUN: env TVOS_DEPLOYMENT_TARGET=9.0 %clang -### -c %s \ | ||
| // RUN: -isysroot SDKs/MacOSX10.9.sdk -target i386-apple-darwin10 -arch x86_64 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=x86_64 -DOS=tvos9.0.0 | ||
|
|
||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=x86_64-apple-driverkit19.0 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=x86_64 -DOS=driverkit19.0.0 | ||
|
|
||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=i386-apple-darwin10 -miphonesimulator-version-min=7.0 -arch i386 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=i386 -DOS=ios7.0.0-simulator | ||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=armv7s-apple-darwin10 -miphoneos-version-min=7.0 -arch armv7s 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=thumbv7s -DOS=ios7.0.0 | ||
|
|
||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=i386-apple-darwin10 -mwatchsimulator-version-min=2.0 -arch i386 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=i386 -DOS=watchos2.0.0-simulator | ||
| // RUN: %clang -### -c %s \ | ||
| // RUN: --target=armv7s-apple-darwin10 -mwatchos-version-min=2.0 -arch armv7k 2>&1 | \ | ||
| // RUN: FileCheck %s -DARCH=thumbv7k -DOS=watchos2.0.0 | ||
|
|
||
| // CHECK: "-cc1" "-triple" "[[ARCH]]-apple-[[OS]]" |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| //===- unittests/Analysis/FlowSensitive/ASTOpsTest.cpp --------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "clang/Analysis/FlowSensitive/ASTOps.h" | ||
| #include "TestingSupport.h" | ||
| #include "gmock/gmock.h" | ||
| #include "gtest/gtest.h" | ||
| #include <memory> | ||
|
|
||
| namespace { | ||
|
|
||
| using namespace clang; | ||
| using namespace dataflow; | ||
|
|
||
| using ast_matchers::cxxRecordDecl; | ||
| using ast_matchers::hasName; | ||
| using ast_matchers::hasType; | ||
| using ast_matchers::initListExpr; | ||
| using ast_matchers::match; | ||
| using ast_matchers::selectFirst; | ||
| using test::findValueDecl; | ||
| using testing::IsEmpty; | ||
| using testing::UnorderedElementsAre; | ||
|
|
||
| TEST(ASTOpsTest, RecordInitListHelperOnEmptyUnionInitList) { | ||
| // This is a regression test: The `RecordInitListHelper` used to assert-fail | ||
| // when called for the `InitListExpr` of an empty union. | ||
| std::string Code = R"cc( | ||
| struct S { | ||
| S() : UField{} {}; | ||
| union U {} UField; | ||
| }; | ||
| )cc"; | ||
| std::unique_ptr<ASTUnit> Unit = | ||
| tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"}); | ||
| auto &ASTCtx = Unit->getASTContext(); | ||
|
|
||
| ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U); | ||
|
|
||
| auto *InitList = selectFirst<InitListExpr>( | ||
| "init", | ||
| match(initListExpr(hasType(cxxRecordDecl(hasName("U")))).bind("init"), | ||
| ASTCtx)); | ||
| ASSERT_NE(InitList, nullptr); | ||
|
|
||
| RecordInitListHelper Helper(InitList); | ||
| EXPECT_THAT(Helper.base_inits(), IsEmpty()); | ||
| EXPECT_THAT(Helper.field_inits(), IsEmpty()); | ||
| } | ||
|
|
||
| TEST(ASTOpsTest, ReferencedDeclsOnUnionInitList) { | ||
| // This is a regression test: `getReferencedDecls()` used to return a null | ||
| // `FieldDecl` in this case (in addition to the correct non-null `FieldDecl`) | ||
| // because `getInitializedFieldInUnion()` returns null for the syntactic form | ||
| // of the `InitListExpr`. | ||
| std::string Code = R"cc( | ||
| struct S { | ||
| S() : UField{0} {}; | ||
| union U { | ||
| int I; | ||
| } UField; | ||
| }; | ||
| )cc"; | ||
| std::unique_ptr<ASTUnit> Unit = | ||
| tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++17"}); | ||
| auto &ASTCtx = Unit->getASTContext(); | ||
|
|
||
| ASSERT_EQ(ASTCtx.getDiagnostics().getClient()->getNumErrors(), 0U); | ||
|
|
||
| auto *InitList = selectFirst<InitListExpr>( | ||
| "init", | ||
| match(initListExpr(hasType(cxxRecordDecl(hasName("U")))).bind("init"), | ||
| ASTCtx)); | ||
| ASSERT_NE(InitList, nullptr); | ||
| auto *IDecl = cast<FieldDecl>(findValueDecl(ASTCtx, "I")); | ||
|
|
||
| EXPECT_THAT(getReferencedDecls(*InitList).Fields, | ||
| UnorderedElementsAre(IDecl)); | ||
| } | ||
|
|
||
| } // namespace |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| ! RUN: %flang_fc1 -emit-llvm -debug-info-kind=standalone %s -o - | FileCheck %s | ||
|
|
||
| subroutine ff(arr) | ||
| implicit none | ||
| integer :: arr(:, :) | ||
| return arr(1,1) | ||
| end subroutine ff | ||
|
|
||
| ! CHECK-DAG: !DICompositeType(tag: DW_TAG_array_type{{.*}}elements: ![[ELEMS:[0-9]+]], dataLocation: !DIExpression(DW_OP_push_object_address, DW_OP_deref)) | ||
| ! CHECK-DAG: ![[ELEMS]] = !{![[ELEM1:[0-9]+]], ![[ELEM2:[0-9]+]]} | ||
| ! CHECK-DAG: ![[ELEM1]] = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 24, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 32, DW_OP_deref)) | ||
| ! CHECK-DAG: ![[ELEM2]] = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 48, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 56, DW_OP_deref)) | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // RUN: fir-opt --add-debug-info --mlir-print-debuginfo %s | FileCheck %s | ||
|
|
||
| module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i64, dense<64> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<270>, dense<32> : vector<4xi64>>, #dlti.dl_entry<f128, dense<128> : vector<2xi64>>, #dlti.dl_entry<f80, dense<128> : vector<2xi64>>, #dlti.dl_entry<i128, dense<128> : vector<2xi64>>, #dlti.dl_entry<i8, dense<8> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi64>>, #dlti.dl_entry<i1, dense<8> : vector<2xi64>>, #dlti.dl_entry<f16, dense<16> : vector<2xi64>>, #dlti.dl_entry<f64, dense<64> : vector<2xi64>>, #dlti.dl_entry<i32, dense<32> : vector<2xi64>>, #dlti.dl_entry<i16, dense<16> : vector<2xi64>>, #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>, #dlti.dl_entry<"dlti.endianness", "little">>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"} { | ||
| func.func @ff_(%arg0: !fir.box<!fir.array<?x?xi32>> {fir.bindc_name = "arr"} ) { | ||
| %0 = fir.undefined !fir.dscope | ||
| %1 = fircg.ext_declare %arg0 dummy_scope %0 {uniq_name = "_QFffEarr"} : (!fir.box<!fir.array<?x?xi32>>, !fir.dscope) -> !fir.box<!fir.array<?x?xi32>> loc(#loc1) | ||
| return | ||
| } loc(#loc2) | ||
| } | ||
| #loc1 = loc("test1.f90":1:1) | ||
| #loc2 = loc("test1.f90":3:16) | ||
|
|
||
| // CHECK: #llvm.di_composite_type<tag = DW_TAG_array_type | ||
| // CHECK-SAME: elements = #llvm.di_subrange<lowerBound = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_plus_uconst(24), DW_OP_deref]>, upperBound = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_plus_uconst(32), DW_OP_deref]>> | ||
| // CHECK-SAME: #llvm.di_subrange<lowerBound = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_plus_uconst(48), DW_OP_deref]>, upperBound = #llvm.di_expression<[DW_OP_push_object_address, DW_OP_plus_uconst(56), DW_OP_deref]>> | ||
| // CHECK-SAME: dataLocation = <[DW_OP_push_object_address, DW_OP_deref]>> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| //===-- Implementation of totalorderf16 function --------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/math/totalorderf16.h" | ||
| #include "src/__support/FPUtil/BasicOperations.h" | ||
| #include "src/__support/common.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| LLVM_LIBC_FUNCTION(int, totalorderf16, (const float16 *x, const float16 *y)) { | ||
| return static_cast<int>(fputil::totalorder(*x, *y)); | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation of totalordermagf16 function -----------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/math/totalordermagf16.h" | ||
| #include "src/__support/FPUtil/BasicOperations.h" | ||
| #include "src/__support/common.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| LLVM_LIBC_FUNCTION(int, totalordermagf16, | ||
| (const float16 *x, const float16 *y)) { | ||
| return static_cast<int>(fputil::totalordermag(*x, *y)); | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation header for totalorderf16 -----------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_SRC_MATH_TOTALORDERF16_H | ||
| #define LLVM_LIBC_SRC_MATH_TOTALORDERF16_H | ||
|
|
||
| #include "src/__support/macros/properties/types.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| int totalorderf16(const float16 *x, const float16 *y); | ||
|
|
||
| } // namespace LIBC_NAMESPACE | ||
|
|
||
| #endif // LLVM_LIBC_SRC_MATH_TOTALORDERF16_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation header for totalordermagf16 --------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H | ||
| #define LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H | ||
|
|
||
| #include "src/__support/macros/properties/types.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| int totalordermagf16(const float16 *x, const float16 *y); | ||
|
|
||
| } // namespace LIBC_NAMESPACE | ||
|
|
||
| #endif // LLVM_LIBC_SRC_MATH_TOTALORDERMAGF16_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| //===-- Utility class to test flavors of totalordermag ----------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERMAGTEST_H | ||
| #define LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERMAGTEST_H | ||
|
|
||
| #include "test/UnitTest/FEnvSafeTest.h" | ||
| #include "test/UnitTest/FPMatcher.h" | ||
| #include "test/UnitTest/Test.h" | ||
|
|
||
| template <typename T> | ||
| class TotalOrderMagTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { | ||
|
|
||
| DECLARE_SPECIAL_CONSTANTS(T) | ||
|
|
||
| public: | ||
| typedef int (*TotalOrderMagFunc)(const T *, const T *); | ||
|
|
||
| bool funcWrapper(TotalOrderMagFunc func, T x, T y) { | ||
| return func(&x, &y) != 0; | ||
| } | ||
|
|
||
| void testXLesserThanY(TotalOrderMagFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, neg_inf, inf)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(123.38))); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, T(-0.1), T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, T(-123.38), T(0.0))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(-0.1), T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-123.38), T(123.38))); | ||
| } | ||
|
|
||
| void testXGreaterThanY(TotalOrderMagFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, inf, neg_inf)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(-0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(-123.38))); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, T(0.1), T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, T(123.38), T(0.0))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.1), T(-0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(123.38), T(-123.38))); | ||
| } | ||
|
|
||
| void testXEqualToY(TotalOrderMagFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, inf, inf)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_inf, neg_inf)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(-0.0), T(0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(-0.0))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-0.0), T(-0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.1), T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-0.1), T(-0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(123.38), T(123.38))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-123.38), T(-123.38))); | ||
| } | ||
|
|
||
| void testSingleNaN(TotalOrderMagFunc func) { | ||
| EXPECT_FALSE(funcWrapper(func, neg_aNaN, T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, neg_aNaN, T(0.1))); | ||
| EXPECT_FALSE(funcWrapper(func, neg_aNaN, T(123.38))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.1), neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, T(123.38), neg_aNaN)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.1), aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, T(123.38), aNaN)); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, aNaN, T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, T(0.1))); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, T(123.38))); | ||
| } | ||
|
|
||
| void testNaNSigns(TotalOrderMagFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, neg_aNaN, sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, sNaN)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, aNaN, neg_aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, neg_sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, neg_sNaN)); | ||
| } | ||
|
|
||
| void testQuietVsSignalingNaN(TotalOrderMagFunc func) { | ||
| EXPECT_FALSE(funcWrapper(func, neg_aNaN, neg_sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, sNaN)); | ||
| } | ||
|
|
||
| void testNaNPayloads(TotalOrderMagFunc func) { | ||
| T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val(); | ||
| T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val(); | ||
| T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val(); | ||
| T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val(); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, aNaN, aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, snan_123)); | ||
| EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, snan_123, sNaN)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_qnan_123)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_snan_123)); | ||
| EXPECT_FALSE(funcWrapper(func, neg_qnan_123, neg_aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, neg_snan_123, neg_sNaN)); | ||
| } | ||
| }; | ||
|
|
||
| #define LIST_TOTALORDERMAG_TESTS(T, func) \ | ||
| using LlvmLibcTotalOrderMagTest = TotalOrderMagTestTemplate<T>; \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, XLesserThanY) { testXLesserThanY(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, XGreaterThanY) { \ | ||
| testXGreaterThanY(&func); \ | ||
| } \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, XEqualToY) { testXEqualToY(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, SingleNaN) { testSingleNaN(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, NaNSigns) { testNaNSigns(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, QuietVsSignalingNaN) { \ | ||
| testQuietVsSignalingNaN(&func); \ | ||
| } \ | ||
| TEST_F(LlvmLibcTotalOrderMagTest, NaNPayloads) { testNaNPayloads(&func); } | ||
|
|
||
| #endif // LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERMAGTEST_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,138 @@ | ||
| //===-- Utility class to test different flavors of totalorder ---*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERTEST_H | ||
| #define LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERTEST_H | ||
|
|
||
| #include "test/UnitTest/FEnvSafeTest.h" | ||
| #include "test/UnitTest/FPMatcher.h" | ||
| #include "test/UnitTest/Test.h" | ||
|
|
||
| template <typename T> | ||
| class TotalOrderTestTemplate : public LIBC_NAMESPACE::testing::FEnvSafeTest { | ||
|
|
||
| DECLARE_SPECIAL_CONSTANTS(T) | ||
|
|
||
| public: | ||
| typedef int (*TotalOrderFunc)(const T *, const T *); | ||
|
|
||
| bool funcWrapper(TotalOrderFunc func, T x, T y) { return func(&x, &y) != 0; } | ||
|
|
||
| void testXLesserThanY(TotalOrderFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, neg_inf, inf)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(123.38))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(-0.1), T(0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-123.38), T(0.0))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(-0.1), T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-123.38), T(123.38))); | ||
| } | ||
|
|
||
| void testXGreaterThanY(TotalOrderFunc func) { | ||
| EXPECT_FALSE(funcWrapper(func, inf, neg_inf)); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, T(0.0), T(-0.1))); | ||
| EXPECT_FALSE(funcWrapper(func, T(0.0), T(-123.38))); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, T(0.1), T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, T(123.38), T(0.0))); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, T(0.1), T(-0.1))); | ||
| EXPECT_FALSE(funcWrapper(func, T(123.38), T(-123.38))); | ||
| } | ||
|
|
||
| void testXEqualToY(TotalOrderFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, inf, inf)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_inf, neg_inf)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(-0.0), T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, T(0.0), T(-0.0))); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), T(0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-0.0), T(-0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.1), T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-0.1), T(-0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, T(123.38), T(123.38))); | ||
| EXPECT_TRUE(funcWrapper(func, T(-123.38), T(-123.38))); | ||
| } | ||
|
|
||
| void testSingleNaN(TotalOrderFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, T(0.0))); | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, T(0.1))); | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, T(123.38))); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, T(0.0), neg_aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, T(0.1), neg_aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, T(123.38), neg_aNaN)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, T(0.0), aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, T(0.1), aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, T(123.38), aNaN)); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, aNaN, T(0.0))); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, T(0.1))); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, T(123.38))); | ||
| } | ||
|
|
||
| void testNaNSigns(TotalOrderFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, sNaN)); | ||
|
|
||
| EXPECT_FALSE(funcWrapper(func, aNaN, neg_aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, neg_sNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, sNaN, neg_aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, sNaN, neg_sNaN)); | ||
| } | ||
|
|
||
| void testQuietVsSignalingNaN(TotalOrderFunc func) { | ||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_sNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, neg_sNaN, neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, aNaN, sNaN)); | ||
| } | ||
|
|
||
| void testNaNPayloads(TotalOrderFunc func) { | ||
| T qnan_123 = FPBits::quiet_nan(Sign::POS, 0x123).get_val(); | ||
| T neg_qnan_123 = FPBits::quiet_nan(Sign::NEG, 0x123).get_val(); | ||
| T snan_123 = FPBits::signaling_nan(Sign::POS, 0x123).get_val(); | ||
| T neg_snan_123 = FPBits::signaling_nan(Sign::NEG, 0x123).get_val(); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, aNaN, aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, sNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, aNaN, qnan_123)); | ||
| EXPECT_TRUE(funcWrapper(func, sNaN, snan_123)); | ||
| EXPECT_FALSE(funcWrapper(func, qnan_123, aNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, snan_123, sNaN)); | ||
|
|
||
| EXPECT_TRUE(funcWrapper(func, neg_aNaN, neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_sNaN, neg_sNaN)); | ||
| EXPECT_FALSE(funcWrapper(func, neg_aNaN, neg_qnan_123)); | ||
| EXPECT_FALSE(funcWrapper(func, neg_sNaN, neg_snan_123)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_qnan_123, neg_aNaN)); | ||
| EXPECT_TRUE(funcWrapper(func, neg_snan_123, neg_sNaN)); | ||
| } | ||
| }; | ||
|
|
||
| #define LIST_TOTALORDER_TESTS(T, func) \ | ||
| using LlvmLibcTotalOrderTest = TotalOrderTestTemplate<T>; \ | ||
| TEST_F(LlvmLibcTotalOrderTest, XLesserThanY) { testXLesserThanY(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderTest, XGreaterThanY) { testXGreaterThanY(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderTest, XEqualToY) { testXEqualToY(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderTest, SingleNaN) { testSingleNaN(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderTest, NaNSigns) { testNaNSigns(&func); } \ | ||
| TEST_F(LlvmLibcTotalOrderTest, QuietVsSignalingNaN) { \ | ||
| testQuietVsSignalingNaN(&func); \ | ||
| } \ | ||
| TEST_F(LlvmLibcTotalOrderTest, NaNPayloads) { testNaNPayloads(&func); } | ||
|
|
||
| #endif // LIBC_TEST_SRC_MATH_SMOKE_TOTALORDERTEST_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| //===-- Unittests for totalorderf16 ---------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "TotalOrderTest.h" | ||
|
|
||
| #include "src/math/totalorderf16.h" | ||
|
|
||
| LIST_TOTALORDER_TESTS(float16, LIBC_NAMESPACE::totalorderf16) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| //===-- Unittests for totalordermagf16 ------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "TotalOrderMagTest.h" | ||
|
|
||
| #include "src/math/totalordermagf16.h" | ||
|
|
||
| LIST_TOTALORDERMAG_TESTS(float16, LIBC_NAMESPACE::totalordermagf16) |