From eb2251ff651ab5e512fcf197b45c31496ad674bd Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Thu, 2 Nov 2017 12:48:48 +0000 Subject: Fix clang-format CLion integration bug. CLion's Sax parser threw this error: Failed to parse clang-format XML replacements. Input: [...] [org.xml.sax.SAXParseException; lineNumber: 2; columnNumber: 66; Open quote is expected for attribute "line" associated with an element type "replacements".] Patch by Justine Tunney (jart@google.com)! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317205 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/clang-format/ClangFormat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/clang-format/ClangFormat.cpp b/tools/clang-format/ClangFormat.cpp index e169b9e585..b7179ffd64 100644 --- a/tools/clang-format/ClangFormat.cpp +++ b/tools/clang-format/ClangFormat.cpp @@ -289,7 +289,7 @@ static bool format(StringRef FileName) { "xml:space='preserve' incomplete_format='" << (Status.FormatComplete ? "false" : "true") << "'"; if (!Status.FormatComplete) - outs() << " line=" << Status.Line; + outs() << " line='" << Status.Line << "'"; outs() << ">\n"; if (Cursor.getNumOccurrences() != 0) outs() << "" -- cgit v1.2.3 From 8148ea17f5b960f0cb6457b9e4906da119f3b1f8 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Thu, 2 Nov 2017 13:30:42 +0000 Subject: [OpenMP] Extend "Avoid VLAs for reduction" optimization to VLAs as base We can generate constant sized arrays whenever the array section has constant length, even if the base expression itself is a VLA. Differential Revision: https://reviews.llvm.org/D39504 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317207 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOpenMP.cpp | 2 +- test/OpenMP/for_reduction_codegen.cpp | 58 +++++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index 941ac75fa6..243c6ed5f4 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -9711,7 +9711,7 @@ static bool ActOnOMPReductionKindClause( } if ((OASE && !ConstantLengthOASE) || - (!ASE && + (!OASE && !ASE && D->getType().getNonReferenceType()->isVariablyModifiedType())) { // For arrays/array sections only: // Create pseudo array type for private copy. The size for this array will diff --git a/test/OpenMP/for_reduction_codegen.cpp b/test/OpenMP/for_reduction_codegen.cpp index ac4c6ffcac..3f014a4530 100644 --- a/test/OpenMP/for_reduction_codegen.cpp +++ b/test/OpenMP/for_reduction_codegen.cpp @@ -207,6 +207,11 @@ int main() { #pragma omp for reduction(+:arr) reduction(&:arrs) for (int i = 0; i < 10; ++i) ++arr[1][i]; + // arr is a VLA, but the array section has constant length so we can generate a constant sized array! +#pragma omp parallel +#pragma omp for reduction(+:arr[1][0:2]) + for (int i = 0; i < 10; ++i) + ++arr[1][i]; #pragma omp parallel #pragma omp for reduction(& : var2[0 : 5][1 : 6]) for (int i = 0; i < 10; ++i) @@ -254,15 +259,16 @@ int main() { // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 6, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, float*, [[S_FLOAT_TY]]*, [[S_FLOAT_TY]]*, float*, [2 x i32]*, [4 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 5, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, i64, i64, i32*, [2 x i32]*, [10 x [4 x [[S_FLOAT_TY]]]]*)* [[MAIN_MICROTASK1:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 4, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, i64, i64, i32*, [10 x [4 x [[S_FLOAT_TY]]]]*)* [[MAIN_MICROTASK2:@.+]] to void -// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)* [[MAIN_MICROTASK3:@.+]] to void +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 3, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, i64, i64, i32*)* [[MAIN_MICROTASK3:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)* [[MAIN_MICROTASK4:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)* [[MAIN_MICROTASK5:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)* [[MAIN_MICROTASK6:@.+]] to void -// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [5 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK7:@.+]] to void -// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [4 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK8:@.+]] to void +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [[S_FLOAT_TY]]***)* [[MAIN_MICROTASK7:@.+]] to void +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [5 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK8:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [4 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK9:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [4 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK10:@.+]] to void // CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [4 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK11:@.+]] to void +// CHECK: call void (%{{.+}}*, i{{[0-9]+}}, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)*, ...) @__kmpc_fork_call(%{{.+}}* @{{.+}}, i{{[0-9]+}} 1, void (i{{[0-9]+}}*, i{{[0-9]+}}*, ...)* bitcast (void (i{{[0-9]+}}*, i{{[0-9]+}}*, [4 x [[S_FLOAT_TY]]]*)* [[MAIN_MICROTASK12:@.+]] to void // CHECK: = call {{.*}}i{{.+}} [[TMAIN_INT_42:@.+]]() // CHECK: call {{.*}} [[S_FLOAT_TY_DESTR:@.+]]([[S_FLOAT_TY]]* // CHECK: ret @@ -915,7 +921,35 @@ int main() { // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK3]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK3]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, i32* {{.*}} %{{.+}}) + +// CHECK: [[VLA1_ORIG_ADDR:%.+]] = alloca i64 +// CHECK: [[VLA2_ORIG_ADDR:%.+]] = alloca i64 +// CHECK: [[ARR_ORIG_ADDR:%.+]] = alloca i32*, +// CHECK: [[ARR_PRIV:%.+]] = alloca [1 x [2 x i32]], + +// Reduction list for runtime. +// CHECK: [[RED_LIST:%.+]] = alloca [1 x i8*], + +// CHECK: store i{{[0-9]+}}* [[GTID_ADDR]], i{{[0-9]+}}** [[GTID_ADDR_ADDR:%.+]], +// CHECK: [[VLA1:%.+]] = load i64, i64* [[VLA1_ORIG_ADDR]] +// CHECK: [[VLA2:%.+]] = load i64, i64* [[VLA2_ORIG_ADDR]] +// CHECK: [[ARR_ORIG:%.+]] = load i32*, i32** [[ARR_ORIG_ADDR]], + +// CHECK: [[LOW_OFFSET:%.+]] = mul nsw i64 1, [[VLA2]] +// CHECK: [[ARRIDX:%.+]] = getelementptr inbounds i32, i32* [[ARR_ORIG]], i64 [[LOW_OFFSET]] +// CHECK: [[LOW:%.+]] = getelementptr inbounds i32, i32* [[ARRIDX]], i64 0 + +// CHECK: [[START:%.+]] = ptrtoint i32* [[ARR_ORIG]] to i64 +// CHECK: [[LOW_BOUND:%.+]] = ptrtoint i32* [[LOW]] to i64 +// CHECK: [[OFFSET_BYTES:%.+]] = sub i64 [[START]], [[LOW_BOUND]] +// CHECK: [[OFFSET:%.+]] = sdiv exact i64 [[OFFSET_BYTES]], ptrtoint (i32* getelementptr (i32, i32* null, i32 1) to i64) +// CHECK: [[PSEUDO_ARR_PRIV:%.+]] = getelementptr [1 x [2 x i32]], [1 x [2 x i32]]* [[ARR_PRIV]], i64 [[OFFSET]] +// CHECK: [[ARR_PRIV:%.+]] = bitcast [1 x [2 x i32]]* [[PSEUDO_ARR_PRIV]] to i32* + +// CHECK: ret void + +// CHECK: define internal void [[MAIN_MICROTASK4]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) // CHECK: [[VAR2_ORIG_ADDR:%.+]] = alloca [[S_FLOAT_TY]]***, @@ -943,7 +977,7 @@ int main() { // CHECK: store [[S_FLOAT_TY]]* [[PSEUDO_VAR2_PRIV]], [[S_FLOAT_TY]]** [[REF]] // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK4]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK5]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) // CHECK: [[VAR2_ORIG_ADDR:%.+]] = alloca [[S_FLOAT_TY]]***, // CHECK: [[VAR2_PRIV:%.+]] = alloca [1 x [6 x [[S_FLOAT_TY]]]], @@ -972,7 +1006,7 @@ int main() { // CHECK: store [[S_FLOAT_TY]]* [[VAR2_PRIV]], [[S_FLOAT_TY]]** [[REF]] // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK5]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK6]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) // CHECK: [[VAR2_ORIG_ADDR:%.+]] = alloca [[S_FLOAT_TY]]***, // CHECK: [[VAR2_PRIV:%.+]] = alloca [1 x [6 x [[S_FLOAT_TY]]]], @@ -1001,7 +1035,7 @@ int main() { // CHECK: store [[S_FLOAT_TY]]* [[VAR2_PRIV]], [[S_FLOAT_TY]]** [[REF]] // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK6]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK7]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [[S_FLOAT_TY]]*** dereferenceable(8) %{{.+}}) // CHECK: [[VAR2_ORIG_ADDR:%.+]] = alloca [[S_FLOAT_TY]]***, // CHECK: [[VAR2_PRIV:%.+]] = alloca [[S_FLOAT_TY]], @@ -1029,7 +1063,7 @@ int main() { // CHECK: store [[S_FLOAT_TY]]* [[PSEUDO_VAR2_PRIV]], [[S_FLOAT_TY]]** [[REF]] // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK7]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [5 x [[S_FLOAT_TY]]]* dereferenceable(20) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK8]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [5 x [[S_FLOAT_TY]]]* dereferenceable(20) %{{.+}}) // CHECK: [[VVAR2_ORIG_ADDR:%.+]] = alloca [5 x [[S_FLOAT_TY]]]*, // CHECK: [[VVAR2_PRIV:%.+]] = alloca [5 x [[S_FLOAT_TY]]], @@ -1049,7 +1083,7 @@ int main() { // CHECK: [[PSEUDO_VVAR2_PRIV:%.+]] = getelementptr [5 x [[S_FLOAT_TY]]], [5 x [[S_FLOAT_TY]]]* [[VVAR2_PRIV]], i64 [[OFFSET]] // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK8]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK9]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) // CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [4 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR3_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]], @@ -1079,7 +1113,7 @@ int main() { // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK9]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK10]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) // CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [4 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR3_PRIV:%.+]] = alloca [2 x [[S_FLOAT_TY]]], @@ -1109,7 +1143,7 @@ int main() { // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK10]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK11]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) // CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [4 x [[S_FLOAT_TY]]]*, @@ -1140,7 +1174,7 @@ int main() { // CHECK: ret void -// CHECK: define internal void [[MAIN_MICROTASK11]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) +// CHECK: define internal void [[MAIN_MICROTASK12]](i{{[0-9]+}}* noalias [[GTID_ADDR:%.+]], i{{[0-9]+}}* noalias %{{.+}}, [4 x [[S_FLOAT_TY]]]* dereferenceable(16) %{{.+}}) // CHECK: [[VAR3_ORIG_ADDR:%.+]] = alloca [4 x [[S_FLOAT_TY]]]*, // CHECK: [[VAR3_PRIV:%.+]] = alloca [4 x [[S_FLOAT_TY]]], -- cgit v1.2.3 From e70ad5241cb2dd0fe883ffacdfa8a839fce108ce Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 2 Nov 2017 14:25:34 +0000 Subject: [OPENMP] Fix PR35156: Get correct thread id with windows exceptions. If the thread id is requested in windows mode within funclets, we may generate incorrect function call that could lead to broken codegen. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317208 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 14 +++++++----- test/OpenMP/critical_codegen.cpp | 2 +- test/OpenMP/for_codegen.cpp | 2 +- test/OpenMP/for_simd_codegen.cpp | 2 +- test/OpenMP/master_codegen.cpp | 2 +- test/OpenMP/openmp_win_codegen.cpp | 38 +++++++++++++++++++++++++++++++ test/OpenMP/parallel_for_codegen.cpp | 2 +- test/OpenMP/parallel_for_simd_codegen.cpp | 2 +- test/OpenMP/parallel_sections_codegen.cpp | 2 +- test/OpenMP/sections_codegen.cpp | 2 +- test/OpenMP/single_codegen.cpp | 2 +- test/OpenMP/taskgroup_codegen.cpp | 2 +- 12 files changed, 56 insertions(+), 16 deletions(-) create mode 100644 test/OpenMP/openmp_win_codegen.cpp diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 35929af95e..779617adc2 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1451,7 +1451,8 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, return ThreadID; } // If exceptions are enabled, do not use parameter to avoid possible crash. - if (!CGF.getInvokeDest()) { + if (!CGF.getInvokeDest() || + CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { if (auto *OMPRegionInfo = dyn_cast_or_null(CGF.CapturedStmtInfo)) { if (OMPRegionInfo->getThreadIDVariable()) { @@ -1475,12 +1476,13 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, // function. CGBuilderTy::InsertPointGuard IPG(CGF.Builder); CGF.Builder.SetInsertPoint(CGF.AllocaInsertPt); - ThreadID = - CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), - emitUpdateLocation(CGF, Loc)); + auto *Call = CGF.Builder.CreateCall( + createRuntimeFunction(OMPRTL__kmpc_global_thread_num), + emitUpdateLocation(CGF, Loc)); + Call->setCallingConv(CGF.getRuntimeCC()); auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); - Elem.second.ThreadID = ThreadID; - return ThreadID; + Elem.second.ThreadID = Call; + return Call; } void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { diff --git a/test/OpenMP/critical_codegen.cpp b/test/OpenMP/critical_codegen.cpp index 964c91f45a..f4e449a223 100644 --- a/test/OpenMP/critical_codegen.cpp +++ b/test/OpenMP/critical_codegen.cpp @@ -78,7 +78,7 @@ void critical_ref(S &s) { void parallel_critical() { #pragma omp parallel #pragma omp critical - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: call void @__kmpc_critical({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] // TERM_DEBUG: invoke void {{.*}}foo{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], diff --git a/test/OpenMP/for_codegen.cpp b/test/OpenMP/for_codegen.cpp index 0d5972f7d0..9ea167fb1f 100644 --- a/test/OpenMP/for_codegen.cpp +++ b/test/OpenMP/for_codegen.cpp @@ -355,7 +355,7 @@ int foo() {return 0;}; void parallel_for(float *a) { #pragma omp parallel #pragma omp for schedule(static, 5) - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: call void @__kmpc_for_static_init_4u({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] // TERM_DEBUG: invoke i32 {{.*}}foo{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], diff --git a/test/OpenMP/for_simd_codegen.cpp b/test/OpenMP/for_simd_codegen.cpp index e33bfe4a57..89f779db33 100644 --- a/test/OpenMP/for_simd_codegen.cpp +++ b/test/OpenMP/for_simd_codegen.cpp @@ -673,7 +673,7 @@ int bar() {return 0;}; void parallel_simd(float *a) { #pragma omp parallel #pragma omp for simd - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: invoke i32 {{.*}}bar{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], // TERM_DEBUG-NOT: __kmpc_global_thread_num diff --git a/test/OpenMP/master_codegen.cpp b/test/OpenMP/master_codegen.cpp index d61b476756..ad92a13e14 100644 --- a/test/OpenMP/master_codegen.cpp +++ b/test/OpenMP/master_codegen.cpp @@ -49,7 +49,7 @@ int main() { void parallel_master() { #pragma omp parallel #pragma omp master - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: call i32 @__kmpc_master({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] // TERM_DEBUG: invoke void {{.*}}foo{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], diff --git a/test/OpenMP/openmp_win_codegen.cpp b/test/OpenMP/openmp_win_codegen.cpp new file mode 100644 index 0000000000..cdad7e29cc --- /dev/null +++ b/test/OpenMP/openmp_win_codegen.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s +// REQUIRES: x86-registered-target +// expected-no-diagnostics + +void foo(); +void bar(); + +// CHECK-LABEL: @main +int main() { + // CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*)) +#pragma omp parallel + { + try { + foo(); + } catch (int t) { +#pragma omp critical + { + bar(); + }; + } + }; + // CHECK: ret i32 0 + return 0; +} + +// CHECK: define internal void [[OUTLINED]]( +// CHECK: [[GID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* @0) +// CHECK: invoke void @{{.+}}foo +// CHECK: catchswitch within +// CHECK: catchpad within +// CHECK: call void @__kmpc_critical(%ident_t* @0, i32 [[GID]], +// CHECK: invoke void @{{.+}}bar +// CHECK: call void @__kmpc_end_critical(%ident_t* @0, i32 [[GID]], +// CHECK: catchret from +// CHECK: cleanuppad within +// CHECK: call void @__kmpc_end_critical(%ident_t* @0, i32 [[GID]], +// CHECK: cleanupret from + diff --git a/test/OpenMP/parallel_for_codegen.cpp b/test/OpenMP/parallel_for_codegen.cpp index bc04532bd1..1773619bce 100644 --- a/test/OpenMP/parallel_for_codegen.cpp +++ b/test/OpenMP/parallel_for_codegen.cpp @@ -348,7 +348,7 @@ int foo() {return 0;}; void parallel_for(float *a, int n) { float arr[n]; #pragma omp parallel for schedule(static, 5) private(arr) - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: call void @__kmpc_for_static_init_4u({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] // TERM_DEBUG: invoke i32 {{.*}}foo{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], diff --git a/test/OpenMP/parallel_for_simd_codegen.cpp b/test/OpenMP/parallel_for_simd_codegen.cpp index 9112635855..369ea17844 100644 --- a/test/OpenMP/parallel_for_simd_codegen.cpp +++ b/test/OpenMP/parallel_for_simd_codegen.cpp @@ -668,7 +668,7 @@ int bar() {return 0;}; // TERM_DEBUG-LABEL: parallel_simd void parallel_simd(float *a) { #pragma omp parallel for simd - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: invoke i32 {{.*}}bar{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], // TERM_DEBUG-NOT: __kmpc_global_thread_num diff --git a/test/OpenMP/parallel_sections_codegen.cpp b/test/OpenMP/parallel_sections_codegen.cpp index afbc6e4d5e..a261473036 100644 --- a/test/OpenMP/parallel_sections_codegen.cpp +++ b/test/OpenMP/parallel_sections_codegen.cpp @@ -74,7 +74,7 @@ int main() { // CHECK-LABEL: tmain // CHECK: call void {{.*}} @__kmpc_fork_call( -// CHECK: __kmpc_global_thread_num +// CHECK-NOT: __kmpc_global_thread_num // CHECK: call void @__kmpc_for_static_init_4( // CHECK: invoke void @{{.*}}foo{{.*}}() // CHECK-NEXT: unwind label %[[TERM_LPAD:.+]] diff --git a/test/OpenMP/sections_codegen.cpp b/test/OpenMP/sections_codegen.cpp index 0ed87e4035..94ded37db9 100644 --- a/test/OpenMP/sections_codegen.cpp +++ b/test/OpenMP/sections_codegen.cpp @@ -84,7 +84,7 @@ int main() { // CHECK-LABEL: tmain // CHECK: call void {{.*}} @__kmpc_fork_call( -// CHECK: __kmpc_global_thread_num +// CHECK-NOT: __kmpc_global_thread_num // CHECK: call void @__kmpc_for_static_init_4( // CHECK: invoke void @{{.*}}foo{{.*}}() // CHECK-NEXT: unwind label %[[TERM_LPAD:.+]] diff --git a/test/OpenMP/single_codegen.cpp b/test/OpenMP/single_codegen.cpp index 4feb3bdac3..892e160324 100644 --- a/test/OpenMP/single_codegen.cpp +++ b/test/OpenMP/single_codegen.cpp @@ -190,7 +190,7 @@ int main() { void parallel_single() { #pragma omp parallel #pragma omp single - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: call i32 @__kmpc_single({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] // TERM_DEBUG: invoke void {{.*}}foo{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], diff --git a/test/OpenMP/taskgroup_codegen.cpp b/test/OpenMP/taskgroup_codegen.cpp index 3dd41a1f82..4b7d89e703 100644 --- a/test/OpenMP/taskgroup_codegen.cpp +++ b/test/OpenMP/taskgroup_codegen.cpp @@ -40,7 +40,7 @@ int main() { void parallel_taskgroup() { #pragma omp parallel #pragma omp taskgroup - // TERM_DEBUG: __kmpc_global_thread_num + // TERM_DEBUG-NOT: __kmpc_global_thread_num // TERM_DEBUG: call void @__kmpc_taskgroup({{.+}}), !dbg [[DBG_LOC_START:![0-9]+]] // TERM_DEBUG: invoke void {{.*}}foo{{.*}}() // TERM_DEBUG: unwind label %[[TERM_LPAD:.+]], -- cgit v1.2.3 From 822590af31ad4856feffc442c124ae4730667d4c Mon Sep 17 00:00:00 2001 From: Jan Korous Date: Thu, 2 Nov 2017 16:37:00 +0000 Subject: Fix comment typo git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317216 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseExprCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index a640439b8f..ce6aa64de6 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -249,7 +249,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, if (Tok.is(tok::code_completion)) { // Code completion for a nested-name-specifier, where the code - // code completion token follows the '::'. + // completion token follows the '::'. Actions.CodeCompleteQualifiedId(getCurScope(), SS, EnteringContext); // Include code completion token into the range of the scope otherwise // when we try to annotate the scope tokens the dangling code completion -- cgit v1.2.3 From c5dac14767566df828dff84280933ba92babab00 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 2 Nov 2017 17:06:05 +0000 Subject: [CodeGen] add builtin attr tests to show errno-related diffs; NFC git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317220 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/builtin-errno.c | 777 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 777 insertions(+) create mode 100644 test/CodeGen/builtin-errno.c diff --git a/test/CodeGen/builtin-errno.c b/test/CodeGen/builtin-errno.c new file mode 100644 index 0000000000..43fdef6973 --- /dev/null +++ b/test/CodeGen/builtin-errno.c @@ -0,0 +1,777 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s | FileCheck %s -check-prefix=NO__ERRNO +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO + +// Test math, complex, and other builtin attributes to see how errno affects the resulting codegen. + + +double *d; +float f; +float *fp; +long double *l; +int *i; +const char *c; + +void foo() { + __builtin_abs(f); __builtin_labs(f); __builtin_llabs(f); + +// NO__ERRNO-NOT: .abs +// NO__ERRNO-NOT: .labs +// NO__ERRNO-NOT: .llabs +// NO__ERRNO-NOT: @abs +// NO__ERRNO-NOT: @labs +// NO__ERRNO-NOT: @llabs +// HAS_ERRNO-NOT: .abs +// HAS_ERRNO-NOT: .labs +// HAS_ERRNO-NOT: .llabs +// HAS_ERRNO-NOT: @abs +// HAS_ERRNO-NOT: @labs +// HAS_ERRNO-NOT: @llabs + + __builtin_atan2(f,f); __builtin_atan2f(f,f) ; __builtin_atan2l(f, f); + +// NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]] +// NO__ERRNO: declare float @atan2f(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]] +// HAS_ERRNO: declare float @atan2f(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]] + + __builtin_copysign(f,f); __builtin_copysignf(f,f);__builtin_copysignl(f,f); + +// NO__ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// NO__ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.copysign.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// HAS_ERRNO: declare float @llvm.copysign.f32(float, float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.copysign.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_fabs(f); __builtin_fabsf(f); __builtin_fabsl(f); + +// NO__ERRNO: declare double @llvm.fabs.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.fabs.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_fmod(f,f); __builtin_fmodf(f,f); __builtin_fmodl(f,f); + +// NO__ERRNO-NOT: .fmod +// NO__ERRNO-NOT: @fmod +// HAS_ERRNO-NOT: .fmod +// HAS_ERRNO-NOT: @fmod + + __builtin_frexp(f,i); __builtin_frexpf(f,i); __builtin_frexpl(f,i); + +// NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]] +// NO__ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]] +// HAS_ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] + + __builtin_huge_val(); __builtin_huge_valf(); __builtin_huge_vall(); + +// NO__ERRNO-NOT: .huge +// NO__ERRNO-NOT: @huge +// HAS_ERRNO-NOT: .huge +// HAS_ERRNO-NOT: @huge + + __builtin_inf(); __builtin_inff(); __builtin_infl(); + +// NO__ERRNO-NOT: .inf +// NO__ERRNO-NOT: @inf +// HAS_ERRNO-NOT: .inf +// HAS_ERRNO-NOT: @inf + + __builtin_ldexp(f,f); __builtin_ldexpf(f,f); __builtin_ldexpl(f,f); + +// NO__ERRNO: declare double @ldexp(double, i32) [[READNONE]] +// NO__ERRNO: declare float @ldexpf(float, i32) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[READNONE]] +// HAS_ERRNO: declare double @ldexp(double, i32) [[READNONE]] +// HAS_ERRNO: declare float @ldexpf(float, i32) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[READNONE]] + + __builtin_modf(f,d); __builtin_modff(f,fp); __builtin_modfl(f,l); + +// NO__ERRNO: declare double @modf(double, double*) [[NOT_READNONE]] +// NO__ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]] +// HAS_ERRNO: declare double @modf(double, double*) [[NOT_READNONE]] +// HAS_ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]] + + __builtin_nan(c); __builtin_nanf(c); __builtin_nanl(c); + +// NO__ERRNO: declare double @nan(i8*) [[READNONE]] +// NO__ERRNO: declare float @nanf(i8*) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] +// HAS_ERRNO: declare double @nan(i8*) [[READNONE:#[0-9]+]] +// HAS_ERRNO: declare float @nanf(i8*) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READNONE]] + + __builtin_nans(c); __builtin_nansf(c); __builtin_nansl(c); + +// NO__ERRNO: declare double @nans(i8*) [[READNONE]] +// NO__ERRNO: declare float @nansf(i8*) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] +// HAS_ERRNO: declare double @nans(i8*) [[READNONE]] +// HAS_ERRNO: declare float @nansf(i8*) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @nansl(i8*) [[READNONE]] + + __builtin_pow(f,f); __builtin_powf(f,f); __builtin_powl(f,f); + +// NO__ERRNO: declare double @llvm.pow.f64(double, double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.pow.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.pow.f64(double, double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.pow.f32(float, float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_powi(f,f); __builtin_powif(f,f); __builtin_powil(f,f); + +// NO__ERRNO: declare double @llvm.powi.f64(double, i32) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.powi.f32(float, i32) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.powi.f80(x86_fp80, i32) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.powi.f64(double, i32) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.powi.f32(float, i32) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.powi.f80(x86_fp80, i32) [[READNONE_INTRINSIC]] + + /* math */ + __builtin_acos(f); __builtin_acosf(f); __builtin_acosl(f); + +// NO__ERRNO: declare double @acos(double) [[READNONE]] +// NO__ERRNO: declare float @acosf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @acosl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @acos(double) [[READNONE]] +// HAS_ERRNO: declare float @acosf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @acosl(x86_fp80) [[READNONE]] + + __builtin_acosh(f); __builtin_acoshf(f); __builtin_acoshl(f); + +// NO__ERRNO: declare double @acosh(double) [[READNONE]] +// NO__ERRNO: declare float @acoshf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @acosh(double) [[READNONE]] +// HAS_ERRNO: declare float @acoshf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[READNONE]] + + __builtin_asin(f); __builtin_asinf(f); __builtin_asinl(f); + +// NO__ERRNO: declare double @asin(double) [[READNONE]] +// NO__ERRNO: declare float @asinf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @asinl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @asin(double) [[READNONE]] +// HAS_ERRNO: declare float @asinf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @asinl(x86_fp80) [[READNONE]] + + __builtin_asinh(f); __builtin_asinhf(f); __builtin_asinhl(f); + +// NO__ERRNO: declare double @asinh(double) [[READNONE]] +// NO__ERRNO: declare float @asinhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @asinh(double) [[READNONE]] +// HAS_ERRNO: declare float @asinhf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[READNONE]] + + __builtin_atan(f); __builtin_atanf(f); __builtin_atanl(f); + +// NO__ERRNO: declare double @atan(double) [[READNONE]] +// NO__ERRNO: declare float @atanf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @atanl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atan(double) [[READNONE]] +// HAS_ERRNO: declare float @atanf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @atanl(x86_fp80) [[READNONE]] + + __builtin_atanh(f); __builtin_atanhf(f); __builtin_atanhl(f); + +// NO__ERRNO: declare double @atanh(double) [[READNONE]] +// NO__ERRNO: declare float @atanhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atanh(double) [[READNONE]] +// HAS_ERRNO: declare float @atanhf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[READNONE]] + + __builtin_cbrt(f); __builtin_cbrtf(f); __builtin_cbrtl(f); + +// NO__ERRNO: declare double @cbrt(double) [[READNONE]] +// NO__ERRNO: declare float @cbrtf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cbrt(double) [[READNONE]] +// HAS_ERRNO: declare float @cbrtf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] + + __builtin_ceil(f); __builtin_ceilf(f); __builtin_ceill(f); + +// NO__ERRNO: declare double @llvm.ceil.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.ceil.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.ceil.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.ceil.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.ceil.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.ceil.f80(x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_cos(f); __builtin_cosf(f); __builtin_cosl(f); + +// NO__ERRNO: declare double @cos(double) [[READNONE]] +// NO__ERRNO: declare float @cosf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cosl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cos(double) [[READNONE]] +// HAS_ERRNO: declare float @cosf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @cosl(x86_fp80) [[READNONE]] + + __builtin_cosh(f); __builtin_coshf(f); __builtin_coshl(f); + +// NO__ERRNO: declare double @cosh(double) [[READNONE]] +// NO__ERRNO: declare float @coshf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @coshl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cosh(double) [[READNONE]] +// HAS_ERRNO: declare float @coshf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @coshl(x86_fp80) [[READNONE]] + + __builtin_erf(f); __builtin_erff(f); __builtin_erfl(f); + +// NO__ERRNO: declare double @erf(double) [[READNONE]] +// NO__ERRNO: declare float @erff(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @erfl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @erf(double) [[READNONE]] +// HAS_ERRNO: declare float @erff(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @erfl(x86_fp80) [[READNONE]] + + __builtin_erfc(f); __builtin_erfcf(f); __builtin_erfcl(f); + +// NO__ERRNO: declare double @erfc(double) [[READNONE]] +// NO__ERRNO: declare float @erfcf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @erfc(double) [[READNONE]] +// HAS_ERRNO: declare float @erfcf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[READNONE]] + + __builtin_exp(f); __builtin_expf(f); __builtin_expl(f); + +// NO__ERRNO: declare double @exp(double) [[READNONE]] +// NO__ERRNO: declare float @expf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @expl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @exp(double) [[READNONE]] +// HAS_ERRNO: declare float @expf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @expl(x86_fp80) [[READNONE]] + + __builtin_exp2(f); __builtin_exp2f(f); __builtin_exp2l(f); + +// NO__ERRNO: declare double @exp2(double) [[READNONE]] +// NO__ERRNO: declare float @exp2f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @exp2(double) [[READNONE]] +// HAS_ERRNO: declare float @exp2f(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[READNONE]] + + __builtin_expm1(f); __builtin_expm1f(f); __builtin_expm1l(f); + +// NO__ERRNO: declare double @expm1(double) [[READNONE]] +// NO__ERRNO: declare float @expm1f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @expm1(double) [[READNONE]] +// HAS_ERRNO: declare float @expm1f(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[READNONE]] + + __builtin_fdim(f,f); __builtin_fdimf(f,f); __builtin_fdiml(f,f); + +// NO__ERRNO: declare double @fdim(double, double) [[READNONE]] +// NO__ERRNO: declare float @fdimf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fdim(double, double) [[READNONE]] +// HAS_ERRNO: declare float @fdimf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[READNONE]] + + __builtin_floor(f); __builtin_floorf(f); __builtin_floorl(f); + +// NO__ERRNO: declare double @llvm.floor.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.floor.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.floor.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.floor.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.floor.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.floor.f80(x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_fma(f,f,f); __builtin_fmaf(f,f,f); __builtin_fmal(f,f,f); + +// NO__ERRNO: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_fmax(f,f); __builtin_fmaxf(f,f); __builtin_fmaxl(f,f); + +// NO__ERRNO: declare double @llvm.maxnum.f64(double, double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.maxnum.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.maxnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.maxnum.f64(double, double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.maxnum.f32(float, float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.maxnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_fmin(f,f); __builtin_fminf(f,f); __builtin_fminl(f,f); + +// NO__ERRNO: declare double @llvm.minnum.f64(double, double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.minnum.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.minnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.minnum.f64(double, double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.minnum.f32(float, float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.minnum.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_hypot(f,f); __builtin_hypotf(f,f); __builtin_hypotl(f,f); + +// NO__ERRNO: declare double @hypot(double, double) [[READNONE]] +// NO__ERRNO: declare float @hypotf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @hypot(double, double) [[READNONE]] +// HAS_ERRNO: declare float @hypotf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[READNONE]] + + __builtin_ilogb(f); __builtin_ilogbf(f); __builtin_ilogbl(f); + +// NO__ERRNO: declare i32 @ilogb(double) [[READNONE]] +// NO__ERRNO: declare i32 @ilogbf(float) [[READNONE]] +// NO__ERRNO: declare i32 @ilogbl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i32 @ilogb(double) [[READNONE]] +// HAS_ERRNO: declare i32 @ilogbf(float) [[READNONE]] +// HAS_ERRNO: declare i32 @ilogbl(x86_fp80) [[READNONE]] + + __builtin_lgamma(f); __builtin_lgammaf(f); __builtin_lgammal(f); + +// NO__ERRNO: declare double @lgamma(double) [[READNONE]] +// NO__ERRNO: declare float @lgammaf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @lgamma(double) [[READNONE]] +// HAS_ERRNO: declare float @lgammaf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[READNONE]] + + __builtin_llrint(f); __builtin_llrintf(f); __builtin_llrintl(f); + +// NO__ERRNO: declare i64 @llrint(double) [[READNONE]] +// NO__ERRNO: declare i64 @llrintf(float) [[READNONE]] +// NO__ERRNO: declare i64 @llrintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @llrint(double) [[READNONE]] +// HAS_ERRNO: declare i64 @llrintf(float) [[READNONE]] +// HAS_ERRNO: declare i64 @llrintl(x86_fp80) [[READNONE]] + + __builtin_llround(f); __builtin_llroundf(f); __builtin_llroundl(f); + +// NO__ERRNO: declare i64 @llround(double) [[READNONE]] +// NO__ERRNO: declare i64 @llroundf(float) [[READNONE]] +// NO__ERRNO: declare i64 @llroundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @llround(double) [[READNONE]] +// HAS_ERRNO: declare i64 @llroundf(float) [[READNONE]] +// HAS_ERRNO: declare i64 @llroundl(x86_fp80) [[READNONE]] + + __builtin_log(f); __builtin_logf(f); __builtin_logl(f); + +// NO__ERRNO: declare double @log(double) [[READNONE]] +// NO__ERRNO: declare float @logf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @logl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log(double) [[READNONE]] +// HAS_ERRNO: declare float @logf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @logl(x86_fp80) [[READNONE]] + + __builtin_log10(f); __builtin_log10f(f); __builtin_log10l(f); + +// NO__ERRNO: declare double @log10(double) [[READNONE]] +// NO__ERRNO: declare float @log10f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @log10l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log10(double) [[READNONE]] +// HAS_ERRNO: declare float @log10f(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @log10l(x86_fp80) [[READNONE]] + + __builtin_log1p(f); __builtin_log1pf(f); __builtin_log1pl(f); + +// NO__ERRNO: declare double @log1p(double) [[READNONE]] +// NO__ERRNO: declare float @log1pf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log1p(double) [[READNONE]] +// HAS_ERRNO: declare float @log1pf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[READNONE]] + + __builtin_log2(f); __builtin_log2f(f); __builtin_log2l(f); + +// NO__ERRNO: declare double @log2(double) [[READNONE]] +// NO__ERRNO: declare float @log2f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @log2l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log2(double) [[READNONE]] +// HAS_ERRNO: declare float @log2f(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @log2l(x86_fp80) [[READNONE]] + + __builtin_logb(f); __builtin_logbf(f); __builtin_logbl(f); + +// NO__ERRNO: declare double @logb(double) [[READNONE]] +// NO__ERRNO: declare float @logbf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @logbl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @logb(double) [[READNONE]] +// HAS_ERRNO: declare float @logbf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @logbl(x86_fp80) [[READNONE]] + + __builtin_lrint(f); __builtin_lrintf(f); __builtin_lrintl(f); + +// NO__ERRNO: declare i64 @lrint(double) [[READNONE]] +// NO__ERRNO: declare i64 @lrintf(float) [[READNONE]] +// NO__ERRNO: declare i64 @lrintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @lrint(double) [[READNONE]] +// HAS_ERRNO: declare i64 @lrintf(float) [[READNONE]] +// HAS_ERRNO: declare i64 @lrintl(x86_fp80) [[READNONE]] + + __builtin_lround(f); __builtin_lroundf(f); __builtin_lroundl(f); + +// NO__ERRNO: declare i64 @lround(double) [[READNONE]] +// NO__ERRNO: declare i64 @lroundf(float) [[READNONE]] +// NO__ERRNO: declare i64 @lroundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @lround(double) [[READNONE]] +// HAS_ERRNO: declare i64 @lroundf(float) [[READNONE]] +// HAS_ERRNO: declare i64 @lroundl(x86_fp80) [[READNONE]] + + __builtin_nearbyint(f); __builtin_nearbyintf(f); __builtin_nearbyintl(f); + +// NO__ERRNO: declare double @llvm.nearbyint.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.nearbyint.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.nearbyint.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.nearbyint.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.nearbyint.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.nearbyint.f80(x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_nextafter(f,f); __builtin_nextafterf(f,f); __builtin_nextafterl(f,f); + +// NO__ERRNO: declare double @nextafter(double, double) [[READNONE]] +// NO__ERRNO: declare float @nextafterf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nextafter(double, double) [[READNONE]] +// HAS_ERRNO: declare float @nextafterf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[READNONE]] + + __builtin_nexttoward(f,f); __builtin_nexttowardf(f,f);__builtin_nexttowardl(f,f); + +// NO__ERRNO: declare double @nexttoward(double, x86_fp80) [[READNONE]] +// NO__ERRNO: declare float @nexttowardf(float, x86_fp80) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nexttoward(double, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare float @nexttowardf(float, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[READNONE]] + + __builtin_remainder(f,f); __builtin_remainderf(f,f); __builtin_remainderl(f,f); + +// NO__ERRNO: declare double @remainder(double, double) [[READNONE]] +// NO__ERRNO: declare float @remainderf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @remainder(double, double) [[READNONE]] +// HAS_ERRNO: declare float @remainderf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[READNONE]] + + __builtin_remquo(f,f,i); __builtin_remquof(f,f,i); __builtin_remquol(f,f,i); + +// NO__ERRNO: declare double @remquo(double, double, i32*) [[NOT_READNONE]] +// NO__ERRNO: declare float @remquof(float, float, i32*) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @remquol(x86_fp80, x86_fp80, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare double @remquo(double, double, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare float @remquof(float, float, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @remquol(x86_fp80, x86_fp80, i32*) [[NOT_READNONE]] + + __builtin_rint(f); __builtin_rintf(f); __builtin_rintl(f); + +// NO__ERRNO: declare double @llvm.rint.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.rint.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.rint.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.rint.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.rint.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.rint.f80(x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_round(f); __builtin_roundf(f); __builtin_roundl(f); + +// NO__ERRNO: declare double @llvm.round.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.round.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.round.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.round.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.round.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.round.f80(x86_fp80) [[READNONE_INTRINSIC]] + + __builtin_scalbln(f,f); __builtin_scalblnf(f,f); __builtin_scalblnl(f,f); + +// NO__ERRNO: declare double @scalbln(double, i64) [[READNONE]] +// NO__ERRNO: declare float @scalblnf(float, i64) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[READNONE]] +// HAS_ERRNO: declare double @scalbln(double, i64) [[READNONE]] +// HAS_ERRNO: declare float @scalblnf(float, i64) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[READNONE]] + + __builtin_scalbn(f,f); __builtin_scalbnf(f,f); __builtin_scalbnl(f,f); + +// NO__ERRNO: declare double @scalbn(double, i32) [[READNONE]] +// NO__ERRNO: declare float @scalbnf(float, i32) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[READNONE]] +// HAS_ERRNO: declare double @scalbn(double, i32) [[READNONE]] +// HAS_ERRNO: declare float @scalbnf(float, i32) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[READNONE]] + + __builtin_sin(f); __builtin_sinf(f); __builtin_sinl(f); + +// NO__ERRNO: declare double @sin(double) [[READNONE]] +// NO__ERRNO: declare float @sinf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @sinl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sin(double) [[READNONE]] +// HAS_ERRNO: declare float @sinf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @sinl(x86_fp80) [[READNONE]] + + __builtin_sinh(f); __builtin_sinhf(f); __builtin_sinhl(f); + +// NO__ERRNO: declare double @sinh(double) [[READNONE]] +// NO__ERRNO: declare float @sinhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sinh(double) [[READNONE]] +// HAS_ERRNO: declare float @sinhf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[READNONE]] + + __builtin_sqrt(f); __builtin_sqrtf(f); __builtin_sqrtl(f); + +// NO__ERRNO: declare double @sqrt(double) [[READNONE]] +// NO__ERRNO: declare float @sqrtf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sqrt(double) [[READNONE]] +// HAS_ERRNO: declare float @sqrtf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[READNONE]] + + __builtin_tan(f); __builtin_tanf(f); __builtin_tanl(f); + +// NO__ERRNO: declare double @tan(double) [[READNONE]] +// NO__ERRNO: declare float @tanf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @tanl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tan(double) [[READNONE]] +// HAS_ERRNO: declare float @tanf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @tanl(x86_fp80) [[READNONE]] + + __builtin_tanh(f); __builtin_tanhf(f); __builtin_tanhl(f); + +// NO__ERRNO: declare double @tanh(double) [[READNONE]] +// NO__ERRNO: declare float @tanhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tanh(double) [[READNONE]] +// HAS_ERRNO: declare float @tanhf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[READNONE]] + + __builtin_tgamma(f); __builtin_tgammaf(f); __builtin_tgammal(f); + +// NO__ERRNO: declare double @tgamma(double) [[READNONE]] +// NO__ERRNO: declare float @tgammaf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tgamma(double) [[READNONE]] +// HAS_ERRNO: declare float @tgammaf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[READNONE]] + + __builtin_trunc(f); __builtin_truncf(f); __builtin_truncl(f); + +// NO__ERRNO: declare double @llvm.trunc.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.trunc.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.trunc.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.trunc.f64(double) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare float @llvm.trunc.f32(float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.trunc.f80(x86_fp80) [[READNONE_INTRINSIC]] + + /* complex */ + + __builtin_cabs(f); __builtin_cabsf(f); __builtin_cabsl(f); + +// NO__ERRNO: declare double @cabs(double, double) [[READNONE]] +// NO__ERRNO: declare float @cabsf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cabsl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare double @cabs(double, double) [[READNONE]] +// HAS_ERRNO: declare float @cabsf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @cabsl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_cacos(f); __builtin_cacosf(f); __builtin_cacosl(f); + +// NO__ERRNO: declare { double, double } @cacos(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cacosf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cacosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cacos(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cacosf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cacosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_cacosh(f); __builtin_cacoshf(f); __builtin_cacoshl(f); + +// NO__ERRNO: declare { double, double } @cacosh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cacoshf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cacoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cacosh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cacoshf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cacoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_carg(f); __builtin_cargf(f); __builtin_cargl(f); + +// NO__ERRNO: declare double @carg(double, double) [[READNONE]] +// NO__ERRNO: declare float @cargf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cargl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare double @carg(double, double) [[READNONE]] +// HAS_ERRNO: declare float @cargf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @cargl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_casin(f); __builtin_casinf(f); __builtin_casinl(f); + +// NO__ERRNO: declare { double, double } @casin(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @casinf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @casinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @casin(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @casinf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_casinh(f); __builtin_casinhf(f); __builtin_casinhl(f); + +// NO__ERRNO: declare { double, double } @casinh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @casinhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @casinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @casinh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @casinhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_catan(f); __builtin_catanf(f); __builtin_catanl(f); + +// NO__ERRNO: declare { double, double } @catan(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @catanf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @catanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @catan(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @catanf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @catanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_catanh(f); __builtin_catanhf(f); __builtin_catanhl(f); + +// NO__ERRNO: declare { double, double } @catanh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @catanhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @catanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @catanh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @catanhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @catanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_ccos(f); __builtin_ccosf(f); __builtin_ccosl(f); + +// NO__ERRNO: declare { double, double } @ccos(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ccosf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ccosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ccos(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ccosf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ccosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_ccosh(f); __builtin_ccoshf(f); __builtin_ccoshl(f); + +// NO__ERRNO: declare { double, double } @ccosh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ccoshf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ccoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ccosh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ccoshf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ccoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_cexp(f); __builtin_cexpf(f); __builtin_cexpl(f); + +// NO__ERRNO: declare { double, double } @cexp(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cexpf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cexpl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cexp(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cexpf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cexpl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_cimag(f); __builtin_cimagf(f); __builtin_cimagl(f); + +// NO__ERRNO-NOT: .cimag +// NO__ERRNO-NOT: @cimag +// HAS_ERRNO-NOT: .cimag +// HAS_ERRNO-NOT: @cimag + + __builtin_conj(f); __builtin_conjf(f); __builtin_conjl(f); + +// NO__ERRNO-NOT: .conj +// NO__ERRNO-NOT: @conj +// HAS_ERRNO-NOT: .conj +// HAS_ERRNO-NOT: @conj + + __builtin_clog(f); __builtin_clogf(f); __builtin_clogl(f); + +// NO__ERRNO: declare { double, double } @clog(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @clogf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @clogl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @clog(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @clogf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @clogl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_cproj(f); __builtin_cprojf(f); __builtin_cprojl(f); + +// NO__ERRNO: declare { double, double } @cproj(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_cpow(f,f); __builtin_cpowf(f,f); __builtin_cpowl(f,f); + +// NO__ERRNO: declare { double, double } @cpow(double, double, double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cpowl({ x86_fp80, x86_fp80 }* byval align 16, { x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cpow(double, double, double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cpowl({ x86_fp80, x86_fp80 }* byval align 16, { x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_creal(f); __builtin_crealf(f); __builtin_creall(f); + +// NO__ERRNO-NOT: .creal +// NO__ERRNO-NOT: @creal +// HAS_ERRNO-NOT: .creal +// HAS_ERRNO-NOT: @creal + + __builtin_csin(f); __builtin_csinf(f); __builtin_csinl(f); + +// NO__ERRNO: declare { double, double } @csin(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @csinf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @csinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @csin(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @csinf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_csinh(f); __builtin_csinhf(f); __builtin_csinhl(f); + +// NO__ERRNO: declare { double, double } @csinh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @csinhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @csinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @csinh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @csinhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_csqrt(f); __builtin_csqrtf(f); __builtin_csqrtl(f); + +// NO__ERRNO: declare { double, double } @csqrt(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @csqrtl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @csqrt(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csqrtl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_ctan(f); __builtin_ctanf(f); __builtin_ctanl(f); + +// NO__ERRNO: declare { double, double } @ctan(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ctanf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ctanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ctan(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ctanf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + __builtin_ctanh(f); __builtin_ctanhf(f); __builtin_ctanhl(f); + +// NO__ERRNO: declare { double, double } @ctanh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ctanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ctanh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +}; + + +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } + +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } + -- cgit v1.2.3 From 55dbed804bb40df7c40c98fd0e3e2057d89d0d02 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 2 Nov 2017 18:05:48 +0000 Subject: [refactor][selection] canonicalize selected string literal to objc string literal when possible git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317224 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Tooling/Refactoring/ASTSelection.cpp | 23 ++++++++++++++++++++++- unittests/Tooling/ASTSelectionTest.cpp | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/lib/Tooling/Refactoring/ASTSelection.cpp b/lib/Tooling/Refactoring/ASTSelection.cpp index 71a0d44be1..ab2be15512 100644 --- a/lib/Tooling/Refactoring/ASTSelection.cpp +++ b/lib/Tooling/Refactoring/ASTSelection.cpp @@ -249,9 +249,30 @@ struct SelectedNodeWithParents { SelectedNodeWithParents &operator=(SelectedNodeWithParents &&) = default; SelectedASTNode::ReferenceType Node; llvm::SmallVector Parents; + + /// Canonicalizes the given selection by selecting different related AST nodes + /// when it makes sense to do so. + void canonicalize(); }; } // end anonymous namespace +void SelectedNodeWithParents::canonicalize() { + const Stmt *S = Node.get().Node.get(); + assert(S && "non statement selection!"); + const Stmt *Parent = Parents[Parents.size() - 1].get().Node.get(); + if (!Parent) + return; + // Select the parent expression when: + // - The string literal in ObjC string literal is selected, e.g.: + // @"test" becomes @"test" + // ~~~~~~ ~~~~~~~ + if (isa(S) && isa(Parent)) + Node = Parents.pop_back_val(); + // FIXME: Syntactic form -> Entire pseudo-object expr. + // FIXME: Callee -> Call. + // FIXME: Callee member expr -> Call. +} + /// Finds the set of bottom-most selected AST nodes that are in the selection /// tree with the specified selection kind. /// @@ -330,7 +351,7 @@ CodeRangeASTSelection::create(SourceRange SelectionRange, return None; const Stmt *CodeRangeStmt = Selected.Node.get().Node.get(); if (!isa(CodeRangeStmt)) { - // FIXME (Alex L): Canonicalize. + Selected.canonicalize(); return CodeRangeASTSelection(Selected.Node, Selected.Parents, /*AreChildrenSelected=*/false); } diff --git a/unittests/Tooling/ASTSelectionTest.cpp b/unittests/Tooling/ASTSelectionTest.cpp index 1435334d6c..f10d899a0a 100644 --- a/unittests/Tooling/ASTSelectionTest.cpp +++ b/unittests/Tooling/ASTSelectionTest.cpp @@ -972,4 +972,36 @@ TEST(ASTSelectionFinder, SimpleCodeRangeASTSelectionInObjCMethod) { SelectionFinderVisitor::Lang_OBJC); } +TEST(ASTSelectionFinder, CanonicalizeObjCStringLiteral) { + StringRef Source = R"( +void foo() { + (void)@"test"; +} + )"; + // Just '"test"': + findSelectedASTNodesWithRange( + Source, {3, 10}, FileRange{{3, 10}, {3, 16}}, + [](SourceRange SelectionRange, Optional Node) { + EXPECT_TRUE(Node); + Optional SelectedCode = + CodeRangeASTSelection::create(SelectionRange, std::move(*Node)); + EXPECT_TRUE(SelectedCode); + EXPECT_EQ(SelectedCode->size(), 1u); + EXPECT_TRUE(isa((*SelectedCode)[0])); + }, + SelectionFinderVisitor::Lang_OBJC); + // Just 'test': + findSelectedASTNodesWithRange( + Source, {3, 11}, FileRange{{3, 11}, {3, 15}}, + [](SourceRange SelectionRange, Optional Node) { + EXPECT_TRUE(Node); + Optional SelectedCode = + CodeRangeASTSelection::create(SelectionRange, std::move(*Node)); + EXPECT_TRUE(SelectedCode); + EXPECT_EQ(SelectedCode->size(), 1u); + EXPECT_TRUE(isa((*SelectedCode)[0])); + }, + SelectionFinderVisitor::Lang_OBJC); +} + } // end anonymous namespace -- cgit v1.2.3 From 0479348d173c39db1dfaf937c4c6b685679124e3 Mon Sep 17 00:00:00 2001 From: Alexey Bataev Date: Thu, 2 Nov 2017 18:55:05 +0000 Subject: [OPENMP] Fix PR35152: Do not use getInvokeDest() function for EH checks. The compiler may crash under some conditions if the getInvokeDest() is used, but later it is not used. Fixed this problem in OpenMP. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317227 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGOpenMPRuntime.cpp | 3 ++- test/OpenMP/openmp_win_codegen.cpp | 35 +++++++++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/CGOpenMPRuntime.cpp b/lib/CodeGen/CGOpenMPRuntime.cpp index 779617adc2..ce7fe9364b 100644 --- a/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1451,7 +1451,8 @@ llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, return ThreadID; } // If exceptions are enabled, do not use parameter to avoid possible crash. - if (!CGF.getInvokeDest() || + if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || + !CGF.getLangOpts().CXXExceptions || CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { if (auto *OMPRegionInfo = dyn_cast_or_null(CGF.CapturedStmtInfo)) { diff --git a/test/OpenMP/openmp_win_codegen.cpp b/test/OpenMP/openmp_win_codegen.cpp index cdad7e29cc..45b2c185cb 100644 --- a/test/OpenMP/openmp_win_codegen.cpp +++ b/test/OpenMP/openmp_win_codegen.cpp @@ -1,13 +1,36 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-pc-windows-msvc18.0.0 -std=c++11 -fms-compatibility-version=18 -fms-extensions -emit-llvm %s -fexceptions -fcxx-exceptions -o - -O1 | FileCheck %s // REQUIRES: x86-registered-target // expected-no-diagnostics void foo(); void bar(); +struct Test { + static void main() { + int failed = 0; + int j = 2; + +#pragma omp parallel + { + int local_j = 3; +#pragma omp single copyprivate(local_j) + { + local_j = 4; + } + + // Assure reports a data race, but value written to "j" + // should always be the same. + j = local_j; + } + + } +}; + // CHECK-LABEL: @main int main() { - // CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*)) + // CHECK: call void @{{.+}}main + Test::main(); + // CHECK: call void (%ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%ident_t* {{.*}}@0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*)) #pragma omp parallel { try { @@ -24,15 +47,15 @@ int main() { } // CHECK: define internal void [[OUTLINED]]( -// CHECK: [[GID:%.+]] = call i32 @__kmpc_global_thread_num(%ident_t* @0) +// CHECK: [[GID:%.+]] = {{.*}}call i32 @__kmpc_global_thread_num(%ident_t* {{.*}}@0) // CHECK: invoke void @{{.+}}foo // CHECK: catchswitch within // CHECK: catchpad within -// CHECK: call void @__kmpc_critical(%ident_t* @0, i32 [[GID]], +// CHECK: call void @__kmpc_critical(%ident_t* {{.*}}@0, i32 [[GID]], // CHECK: invoke void @{{.+}}bar -// CHECK: call void @__kmpc_end_critical(%ident_t* @0, i32 [[GID]], +// CHECK: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]], // CHECK: catchret from // CHECK: cleanuppad within -// CHECK: call void @__kmpc_end_critical(%ident_t* @0, i32 [[GID]], +// CHECK: call void @__kmpc_end_critical(%ident_t* {{.*}}@0, i32 [[GID]], // CHECK: cleanupret from -- cgit v1.2.3 From 798d3688c7809b32149889c638618d175c091923 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 2 Nov 2017 19:01:34 +0000 Subject: remove unused function from ObjCRuntime.h, NFC git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317228 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/ObjCRuntime.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index 8dc259c7ab..03a53a0bf8 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -67,11 +67,6 @@ public: ObjCRuntime(Kind kind, const VersionTuple &version) : TheKind(kind), Version(version) {} - void set(Kind kind, VersionTuple version) { - TheKind = kind; - Version = version; - } - Kind getKind() const { return TheKind; } const VersionTuple &getVersion() const { return Version; } -- cgit v1.2.3 From de0289c4685fc6f78767d6257a3a17467bcf6783 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Thu, 2 Nov 2017 19:42:40 +0000 Subject: revert r317228: remove unused function from ObjCRuntime.h, NFC This function is actually used in LLDB git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317231 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/ObjCRuntime.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index 03a53a0bf8..8dc259c7ab 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -67,6 +67,11 @@ public: ObjCRuntime(Kind kind, const VersionTuple &version) : TheKind(kind), Version(version) {} + void set(Kind kind, VersionTuple version) { + TheKind = kind; + Version = version; + } + Kind getKind() const { return TheKind; } const VersionTuple &getVersion() const { return Version; } -- cgit v1.2.3 From 603490dae39300a191e0485ce192a46176267397 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Thu, 2 Nov 2017 20:39:26 +0000 Subject: [CodeGen] fix const-ness of builtin equivalents of and functions that might set errno This just makes const-ness of the builtins match const-ness of their lib function siblings. We're deferring fixing some of these that are obviously wrong to follow-up patches. Hopefully, the bugs are visible in the new test file (added at rL317220). As the description in Builtins.def says: "e = const, but only when -fmath-errno=0". This is step 2 of N to fix builtins and math calls as discussed in D39204. Differential Revision: https://reviews.llvm.org/D39481 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317265 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Builtins.def | 258 +++++++++++++++++++-------------------- test/CodeGen/builtin-errno.c | 258 +++++++++++++++++++-------------------- test/CodeGen/builtin-sqrt.c | 6 +- 3 files changed, 260 insertions(+), 262 deletions(-) diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 8e276e8445..ab7d22f880 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -103,9 +103,9 @@ #endif // Standard libc/libm functions: -BUILTIN(__builtin_atan2 , "ddd" , "Fnc") -BUILTIN(__builtin_atan2f, "fff" , "Fnc") -BUILTIN(__builtin_atan2l, "LdLdLd", "Fnc") +BUILTIN(__builtin_atan2 , "ddd" , "Fne") +BUILTIN(__builtin_atan2f, "fff" , "Fne") +BUILTIN(__builtin_atan2l, "LdLdLd", "Fne") BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_copysign, "ddd", "ncF") BUILTIN(__builtin_copysignf, "fff", "ncF") @@ -113,9 +113,9 @@ BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") BUILTIN(__builtin_fabs , "dd" , "ncF") BUILTIN(__builtin_fabsf, "ff" , "ncF") BUILTIN(__builtin_fabsl, "LdLd", "ncF") -BUILTIN(__builtin_fmod , "ddd" , "Fnc") -BUILTIN(__builtin_fmodf, "fff" , "Fnc") -BUILTIN(__builtin_fmodl, "LdLdLd", "Fnc") +BUILTIN(__builtin_fmod , "ddd" , "Fne") +BUILTIN(__builtin_fmodf, "fff" , "Fne") +BUILTIN(__builtin_fmodl, "LdLdLd", "Fne") BUILTIN(__builtin_frexp , "ddi*" , "Fn") BUILTIN(__builtin_frexpf, "ffi*" , "Fn") BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") @@ -127,9 +127,9 @@ BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") -BUILTIN(__builtin_ldexp , "ddi" , "Fnc") -BUILTIN(__builtin_ldexpf, "ffi" , "Fnc") -BUILTIN(__builtin_ldexpl, "LdLdi", "Fnc") +BUILTIN(__builtin_ldexp , "ddi" , "Fne") +BUILTIN(__builtin_ldexpf, "ffi" , "Fne") +BUILTIN(__builtin_ldexpl, "LdLdi", "Fne") BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") @@ -142,119 +142,119 @@ BUILTIN(__builtin_nansl, "LdcC*", "ncF") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") -BUILTIN(__builtin_pow , "ddd" , "Fnc") -BUILTIN(__builtin_powf, "fff" , "Fnc") -BUILTIN(__builtin_powl, "LdLdLd", "Fnc") +BUILTIN(__builtin_pow , "ddd" , "Fne") +BUILTIN(__builtin_powf, "fff" , "Fne") +BUILTIN(__builtin_powl, "LdLdLd", "Fne") // Standard unary libc/libm functions with double/float/long double variants: -BUILTIN(__builtin_acos , "dd" , "Fnc") -BUILTIN(__builtin_acosf, "ff" , "Fnc") -BUILTIN(__builtin_acosl, "LdLd", "Fnc") -BUILTIN(__builtin_acosh , "dd" , "Fnc") -BUILTIN(__builtin_acoshf, "ff" , "Fnc") -BUILTIN(__builtin_acoshl, "LdLd", "Fnc") -BUILTIN(__builtin_asin , "dd" , "Fnc") -BUILTIN(__builtin_asinf, "ff" , "Fnc") -BUILTIN(__builtin_asinl, "LdLd", "Fnc") -BUILTIN(__builtin_asinh , "dd" , "Fnc") -BUILTIN(__builtin_asinhf, "ff" , "Fnc") -BUILTIN(__builtin_asinhl, "LdLd", "Fnc") -BUILTIN(__builtin_atan , "dd" , "Fnc") -BUILTIN(__builtin_atanf, "ff" , "Fnc") -BUILTIN(__builtin_atanl, "LdLd", "Fnc") -BUILTIN(__builtin_atanh , "dd", "Fnc") -BUILTIN(__builtin_atanhf, "ff", "Fnc") -BUILTIN(__builtin_atanhl, "LdLd", "Fnc") -BUILTIN(__builtin_cbrt , "dd", "Fnc") -BUILTIN(__builtin_cbrtf, "ff", "Fnc") -BUILTIN(__builtin_cbrtl, "LdLd", "Fnc") +BUILTIN(__builtin_acos , "dd" , "Fne") +BUILTIN(__builtin_acosf, "ff" , "Fne") +BUILTIN(__builtin_acosl, "LdLd", "Fne") +BUILTIN(__builtin_acosh , "dd" , "Fne") +BUILTIN(__builtin_acoshf, "ff" , "Fne") +BUILTIN(__builtin_acoshl, "LdLd", "Fne") +BUILTIN(__builtin_asin , "dd" , "Fne") +BUILTIN(__builtin_asinf, "ff" , "Fne") +BUILTIN(__builtin_asinl, "LdLd", "Fne") +BUILTIN(__builtin_asinh , "dd" , "Fne") +BUILTIN(__builtin_asinhf, "ff" , "Fne") +BUILTIN(__builtin_asinhl, "LdLd", "Fne") +BUILTIN(__builtin_atan , "dd" , "Fne") +BUILTIN(__builtin_atanf, "ff" , "Fne") +BUILTIN(__builtin_atanl, "LdLd", "Fne") +BUILTIN(__builtin_atanh , "dd", "Fne") +BUILTIN(__builtin_atanhf, "ff", "Fne") +BUILTIN(__builtin_atanhl, "LdLd", "Fne") +BUILTIN(__builtin_cbrt , "dd", "Fne") +BUILTIN(__builtin_cbrtf, "ff", "Fne") +BUILTIN(__builtin_cbrtl, "LdLd", "Fne") BUILTIN(__builtin_ceil , "dd" , "Fnc") BUILTIN(__builtin_ceilf, "ff" , "Fnc") BUILTIN(__builtin_ceill, "LdLd", "Fnc") -BUILTIN(__builtin_cos , "dd" , "Fnc") -BUILTIN(__builtin_cosf, "ff" , "Fnc") -BUILTIN(__builtin_cosh , "dd" , "Fnc") -BUILTIN(__builtin_coshf, "ff" , "Fnc") -BUILTIN(__builtin_coshl, "LdLd", "Fnc") -BUILTIN(__builtin_cosl, "LdLd", "Fnc") -BUILTIN(__builtin_erf , "dd", "Fnc") -BUILTIN(__builtin_erff, "ff", "Fnc") -BUILTIN(__builtin_erfl, "LdLd", "Fnc") -BUILTIN(__builtin_erfc , "dd", "Fnc") -BUILTIN(__builtin_erfcf, "ff", "Fnc") -BUILTIN(__builtin_erfcl, "LdLd", "Fnc") -BUILTIN(__builtin_exp , "dd" , "Fnc") -BUILTIN(__builtin_expf, "ff" , "Fnc") -BUILTIN(__builtin_expl, "LdLd", "Fnc") -BUILTIN(__builtin_exp2 , "dd" , "Fnc") -BUILTIN(__builtin_exp2f, "ff" , "Fnc") -BUILTIN(__builtin_exp2l, "LdLd", "Fnc") -BUILTIN(__builtin_expm1 , "dd", "Fnc") -BUILTIN(__builtin_expm1f, "ff", "Fnc") -BUILTIN(__builtin_expm1l, "LdLd", "Fnc") -BUILTIN(__builtin_fdim, "ddd", "Fnc") -BUILTIN(__builtin_fdimf, "fff", "Fnc") -BUILTIN(__builtin_fdiml, "LdLdLd", "Fnc") +BUILTIN(__builtin_cos , "dd" , "Fne") +BUILTIN(__builtin_cosf, "ff" , "Fne") +BUILTIN(__builtin_cosh , "dd" , "Fne") +BUILTIN(__builtin_coshf, "ff" , "Fne") +BUILTIN(__builtin_coshl, "LdLd", "Fne") +BUILTIN(__builtin_cosl, "LdLd", "Fne") +BUILTIN(__builtin_erf , "dd", "Fne") +BUILTIN(__builtin_erff, "ff", "Fne") +BUILTIN(__builtin_erfl, "LdLd", "Fne") +BUILTIN(__builtin_erfc , "dd", "Fne") +BUILTIN(__builtin_erfcf, "ff", "Fne") +BUILTIN(__builtin_erfcl, "LdLd", "Fne") +BUILTIN(__builtin_exp , "dd" , "Fne") +BUILTIN(__builtin_expf, "ff" , "Fne") +BUILTIN(__builtin_expl, "LdLd", "Fne") +BUILTIN(__builtin_exp2 , "dd" , "Fne") +BUILTIN(__builtin_exp2f, "ff" , "Fne") +BUILTIN(__builtin_exp2l, "LdLd", "Fne") +BUILTIN(__builtin_expm1 , "dd", "Fne") +BUILTIN(__builtin_expm1f, "ff", "Fne") +BUILTIN(__builtin_expm1l, "LdLd", "Fne") +BUILTIN(__builtin_fdim, "ddd", "Fne") +BUILTIN(__builtin_fdimf, "fff", "Fne") +BUILTIN(__builtin_fdiml, "LdLdLd", "Fne") BUILTIN(__builtin_floor , "dd" , "Fnc") BUILTIN(__builtin_floorf, "ff" , "Fnc") BUILTIN(__builtin_floorl, "LdLd", "Fnc") -BUILTIN(__builtin_fma, "dddd", "Fnc") -BUILTIN(__builtin_fmaf, "ffff", "Fnc") -BUILTIN(__builtin_fmal, "LdLdLdLd", "Fnc") +BUILTIN(__builtin_fma, "dddd", "Fne") +BUILTIN(__builtin_fmaf, "ffff", "Fne") +BUILTIN(__builtin_fmal, "LdLdLdLd", "Fne") BUILTIN(__builtin_fmax, "ddd", "Fnc") BUILTIN(__builtin_fmaxf, "fff", "Fnc") BUILTIN(__builtin_fmaxl, "LdLdLd", "Fnc") BUILTIN(__builtin_fmin, "ddd", "Fnc") BUILTIN(__builtin_fminf, "fff", "Fnc") BUILTIN(__builtin_fminl, "LdLdLd", "Fnc") -BUILTIN(__builtin_hypot , "ddd" , "Fnc") -BUILTIN(__builtin_hypotf, "fff" , "Fnc") -BUILTIN(__builtin_hypotl, "LdLdLd", "Fnc") -BUILTIN(__builtin_ilogb , "id", "Fnc") -BUILTIN(__builtin_ilogbf, "if", "Fnc") -BUILTIN(__builtin_ilogbl, "iLd", "Fnc") -BUILTIN(__builtin_lgamma , "dd", "Fnc") -BUILTIN(__builtin_lgammaf, "ff", "Fnc") -BUILTIN(__builtin_lgammal, "LdLd", "Fnc") -BUILTIN(__builtin_llrint, "LLid", "Fnc") -BUILTIN(__builtin_llrintf, "LLif", "Fnc") -BUILTIN(__builtin_llrintl, "LLiLd", "Fnc") -BUILTIN(__builtin_llround , "LLid", "Fnc") -BUILTIN(__builtin_llroundf, "LLif", "Fnc") -BUILTIN(__builtin_llroundl, "LLiLd", "Fnc") -BUILTIN(__builtin_log , "dd" , "Fnc") -BUILTIN(__builtin_log10 , "dd" , "Fnc") -BUILTIN(__builtin_log10f, "ff" , "Fnc") -BUILTIN(__builtin_log10l, "LdLd", "Fnc") -BUILTIN(__builtin_log1p , "dd" , "Fnc") -BUILTIN(__builtin_log1pf, "ff" , "Fnc") -BUILTIN(__builtin_log1pl, "LdLd", "Fnc") -BUILTIN(__builtin_log2, "dd" , "Fnc") -BUILTIN(__builtin_log2f, "ff" , "Fnc") -BUILTIN(__builtin_log2l, "LdLd" , "Fnc") -BUILTIN(__builtin_logb , "dd", "Fnc") -BUILTIN(__builtin_logbf, "ff", "Fnc") -BUILTIN(__builtin_logbl, "LdLd", "Fnc") -BUILTIN(__builtin_logf, "ff" , "Fnc") -BUILTIN(__builtin_logl, "LdLd", "Fnc") -BUILTIN(__builtin_lrint , "Lid", "Fnc") -BUILTIN(__builtin_lrintf, "Lif", "Fnc") -BUILTIN(__builtin_lrintl, "LiLd", "Fnc") -BUILTIN(__builtin_lround , "Lid", "Fnc") -BUILTIN(__builtin_lroundf, "Lif", "Fnc") -BUILTIN(__builtin_lroundl, "LiLd", "Fnc") +BUILTIN(__builtin_hypot , "ddd" , "Fne") +BUILTIN(__builtin_hypotf, "fff" , "Fne") +BUILTIN(__builtin_hypotl, "LdLdLd", "Fne") +BUILTIN(__builtin_ilogb , "id", "Fne") +BUILTIN(__builtin_ilogbf, "if", "Fne") +BUILTIN(__builtin_ilogbl, "iLd", "Fne") +BUILTIN(__builtin_lgamma , "dd", "Fn") +BUILTIN(__builtin_lgammaf, "ff", "Fn") +BUILTIN(__builtin_lgammal, "LdLd", "Fn") +BUILTIN(__builtin_llrint, "LLid", "Fne") +BUILTIN(__builtin_llrintf, "LLif", "Fne") +BUILTIN(__builtin_llrintl, "LLiLd", "Fne") +BUILTIN(__builtin_llround , "LLid", "Fne") +BUILTIN(__builtin_llroundf, "LLif", "Fne") +BUILTIN(__builtin_llroundl, "LLiLd", "Fne") +BUILTIN(__builtin_log , "dd" , "Fne") +BUILTIN(__builtin_log10 , "dd" , "Fne") +BUILTIN(__builtin_log10f, "ff" , "Fne") +BUILTIN(__builtin_log10l, "LdLd", "Fne") +BUILTIN(__builtin_log1p , "dd" , "Fne") +BUILTIN(__builtin_log1pf, "ff" , "Fne") +BUILTIN(__builtin_log1pl, "LdLd", "Fne") +BUILTIN(__builtin_log2, "dd" , "Fne") +BUILTIN(__builtin_log2f, "ff" , "Fne") +BUILTIN(__builtin_log2l, "LdLd" , "Fne") +BUILTIN(__builtin_logb , "dd", "Fne") +BUILTIN(__builtin_logbf, "ff", "Fne") +BUILTIN(__builtin_logbl, "LdLd", "Fne") +BUILTIN(__builtin_logf, "ff" , "Fne") +BUILTIN(__builtin_logl, "LdLd", "Fne") +BUILTIN(__builtin_lrint , "Lid", "Fne") +BUILTIN(__builtin_lrintf, "Lif", "Fne") +BUILTIN(__builtin_lrintl, "LiLd", "Fne") +BUILTIN(__builtin_lround , "Lid", "Fne") +BUILTIN(__builtin_lroundf, "Lif", "Fne") +BUILTIN(__builtin_lroundl, "LiLd", "Fne") BUILTIN(__builtin_nearbyint , "dd", "Fnc") BUILTIN(__builtin_nearbyintf, "ff", "Fnc") BUILTIN(__builtin_nearbyintl, "LdLd", "Fnc") -BUILTIN(__builtin_nextafter , "ddd", "Fnc") -BUILTIN(__builtin_nextafterf, "fff", "Fnc") -BUILTIN(__builtin_nextafterl, "LdLdLd", "Fnc") -BUILTIN(__builtin_nexttoward , "ddLd", "Fnc") -BUILTIN(__builtin_nexttowardf, "ffLd", "Fnc") -BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fnc") -BUILTIN(__builtin_remainder , "ddd", "Fnc") -BUILTIN(__builtin_remainderf, "fff", "Fnc") -BUILTIN(__builtin_remainderl, "LdLdLd", "Fnc") +BUILTIN(__builtin_nextafter , "ddd", "Fne") +BUILTIN(__builtin_nextafterf, "fff", "Fne") +BUILTIN(__builtin_nextafterl, "LdLdLd", "Fne") +BUILTIN(__builtin_nexttoward , "ddLd", "Fne") +BUILTIN(__builtin_nexttowardf, "ffLd", "Fne") +BUILTIN(__builtin_nexttowardl, "LdLdLd", "Fne") +BUILTIN(__builtin_remainder , "ddd", "Fne") +BUILTIN(__builtin_remainderf, "fff", "Fne") +BUILTIN(__builtin_remainderl, "LdLdLd", "Fne") BUILTIN(__builtin_remquo , "dddi*", "Fn") BUILTIN(__builtin_remquof, "fffi*", "Fn") BUILTIN(__builtin_remquol, "LdLdLdi*", "Fn") @@ -264,30 +264,30 @@ BUILTIN(__builtin_rintl, "LdLd", "Fnc") BUILTIN(__builtin_round, "dd" , "Fnc") BUILTIN(__builtin_roundf, "ff" , "Fnc") BUILTIN(__builtin_roundl, "LdLd" , "Fnc") -BUILTIN(__builtin_scalbln , "ddLi", "Fnc") -BUILTIN(__builtin_scalblnf, "ffLi", "Fnc") -BUILTIN(__builtin_scalblnl, "LdLdLi", "Fnc") -BUILTIN(__builtin_scalbn , "ddi", "Fnc") -BUILTIN(__builtin_scalbnf, "ffi", "Fnc") -BUILTIN(__builtin_scalbnl, "LdLdi", "Fnc") -BUILTIN(__builtin_sin , "dd" , "Fnc") -BUILTIN(__builtin_sinf, "ff" , "Fnc") -BUILTIN(__builtin_sinh , "dd" , "Fnc") -BUILTIN(__builtin_sinhf, "ff" , "Fnc") -BUILTIN(__builtin_sinhl, "LdLd", "Fnc") -BUILTIN(__builtin_sinl, "LdLd", "Fnc") -BUILTIN(__builtin_sqrt , "dd" , "Fnc") -BUILTIN(__builtin_sqrtf, "ff" , "Fnc") -BUILTIN(__builtin_sqrtl, "LdLd", "Fnc") -BUILTIN(__builtin_tan , "dd" , "Fnc") -BUILTIN(__builtin_tanf, "ff" , "Fnc") -BUILTIN(__builtin_tanh , "dd" , "Fnc") -BUILTIN(__builtin_tanhf, "ff" , "Fnc") -BUILTIN(__builtin_tanhl, "LdLd", "Fnc") -BUILTIN(__builtin_tanl, "LdLd", "Fnc") -BUILTIN(__builtin_tgamma , "dd", "Fnc") -BUILTIN(__builtin_tgammaf, "ff", "Fnc") -BUILTIN(__builtin_tgammal, "LdLd", "Fnc") +BUILTIN(__builtin_scalbln , "ddLi", "Fne") +BUILTIN(__builtin_scalblnf, "ffLi", "Fne") +BUILTIN(__builtin_scalblnl, "LdLdLi", "Fne") +BUILTIN(__builtin_scalbn , "ddi", "Fne") +BUILTIN(__builtin_scalbnf, "ffi", "Fne") +BUILTIN(__builtin_scalbnl, "LdLdi", "Fne") +BUILTIN(__builtin_sin , "dd" , "Fne") +BUILTIN(__builtin_sinf, "ff" , "Fne") +BUILTIN(__builtin_sinh , "dd" , "Fne") +BUILTIN(__builtin_sinhf, "ff" , "Fne") +BUILTIN(__builtin_sinhl, "LdLd", "Fne") +BUILTIN(__builtin_sinl, "LdLd", "Fne") +BUILTIN(__builtin_sqrt , "dd" , "Fne") +BUILTIN(__builtin_sqrtf, "ff" , "Fne") +BUILTIN(__builtin_sqrtl, "LdLd", "Fne") +BUILTIN(__builtin_tan , "dd" , "Fne") +BUILTIN(__builtin_tanf, "ff" , "Fne") +BUILTIN(__builtin_tanh , "dd" , "Fne") +BUILTIN(__builtin_tanhf, "ff" , "Fne") +BUILTIN(__builtin_tanhl, "LdLd", "Fne") +BUILTIN(__builtin_tanl, "LdLd", "Fne") +BUILTIN(__builtin_tgamma , "dd", "Fne") +BUILTIN(__builtin_tgammaf, "ff", "Fne") +BUILTIN(__builtin_tgammal, "LdLd", "Fne") BUILTIN(__builtin_trunc , "dd", "Fnc") BUILTIN(__builtin_truncf, "ff", "Fnc") BUILTIN(__builtin_truncl, "LdLd", "Fnc") diff --git a/test/CodeGen/builtin-errno.c b/test/CodeGen/builtin-errno.c index 43fdef6973..4b2361d12d 100644 --- a/test/CodeGen/builtin-errno.c +++ b/test/CodeGen/builtin-errno.c @@ -32,9 +32,9 @@ void foo() { // NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]] // NO__ERRNO: declare float @atan2f(float, float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]] -// HAS_ERRNO: declare float @atan2f(float, float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE:#[0-9]+]] +// HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_copysign(f,f); __builtin_copysignf(f,f);__builtin_copysignl(f,f); @@ -66,7 +66,7 @@ void foo() { // NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]] // NO__ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] // NO__ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] -// HAS_ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]] +// HAS_ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE]] // HAS_ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] // HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] @@ -89,9 +89,9 @@ void foo() { // NO__ERRNO: declare double @ldexp(double, i32) [[READNONE]] // NO__ERRNO: declare float @ldexpf(float, i32) [[READNONE]] // NO__ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[READNONE]] -// HAS_ERRNO: declare double @ldexp(double, i32) [[READNONE]] -// HAS_ERRNO: declare float @ldexpf(float, i32) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[READNONE]] +// HAS_ERRNO: declare double @ldexp(double, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare float @ldexpf(float, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NOT_READNONE]] __builtin_modf(f,d); __builtin_modff(f,fp); __builtin_modfl(f,l); @@ -125,9 +125,9 @@ void foo() { // NO__ERRNO: declare double @llvm.pow.f64(double, double) [[READNONE_INTRINSIC]] // NO__ERRNO: declare float @llvm.pow.f32(float, float) [[READNONE_INTRINSIC]] // NO__ERRNO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] -// HAS_ERRNO: declare double @llvm.pow.f64(double, double) [[READNONE_INTRINSIC]] -// HAS_ERRNO: declare float @llvm.pow.f32(float, float) [[READNONE_INTRINSIC]] -// HAS_ERRNO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @pow(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @powf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_powi(f,f); __builtin_powif(f,f); __builtin_powil(f,f); @@ -144,63 +144,63 @@ void foo() { // NO__ERRNO: declare double @acos(double) [[READNONE]] // NO__ERRNO: declare float @acosf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @acosl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @acos(double) [[READNONE]] -// HAS_ERRNO: declare float @acosf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @acosl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @acos(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @acosf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @acosl(x86_fp80) [[NOT_READNONE]] __builtin_acosh(f); __builtin_acoshf(f); __builtin_acoshl(f); // NO__ERRNO: declare double @acosh(double) [[READNONE]] // NO__ERRNO: declare float @acoshf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @acosh(double) [[READNONE]] -// HAS_ERRNO: declare float @acoshf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @acosh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @acoshf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[NOT_READNONE]] __builtin_asin(f); __builtin_asinf(f); __builtin_asinl(f); // NO__ERRNO: declare double @asin(double) [[READNONE]] // NO__ERRNO: declare float @asinf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @asinl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @asin(double) [[READNONE]] -// HAS_ERRNO: declare float @asinf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @asinl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @asin(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @asinf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @asinl(x86_fp80) [[NOT_READNONE]] __builtin_asinh(f); __builtin_asinhf(f); __builtin_asinhl(f); // NO__ERRNO: declare double @asinh(double) [[READNONE]] // NO__ERRNO: declare float @asinhf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @asinh(double) [[READNONE]] -// HAS_ERRNO: declare float @asinhf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @asinh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @asinhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[NOT_READNONE]] __builtin_atan(f); __builtin_atanf(f); __builtin_atanl(f); // NO__ERRNO: declare double @atan(double) [[READNONE]] // NO__ERRNO: declare float @atanf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @atanl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @atan(double) [[READNONE]] -// HAS_ERRNO: declare float @atanf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @atanl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atan(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @atanf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @atanl(x86_fp80) [[NOT_READNONE]] __builtin_atanh(f); __builtin_atanhf(f); __builtin_atanhl(f); // NO__ERRNO: declare double @atanh(double) [[READNONE]] // NO__ERRNO: declare float @atanhf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @atanh(double) [[READNONE]] -// HAS_ERRNO: declare float @atanhf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atanh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @atanhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[NOT_READNONE]] __builtin_cbrt(f); __builtin_cbrtf(f); __builtin_cbrtl(f); // NO__ERRNO: declare double @cbrt(double) [[READNONE]] // NO__ERRNO: declare float @cbrtf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @cbrt(double) [[READNONE]] -// HAS_ERRNO: declare float @cbrtf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cbrt(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @cbrtf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[NOT_READNONE]] __builtin_ceil(f); __builtin_ceilf(f); __builtin_ceill(f); @@ -216,72 +216,72 @@ void foo() { // NO__ERRNO: declare double @cos(double) [[READNONE]] // NO__ERRNO: declare float @cosf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @cosl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @cos(double) [[READNONE]] -// HAS_ERRNO: declare float @cosf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @cosl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cos(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @cosf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @cosl(x86_fp80) [[NOT_READNONE]] __builtin_cosh(f); __builtin_coshf(f); __builtin_coshl(f); // NO__ERRNO: declare double @cosh(double) [[READNONE]] // NO__ERRNO: declare float @coshf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @coshl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @cosh(double) [[READNONE]] -// HAS_ERRNO: declare float @coshf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @coshl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cosh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @coshf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @coshl(x86_fp80) [[NOT_READNONE]] __builtin_erf(f); __builtin_erff(f); __builtin_erfl(f); // NO__ERRNO: declare double @erf(double) [[READNONE]] // NO__ERRNO: declare float @erff(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @erfl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @erf(double) [[READNONE]] -// HAS_ERRNO: declare float @erff(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @erfl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @erf(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @erff(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @erfl(x86_fp80) [[NOT_READNONE]] __builtin_erfc(f); __builtin_erfcf(f); __builtin_erfcl(f); // NO__ERRNO: declare double @erfc(double) [[READNONE]] // NO__ERRNO: declare float @erfcf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @erfc(double) [[READNONE]] -// HAS_ERRNO: declare float @erfcf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @erfc(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @erfcf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[NOT_READNONE]] __builtin_exp(f); __builtin_expf(f); __builtin_expl(f); // NO__ERRNO: declare double @exp(double) [[READNONE]] // NO__ERRNO: declare float @expf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @expl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @exp(double) [[READNONE]] -// HAS_ERRNO: declare float @expf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @expl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @exp(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @expf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @expl(x86_fp80) [[NOT_READNONE]] __builtin_exp2(f); __builtin_exp2f(f); __builtin_exp2l(f); // NO__ERRNO: declare double @exp2(double) [[READNONE]] // NO__ERRNO: declare float @exp2f(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @exp2(double) [[READNONE]] -// HAS_ERRNO: declare float @exp2f(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @exp2(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @exp2f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[NOT_READNONE]] __builtin_expm1(f); __builtin_expm1f(f); __builtin_expm1l(f); // NO__ERRNO: declare double @expm1(double) [[READNONE]] // NO__ERRNO: declare float @expm1f(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @expm1(double) [[READNONE]] -// HAS_ERRNO: declare float @expm1f(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @expm1(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @expm1f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[NOT_READNONE]] __builtin_fdim(f,f); __builtin_fdimf(f,f); __builtin_fdiml(f,f); // NO__ERRNO: declare double @fdim(double, double) [[READNONE]] // NO__ERRNO: declare float @fdimf(float, float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @fdim(double, double) [[READNONE]] -// HAS_ERRNO: declare float @fdimf(float, float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fdim(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @fdimf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_floor(f); __builtin_floorf(f); __builtin_floorl(f); @@ -324,108 +324,108 @@ void foo() { // NO__ERRNO: declare double @hypot(double, double) [[READNONE]] // NO__ERRNO: declare float @hypotf(float, float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @hypot(double, double) [[READNONE]] -// HAS_ERRNO: declare float @hypotf(float, float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @hypot(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @hypotf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_ilogb(f); __builtin_ilogbf(f); __builtin_ilogbl(f); // NO__ERRNO: declare i32 @ilogb(double) [[READNONE]] // NO__ERRNO: declare i32 @ilogbf(float) [[READNONE]] // NO__ERRNO: declare i32 @ilogbl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare i32 @ilogb(double) [[READNONE]] -// HAS_ERRNO: declare i32 @ilogbf(float) [[READNONE]] -// HAS_ERRNO: declare i32 @ilogbl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i32 @ilogb(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i32 @ilogbf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i32 @ilogbl(x86_fp80) [[NOT_READNONE]] __builtin_lgamma(f); __builtin_lgammaf(f); __builtin_lgammal(f); -// NO__ERRNO: declare double @lgamma(double) [[READNONE]] -// NO__ERRNO: declare float @lgammaf(float) [[READNONE]] -// NO__ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @lgamma(double) [[READNONE]] -// HAS_ERRNO: declare float @lgammaf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[READNONE]] +// NO__ERRNO: declare double @lgamma(double) [[NOT_READNONE]] +// NO__ERRNO: declare float @lgammaf(float) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[NOT_READNONE]] +// HAS_ERRNO: declare double @lgamma(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @lgammaf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[NOT_READNONE]] __builtin_llrint(f); __builtin_llrintf(f); __builtin_llrintl(f); // NO__ERRNO: declare i64 @llrint(double) [[READNONE]] // NO__ERRNO: declare i64 @llrintf(float) [[READNONE]] // NO__ERRNO: declare i64 @llrintl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare i64 @llrint(double) [[READNONE]] -// HAS_ERRNO: declare i64 @llrintf(float) [[READNONE]] -// HAS_ERRNO: declare i64 @llrintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @llrint(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llrintf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llrintl(x86_fp80) [[NOT_READNONE]] __builtin_llround(f); __builtin_llroundf(f); __builtin_llroundl(f); // NO__ERRNO: declare i64 @llround(double) [[READNONE]] // NO__ERRNO: declare i64 @llroundf(float) [[READNONE]] // NO__ERRNO: declare i64 @llroundl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare i64 @llround(double) [[READNONE]] -// HAS_ERRNO: declare i64 @llroundf(float) [[READNONE]] -// HAS_ERRNO: declare i64 @llroundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @llround(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llroundf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llroundl(x86_fp80) [[NOT_READNONE]] __builtin_log(f); __builtin_logf(f); __builtin_logl(f); // NO__ERRNO: declare double @log(double) [[READNONE]] // NO__ERRNO: declare float @logf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @logl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @log(double) [[READNONE]] -// HAS_ERRNO: declare float @logf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @logl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @logf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @logl(x86_fp80) [[NOT_READNONE]] __builtin_log10(f); __builtin_log10f(f); __builtin_log10l(f); // NO__ERRNO: declare double @log10(double) [[READNONE]] // NO__ERRNO: declare float @log10f(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @log10l(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @log10(double) [[READNONE]] -// HAS_ERRNO: declare float @log10f(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @log10l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log10(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @log10f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @log10l(x86_fp80) [[NOT_READNONE]] __builtin_log1p(f); __builtin_log1pf(f); __builtin_log1pl(f); // NO__ERRNO: declare double @log1p(double) [[READNONE]] // NO__ERRNO: declare float @log1pf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @log1p(double) [[READNONE]] -// HAS_ERRNO: declare float @log1pf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log1p(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @log1pf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[NOT_READNONE]] __builtin_log2(f); __builtin_log2f(f); __builtin_log2l(f); // NO__ERRNO: declare double @log2(double) [[READNONE]] // NO__ERRNO: declare float @log2f(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @log2l(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @log2(double) [[READNONE]] -// HAS_ERRNO: declare float @log2f(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @log2l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log2(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @log2f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @log2l(x86_fp80) [[NOT_READNONE]] __builtin_logb(f); __builtin_logbf(f); __builtin_logbl(f); // NO__ERRNO: declare double @logb(double) [[READNONE]] // NO__ERRNO: declare float @logbf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @logbl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @logb(double) [[READNONE]] -// HAS_ERRNO: declare float @logbf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @logbl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @logb(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @logbf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @logbl(x86_fp80) [[NOT_READNONE]] __builtin_lrint(f); __builtin_lrintf(f); __builtin_lrintl(f); // NO__ERRNO: declare i64 @lrint(double) [[READNONE]] // NO__ERRNO: declare i64 @lrintf(float) [[READNONE]] // NO__ERRNO: declare i64 @lrintl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare i64 @lrint(double) [[READNONE]] -// HAS_ERRNO: declare i64 @lrintf(float) [[READNONE]] -// HAS_ERRNO: declare i64 @lrintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @lrint(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lrintf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lrintl(x86_fp80) [[NOT_READNONE]] __builtin_lround(f); __builtin_lroundf(f); __builtin_lroundl(f); // NO__ERRNO: declare i64 @lround(double) [[READNONE]] // NO__ERRNO: declare i64 @lroundf(float) [[READNONE]] // NO__ERRNO: declare i64 @lroundl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare i64 @lround(double) [[READNONE]] -// HAS_ERRNO: declare i64 @lroundf(float) [[READNONE]] -// HAS_ERRNO: declare i64 @lroundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @lround(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lroundf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lroundl(x86_fp80) [[NOT_READNONE]] __builtin_nearbyint(f); __builtin_nearbyintf(f); __builtin_nearbyintl(f); @@ -441,27 +441,27 @@ void foo() { // NO__ERRNO: declare double @nextafter(double, double) [[READNONE]] // NO__ERRNO: declare float @nextafterf(float, float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @nextafter(double, double) [[READNONE]] -// HAS_ERRNO: declare float @nextafterf(float, float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nextafter(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @nextafterf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_nexttoward(f,f); __builtin_nexttowardf(f,f);__builtin_nexttowardl(f,f); // NO__ERRNO: declare double @nexttoward(double, x86_fp80) [[READNONE]] // NO__ERRNO: declare float @nexttowardf(float, x86_fp80) [[READNONE]] // NO__ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @nexttoward(double, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare float @nexttowardf(float, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nexttoward(double, x86_fp80) [[NOT_READNONE]] +// HAS_ERRNO: declare float @nexttowardf(float, x86_fp80) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_remainder(f,f); __builtin_remainderf(f,f); __builtin_remainderl(f,f); // NO__ERRNO: declare double @remainder(double, double) [[READNONE]] // NO__ERRNO: declare float @remainderf(float, float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @remainder(double, double) [[READNONE]] -// HAS_ERRNO: declare float @remainderf(float, float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @remainder(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @remainderf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[NOT_READNONE]] __builtin_remquo(f,f,i); __builtin_remquof(f,f,i); __builtin_remquol(f,f,i); @@ -495,72 +495,72 @@ void foo() { // NO__ERRNO: declare double @scalbln(double, i64) [[READNONE]] // NO__ERRNO: declare float @scalblnf(float, i64) [[READNONE]] // NO__ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[READNONE]] -// HAS_ERRNO: declare double @scalbln(double, i64) [[READNONE]] -// HAS_ERRNO: declare float @scalblnf(float, i64) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[READNONE]] +// HAS_ERRNO: declare double @scalbln(double, i64) [[NOT_READNONE]] +// HAS_ERRNO: declare float @scalblnf(float, i64) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[NOT_READNONE]] __builtin_scalbn(f,f); __builtin_scalbnf(f,f); __builtin_scalbnl(f,f); // NO__ERRNO: declare double @scalbn(double, i32) [[READNONE]] // NO__ERRNO: declare float @scalbnf(float, i32) [[READNONE]] // NO__ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[READNONE]] -// HAS_ERRNO: declare double @scalbn(double, i32) [[READNONE]] -// HAS_ERRNO: declare float @scalbnf(float, i32) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[READNONE]] +// HAS_ERRNO: declare double @scalbn(double, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare float @scalbnf(float, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[NOT_READNONE]] __builtin_sin(f); __builtin_sinf(f); __builtin_sinl(f); // NO__ERRNO: declare double @sin(double) [[READNONE]] // NO__ERRNO: declare float @sinf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @sinl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @sin(double) [[READNONE]] -// HAS_ERRNO: declare float @sinf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @sinl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sin(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @sinf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @sinl(x86_fp80) [[NOT_READNONE]] __builtin_sinh(f); __builtin_sinhf(f); __builtin_sinhl(f); // NO__ERRNO: declare double @sinh(double) [[READNONE]] // NO__ERRNO: declare float @sinhf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @sinh(double) [[READNONE]] -// HAS_ERRNO: declare float @sinhf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sinh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @sinhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[NOT_READNONE]] __builtin_sqrt(f); __builtin_sqrtf(f); __builtin_sqrtl(f); // NO__ERRNO: declare double @sqrt(double) [[READNONE]] // NO__ERRNO: declare float @sqrtf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @sqrt(double) [[READNONE]] -// HAS_ERRNO: declare float @sqrtf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sqrt(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @sqrtf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[NOT_READNONE]] __builtin_tan(f); __builtin_tanf(f); __builtin_tanl(f); // NO__ERRNO: declare double @tan(double) [[READNONE]] // NO__ERRNO: declare float @tanf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @tanl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @tan(double) [[READNONE]] -// HAS_ERRNO: declare float @tanf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @tanl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tan(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @tanf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @tanl(x86_fp80) [[NOT_READNONE]] __builtin_tanh(f); __builtin_tanhf(f); __builtin_tanhl(f); // NO__ERRNO: declare double @tanh(double) [[READNONE]] // NO__ERRNO: declare float @tanhf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @tanh(double) [[READNONE]] -// HAS_ERRNO: declare float @tanhf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tanh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @tanhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[NOT_READNONE]] __builtin_tgamma(f); __builtin_tgammaf(f); __builtin_tgammal(f); // NO__ERRNO: declare double @tgamma(double) [[READNONE]] // NO__ERRNO: declare float @tgammaf(float) [[READNONE]] // NO__ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[READNONE]] -// HAS_ERRNO: declare double @tgamma(double) [[READNONE]] -// HAS_ERRNO: declare float @tgammaf(float) [[READNONE]] -// HAS_ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tgamma(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @tgammaf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[NOT_READNONE]] __builtin_trunc(f); __builtin_truncf(f); __builtin_truncl(f); @@ -771,7 +771,7 @@ void foo() { // NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } -// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } -// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } diff --git a/test/CodeGen/builtin-sqrt.c b/test/CodeGen/builtin-sqrt.c index f93c5926d5..528ad09517 100644 --- a/test/CodeGen/builtin-sqrt.c +++ b/test/CodeGen/builtin-sqrt.c @@ -1,9 +1,7 @@ // RUN: %clang_cc1 -fmath-errno -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s --check-prefix=HAS_ERRNO // RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s --check-prefix=NO_ERRNO -// FIXME: If a builtin is supposed to have identical semantics to its libm twin, then it -// should not be marked "constant" in Builtins.def because that means it can't set errno. -// Note that both runs have 'readnone' on the libcall here. +// FIXME: If the builtin does not set errno, it should be converted to an LLVM intrinsic. float foo(float X) { // HAS_ERRNO: call float @sqrtf(float @@ -12,7 +10,7 @@ float foo(float X) { } // HAS_ERRNO: declare float @sqrtf(float) [[ATTR:#[0-9]+]] -// HAS_ERRNO: attributes [[ATTR]] = { nounwind readnone {{.*}}} +// HAS_ERRNO-NOT: attributes [[ATTR]] = {{{.*}} readnone // NO_ERRNO: declare float @sqrtf(float) [[ATTR:#[0-9]+]] // NO_ERRNO: attributes [[ATTR]] = { nounwind readnone {{.*}}} -- cgit v1.2.3 From 05b45eab313143ee8429824208c42f30e24bb013 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Thu, 2 Nov 2017 21:08:00 +0000 Subject: Add default calling convention support for regcall. Added support for regcall as default calling convention. Also added code to exclude main when applying default calling conventions. Patch-By: eandrews Differential Revision: https://reviews.llvm.org/D39210 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317268 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/LangOptions.h | 3 ++- include/clang/Driver/CC1Options.td | 2 +- include/clang/Driver/CLCompatOptions.td | 2 ++ lib/AST/ASTContext.cpp | 5 +++++ lib/Driver/ToolChains/Clang.cpp | 7 ++++++- lib/Frontend/CompilerInvocation.cpp | 7 ++++--- lib/Sema/SemaDecl.cpp | 7 +++++++ test/CodeGenCXX/default_calling_conv.cpp | 13 ++++++++++++- test/Driver/cl-cc-flags.c | 3 +++ 9 files changed, 42 insertions(+), 7 deletions(-) diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 51fb5ad661..f7a43adefa 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -77,7 +77,8 @@ public: DCC_CDecl, DCC_FastCall, DCC_StdCall, - DCC_VectorCall + DCC_VectorCall, + DCC_RegCall }; enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index bca51b593a..348a42f4b3 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -704,7 +704,7 @@ def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">, HelpText<"Allow function arguments and returns of type half">; def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, - HelpText<"Set default MS calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall">; + HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">; def finclude_default_header : Flag<["-"], "finclude-default-header">, HelpText<"Include the default header file for OpenCL">; def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">, diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index aebb36ed0e..68a9a8136c 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -302,6 +302,8 @@ def _SLASH_Gz : CLFlag<"Gz">, HelpText<"Set __stdcall as a default calling convention">; def _SLASH_Gv : CLFlag<"Gv">, HelpText<"Set __vectorcall as a default calling convention">; +def _SLASH_Gregcall : CLFlag<"Gregcall">, + HelpText<"Set __regcall as a default calling convention">; // Ignored: diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 87d096dab0..8247d1a23e 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -9281,6 +9281,11 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, if (!IsVariadic) return CC_X86VectorCall; break; + case LangOptions::DCC_RegCall: + // __regcall cannot be applied to variadic functions. + if (!IsVariadic) + return CC_X86RegCall; + break; } return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); } diff --git a/lib/Driver/ToolChains/Clang.cpp b/lib/Driver/ToolChains/Clang.cpp index c1c8813cc4..6ba5d048a4 100644 --- a/lib/Driver/ToolChains/Clang.cpp +++ b/lib/Driver/ToolChains/Clang.cpp @@ -4972,7 +4972,8 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, // Parse the default calling convention options. if (Arg *CCArg = Args.getLastArg(options::OPT__SLASH_Gd, options::OPT__SLASH_Gr, - options::OPT__SLASH_Gz, options::OPT__SLASH_Gv)) { + options::OPT__SLASH_Gz, options::OPT__SLASH_Gv, + options::OPT__SLASH_Gregcall)) { unsigned DCCOptId = CCArg->getOption().getID(); const char *DCCFlag = nullptr; bool ArchSupported = true; @@ -4993,6 +4994,10 @@ void Clang::AddClangCLArgs(const ArgList &Args, types::ID InputType, ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64; DCCFlag = "-fdefault-calling-conv=vectorcall"; break; + case options::OPT__SLASH_Gregcall: + ArchSupported = Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64; + DCCFlag = "-fdefault-calling-conv=regcall"; + break; } // MSVC doesn't warn if /Gr or /Gz is used on x64, so we don't either. diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 2c0d99b4be..692b20bd3a 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -2310,12 +2310,12 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Check for MS default calling conventions being specified. if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { LangOptions::DefaultCallingConvention DefaultCC = - llvm::StringSwitch( - A->getValue()) + llvm::StringSwitch(A->getValue()) .Case("cdecl", LangOptions::DCC_CDecl) .Case("fastcall", LangOptions::DCC_FastCall) .Case("stdcall", LangOptions::DCC_StdCall) .Case("vectorcall", LangOptions::DCC_VectorCall) + .Case("regcall", LangOptions::DCC_RegCall) .Default(LangOptions::DCC_None); if (DefaultCC == LangOptions::DCC_None) Diags.Report(diag::err_drv_invalid_value) @@ -2326,7 +2326,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, bool emitError = (DefaultCC == LangOptions::DCC_FastCall || DefaultCC == LangOptions::DCC_StdCall) && Arch != llvm::Triple::x86; - emitError |= DefaultCC == LangOptions::DCC_VectorCall && + emitError |= (DefaultCC == LangOptions::DCC_VectorCall || + DefaultCC == LangOptions::DCC_RegCall) && !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); if (emitError) Diags.Report(diag::err_drv_argument_not_allowed_with) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 0c00ef7e26..ab1a66ad8f 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9673,6 +9673,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { assert(T->isFunctionType() && "function decl is not of function type"); const FunctionType* FT = T->castAs(); + // Set default calling convention for main() + if (FT->getCallConv() != CC_C) { + FT = Context.adjustFunctionType(FT, FT->getExtInfo().withCallingConv(CC_C)); + FD->setType(QualType(FT, 0)); + T = Context.getCanonicalType(FD->getType()); + } + if (getLangOpts().GNUMode && !getLangOpts().CPlusPlus) { // In C with GNU extensions we allow main() to have non-integer return // type, but we should warn about the extension, and we disable the diff --git a/test/CodeGenCXX/default_calling_conv.cpp b/test/CodeGenCXX/default_calling_conv.cpp index 15eedc8e31..b5b0f47ceb 100644 --- a/test/CodeGenCXX/default_calling_conv.cpp +++ b/test/CodeGenCXX/default_calling_conv.cpp @@ -3,18 +3,21 @@ // RUN: %clang_cc1 -triple i486-unknown-linux-gnu -fdefault-calling-conv=stdcall -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL // RUN: %clang_cc1 -triple i486-unknown-linux-gnu -mrtd -emit-llvm -o - %s | FileCheck %s --check-prefix=STDCALL --check-prefix=ALL // RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=vectorcall -emit-llvm -o - %s | FileCheck %s --check-prefix=VECTORCALL --check-prefix=ALL +// RUN: %clang_cc1 -triple i986-unknown-linux-gnu -fdefault-calling-conv=regcall -emit-llvm -o - %s | FileCheck %s --check-prefix=REGCALL --check-prefix=ALL // CDECL: define void @_Z5test1v // FASTCALL: define x86_fastcallcc void @_Z5test1v // STDCALL: define x86_stdcallcc void @_Z5test1v // VECTORCALL: define x86_vectorcallcc void @_Z5test1v +// REGCALL: define x86_regcallcc void @_Z17__regcall3__test1v void test1() {} -// fastcall, stdcall, and vectorcall all do not support variadic functions. +// fastcall, stdcall, vectorcall and regcall do not support variadic functions. // CDECL: define void @_Z12testVariadicz // FASTCALL: define void @_Z12testVariadicz // STDCALL: define void @_Z12testVariadicz // VECTORCALL: define void @_Z12testVariadicz +// REGCALL: define void @_Z12testVariadicz void testVariadic(...){} // ALL: define void @_Z5test2v @@ -29,6 +32,9 @@ void __attribute__((stdcall)) test4() {} // ALL: define x86_vectorcallcc void @_Z5test5v void __attribute__((vectorcall)) test5() {} +// ALL: define x86_regcallcc void @_Z17__regcall3__test6v +void __attribute__((regcall)) test6() {} + // ALL: define linkonce_odr void @_ZN1A11test_memberEv class A { public: @@ -39,3 +45,8 @@ void test() { A a; a.test_member(); } + +// ALL: define i32 @main +int main() { + return 1; +} diff --git a/test/Driver/cl-cc-flags.c b/test/Driver/cl-cc-flags.c index 76f116e199..d74062a656 100644 --- a/test/Driver/cl-cc-flags.c +++ b/test/Driver/cl-cc-flags.c @@ -13,6 +13,9 @@ // RUN: %clang_cl --target=i686-windows-msvc /Gv -### -- %s 2>&1 | FileCheck --check-prefix=VECTORCALL %s // VECTORCALL: -fdefault-calling-conv=vectorcall +// RUN: %clang_cl --target=i686-windows-msvc /Gregcall -### -- %s 2>&1 | FileCheck --check-prefix=REGCALL %s +// REGCALL: -fdefault-calling-conv=regcall + // Last one should win: // RUN: %clang_cl --target=i686-windows-msvc /Gd /Gv -### -- %s 2>&1 | FileCheck --check-prefix=LASTWINS_VECTOR %s -- cgit v1.2.3 From f86fcb268fec5ab278a4420af40bfd9e4f298b76 Mon Sep 17 00:00:00 2001 From: Eugene Zelenko Date: Thu, 2 Nov 2017 21:45:30 +0000 Subject: [Serialization] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317273 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Serialization/ASTBitCodes.h | 411 ++++++++++++++++++++--- include/clang/Serialization/ContinuousRangeMap.h | 34 +- lib/Serialization/MultiOnDiskHashTable.h | 69 ++-- 3 files changed, 424 insertions(+), 90 deletions(-) diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 42c62257ad..34a7bb3301 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -14,17 +14,23 @@ // respective lists. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #include "clang/AST/DeclarationName.h" #include "clang/AST/Type.h" -#include "llvm/ADT/DenseMap.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Bitcode/BitCodes.h" -#include "llvm/Support/DataTypes.h" +#include +#include namespace clang { - namespace serialization { +namespace serialization { + /// \brief AST file major version number supported by this version of /// Clang. /// @@ -52,7 +58,7 @@ namespace clang { /// /// The ID numbers of identifiers are consecutive (in order of discovery) /// and start at 1. 0 is reserved for NULL. - typedef uint32_t IdentifierID; + using IdentifierID = uint32_t; /// \brief An ID number that refers to a declaration in an AST file. /// @@ -60,12 +66,12 @@ namespace clang { /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved. /// At the start of a chain of precompiled headers, declaration ID 1 is /// used for the translation unit declaration. - typedef uint32_t DeclID; + using DeclID = uint32_t; // FIXME: Turn these into classes so we can have some type safety when // we go from local ID to global and vice-versa. - typedef DeclID LocalDeclID; - typedef DeclID GlobalDeclID; + using LocalDeclID = DeclID; + using GlobalDeclID = DeclID; /// \brief An ID number that refers to a type in an AST file. /// @@ -77,22 +83,25 @@ namespace clang { /// IDs (based on the PREDEF_TYPE_*_ID constants), with 0 as a /// placeholder for "no type". Values from NUM_PREDEF_TYPE_IDs are /// other types that have serialized representations. - typedef uint32_t TypeID; + using TypeID = uint32_t; /// \brief A type index; the type ID with the qualifier bits removed. class TypeIdx { - uint32_t Idx; + uint32_t Idx = 0; + public: - TypeIdx() : Idx(0) { } - explicit TypeIdx(uint32_t index) : Idx(index) { } + TypeIdx() = default; + explicit TypeIdx(uint32_t index) : Idx(index) {} uint32_t getIndex() const { return Idx; } + TypeID asTypeID(unsigned FastQuals) const { if (Idx == uint32_t(-1)) return TypeID(-1); return (Idx << Qualifiers::FastWidth) | FastQuals; } + static TypeIdx fromTypeID(TypeID ID) { if (ID == TypeID(-1)) return TypeIdx(-1); @@ -104,14 +113,17 @@ namespace clang { /// A structure for putting "fast"-unqualified QualTypes into a /// DenseMap. This uses the standard pointer hash function. struct UnsafeQualTypeDenseMapInfo { - static inline bool isEqual(QualType A, QualType B) { return A == B; } - static inline QualType getEmptyKey() { + static bool isEqual(QualType A, QualType B) { return A == B; } + + static QualType getEmptyKey() { return QualType::getFromOpaquePtr((void*) 1); } - static inline QualType getTombstoneKey() { + + static QualType getTombstoneKey() { return QualType::getFromOpaquePtr((void*) 2); } - static inline unsigned getHashValue(QualType T) { + + static unsigned getHashValue(QualType T) { assert(!T.getLocalFastQualifiers() && "hash invalid for types with fast quals"); uintptr_t v = reinterpret_cast(T.getAsOpaquePtr()); @@ -120,44 +132,44 @@ namespace clang { }; /// \brief An ID number that refers to an identifier in an AST file. - typedef uint32_t IdentID; + using IdentID = uint32_t; /// \brief The number of predefined identifier IDs. const unsigned int NUM_PREDEF_IDENT_IDS = 1; /// \brief An ID number that refers to a macro in an AST file. - typedef uint32_t MacroID; + using MacroID = uint32_t; /// \brief A global ID number that refers to a macro in an AST file. - typedef uint32_t GlobalMacroID; + using GlobalMacroID = uint32_t; /// \brief A local to a module ID number that refers to a macro in an /// AST file. - typedef uint32_t LocalMacroID; + using LocalMacroID = uint32_t; /// \brief The number of predefined macro IDs. const unsigned int NUM_PREDEF_MACRO_IDS = 1; /// \brief An ID number that refers to an ObjC selector in an AST file. - typedef uint32_t SelectorID; + using SelectorID = uint32_t; /// \brief The number of predefined selector IDs. const unsigned int NUM_PREDEF_SELECTOR_IDS = 1; /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an /// AST file. - typedef uint32_t CXXBaseSpecifiersID; + using CXXBaseSpecifiersID = uint32_t; /// \brief An ID number that refers to a list of CXXCtorInitializers in an /// AST file. - typedef uint32_t CXXCtorInitializersID; + using CXXCtorInitializersID = uint32_t; /// \brief An ID number that refers to an entity in the detailed /// preprocessing record. - typedef uint32_t PreprocessedEntityID; + using PreprocessedEntityID = uint32_t; /// \brief An ID number that refers to a submodule in a module file. - typedef uint32_t SubmoduleID; + using SubmoduleID = uint32_t; /// \brief The number of predefined submodule IDs. const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1; @@ -166,18 +178,21 @@ namespace clang { struct PPEntityOffset { /// \brief Raw source location of beginning of range. unsigned Begin; + /// \brief Raw source location of end of range. unsigned End; + /// \brief Offset in the AST file. uint32_t BitOffset; PPEntityOffset(SourceRange R, uint32_t BitOffset) : Begin(R.getBegin().getRawEncoding()), - End(R.getEnd().getRawEncoding()), - BitOffset(BitOffset) { } + End(R.getEnd().getRawEncoding()), BitOffset(BitOffset) {} + SourceLocation getBegin() const { return SourceLocation::getFromRawEncoding(Begin); } + SourceLocation getEnd() const { return SourceLocation::getFromRawEncoding(End); } @@ -186,17 +201,19 @@ namespace clang { /// \brief Source range/offset of a preprocessed entity. struct DeclOffset { /// \brief Raw source location. - unsigned Loc; + unsigned Loc = 0; + /// \brief Offset in the AST file. - uint32_t BitOffset; + uint32_t BitOffset = 0; - DeclOffset() : Loc(0), BitOffset(0) { } + DeclOffset() = default; DeclOffset(SourceLocation Loc, uint32_t BitOffset) - : Loc(Loc.getRawEncoding()), - BitOffset(BitOffset) { } + : Loc(Loc.getRawEncoding()), BitOffset(BitOffset) {} + void setLocation(SourceLocation L) { Loc = L.getRawEncoding(); } + SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Loc); } @@ -617,17 +634,21 @@ namespace clang { /// \brief Describes a source location entry (SLocEntry) for a /// file. SM_SLOC_FILE_ENTRY = 1, + /// \brief Describes a source location entry (SLocEntry) for a /// buffer. SM_SLOC_BUFFER_ENTRY = 2, + /// \brief Describes a blob that contains the data for a buffer /// entry. This kind of record always directly follows a /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an /// overridden buffer. SM_SLOC_BUFFER_BLOB = 3, + /// \brief Describes a zlib-compressed blob that contains the data for /// a buffer entry. SM_SLOC_BUFFER_BLOB_COMPRESSED = 4, + /// \brief Describes a source location entry (SLocEntry) for a /// macro expansion. SM_SLOC_EXPANSION_ENTRY = 5 @@ -676,46 +697,63 @@ namespace clang { enum SubmoduleRecordTypes { /// \brief Metadata for submodules as a whole. SUBMODULE_METADATA = 0, + /// \brief Defines the major attributes of a submodule, including its /// name and parent. SUBMODULE_DEFINITION = 1, + /// \brief Specifies the umbrella header used to create this module, /// if any. SUBMODULE_UMBRELLA_HEADER = 2, + /// \brief Specifies a header that falls into this (sub)module. SUBMODULE_HEADER = 3, + /// \brief Specifies a top-level header that falls into this (sub)module. SUBMODULE_TOPHEADER = 4, + /// \brief Specifies an umbrella directory. SUBMODULE_UMBRELLA_DIR = 5, + /// \brief Specifies the submodules that are imported by this /// submodule. SUBMODULE_IMPORTS = 6, + /// \brief Specifies the submodules that are re-exported from this /// submodule. SUBMODULE_EXPORTS = 7, + /// \brief Specifies a required feature. SUBMODULE_REQUIRES = 8, + /// \brief Specifies a header that has been explicitly excluded /// from this submodule. SUBMODULE_EXCLUDED_HEADER = 9, + /// \brief Specifies a library or framework to link against. SUBMODULE_LINK_LIBRARY = 10, + /// \brief Specifies a configuration macro for this module. SUBMODULE_CONFIG_MACRO = 11, + /// \brief Specifies a conflict with another module. SUBMODULE_CONFLICT = 12, + /// \brief Specifies a header that is private to this submodule. SUBMODULE_PRIVATE_HEADER = 13, + /// \brief Specifies a header that is part of the module but must be /// textually included. SUBMODULE_TEXTUAL_HEADER = 14, + /// \brief Specifies a header that is private to this submodule but /// must be textually included. SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15, + /// \brief Specifies some declarations with initializers that must be /// emitted to initialize the module. SUBMODULE_INITIALIZERS = 16, + /// \brief Specifies the name of the module that will eventually /// re-export the entities in this module. SUBMODULE_EXPORT_AS = 17, @@ -743,94 +781,139 @@ namespace clang { enum PredefinedTypeIDs { /// \brief The NULL type. PREDEF_TYPE_NULL_ID = 0, + /// \brief The void type. PREDEF_TYPE_VOID_ID = 1, + /// \brief The 'bool' or '_Bool' type. PREDEF_TYPE_BOOL_ID = 2, + /// \brief The 'char' type, when it is unsigned. PREDEF_TYPE_CHAR_U_ID = 3, + /// \brief The 'unsigned char' type. PREDEF_TYPE_UCHAR_ID = 4, + /// \brief The 'unsigned short' type. PREDEF_TYPE_USHORT_ID = 5, + /// \brief The 'unsigned int' type. PREDEF_TYPE_UINT_ID = 6, + /// \brief The 'unsigned long' type. PREDEF_TYPE_ULONG_ID = 7, + /// \brief The 'unsigned long long' type. PREDEF_TYPE_ULONGLONG_ID = 8, + /// \brief The 'char' type, when it is signed. PREDEF_TYPE_CHAR_S_ID = 9, + /// \brief The 'signed char' type. PREDEF_TYPE_SCHAR_ID = 10, + /// \brief The C++ 'wchar_t' type. PREDEF_TYPE_WCHAR_ID = 11, + /// \brief The (signed) 'short' type. PREDEF_TYPE_SHORT_ID = 12, + /// \brief The (signed) 'int' type. PREDEF_TYPE_INT_ID = 13, + /// \brief The (signed) 'long' type. PREDEF_TYPE_LONG_ID = 14, + /// \brief The (signed) 'long long' type. PREDEF_TYPE_LONGLONG_ID = 15, + /// \brief The 'float' type. PREDEF_TYPE_FLOAT_ID = 16, + /// \brief The 'double' type. PREDEF_TYPE_DOUBLE_ID = 17, + /// \brief The 'long double' type. PREDEF_TYPE_LONGDOUBLE_ID = 18, + /// \brief The placeholder type for overloaded function sets. PREDEF_TYPE_OVERLOAD_ID = 19, + /// \brief The placeholder type for dependent types. PREDEF_TYPE_DEPENDENT_ID = 20, + /// \brief The '__uint128_t' type. PREDEF_TYPE_UINT128_ID = 21, + /// \brief The '__int128_t' type. PREDEF_TYPE_INT128_ID = 22, + /// \brief The type of 'nullptr'. PREDEF_TYPE_NULLPTR_ID = 23, + /// \brief The C++ 'char16_t' type. PREDEF_TYPE_CHAR16_ID = 24, + /// \brief The C++ 'char32_t' type. PREDEF_TYPE_CHAR32_ID = 25, + /// \brief The ObjC 'id' type. PREDEF_TYPE_OBJC_ID = 26, + /// \brief The ObjC 'Class' type. PREDEF_TYPE_OBJC_CLASS = 27, + /// \brief The ObjC 'SEL' type. PREDEF_TYPE_OBJC_SEL = 28, + /// \brief The 'unknown any' placeholder type. PREDEF_TYPE_UNKNOWN_ANY = 29, + /// \brief The placeholder type for bound member functions. PREDEF_TYPE_BOUND_MEMBER = 30, + /// \brief The "auto" deduction type. PREDEF_TYPE_AUTO_DEDUCT = 31, + /// \brief The "auto &&" deduction type. PREDEF_TYPE_AUTO_RREF_DEDUCT = 32, + /// \brief The OpenCL 'half' / ARM NEON __fp16 type. PREDEF_TYPE_HALF_ID = 33, + /// \brief ARC's unbridged-cast placeholder type. PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34, + /// \brief The pseudo-object placeholder type. PREDEF_TYPE_PSEUDO_OBJECT = 35, + /// \brief The placeholder type for builtin functions. PREDEF_TYPE_BUILTIN_FN = 36, + /// \brief OpenCL event type. PREDEF_TYPE_EVENT_ID = 37, + /// \brief OpenCL clk event type. PREDEF_TYPE_CLK_EVENT_ID = 38, + /// \brief OpenCL sampler type. PREDEF_TYPE_SAMPLER_ID = 39, + /// \brief OpenCL queue type. PREDEF_TYPE_QUEUE_ID = 40, + /// \brief OpenCL reserve_id type. PREDEF_TYPE_RESERVE_ID_ID = 41, + /// \brief The placeholder type for OpenMP array section. PREDEF_TYPE_OMP_ARRAY_SECTION = 42, + /// \brief The '__float128' type PREDEF_TYPE_FLOAT128_ID = 43, + /// \brief The '_Float16' type PREDEF_TYPE_FLOAT16_ID = 44, + /// \brief OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, @@ -853,94 +936,139 @@ namespace clang { enum TypeCode { /// \brief An ExtQualType record. TYPE_EXT_QUAL = 1, + /// \brief A ComplexType record. TYPE_COMPLEX = 3, + /// \brief A PointerType record. TYPE_POINTER = 4, + /// \brief A BlockPointerType record. TYPE_BLOCK_POINTER = 5, + /// \brief An LValueReferenceType record. TYPE_LVALUE_REFERENCE = 6, + /// \brief An RValueReferenceType record. TYPE_RVALUE_REFERENCE = 7, + /// \brief A MemberPointerType record. TYPE_MEMBER_POINTER = 8, + /// \brief A ConstantArrayType record. TYPE_CONSTANT_ARRAY = 9, + /// \brief An IncompleteArrayType record. TYPE_INCOMPLETE_ARRAY = 10, + /// \brief A VariableArrayType record. TYPE_VARIABLE_ARRAY = 11, + /// \brief A VectorType record. TYPE_VECTOR = 12, + /// \brief An ExtVectorType record. TYPE_EXT_VECTOR = 13, + /// \brief A FunctionNoProtoType record. TYPE_FUNCTION_NO_PROTO = 14, + /// \brief A FunctionProtoType record. TYPE_FUNCTION_PROTO = 15, + /// \brief A TypedefType record. TYPE_TYPEDEF = 16, + /// \brief A TypeOfExprType record. TYPE_TYPEOF_EXPR = 17, + /// \brief A TypeOfType record. TYPE_TYPEOF = 18, + /// \brief A RecordType record. TYPE_RECORD = 19, + /// \brief An EnumType record. TYPE_ENUM = 20, + /// \brief An ObjCInterfaceType record. TYPE_OBJC_INTERFACE = 21, + /// \brief An ObjCObjectPointerType record. TYPE_OBJC_OBJECT_POINTER = 22, + /// \brief a DecltypeType record. TYPE_DECLTYPE = 23, + /// \brief An ElaboratedType record. TYPE_ELABORATED = 24, + /// \brief A SubstTemplateTypeParmType record. TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, + /// \brief An UnresolvedUsingType record. TYPE_UNRESOLVED_USING = 26, + /// \brief An InjectedClassNameType record. TYPE_INJECTED_CLASS_NAME = 27, + /// \brief An ObjCObjectType record. TYPE_OBJC_OBJECT = 28, + /// \brief An TemplateTypeParmType record. TYPE_TEMPLATE_TYPE_PARM = 29, + /// \brief An TemplateSpecializationType record. TYPE_TEMPLATE_SPECIALIZATION = 30, + /// \brief A DependentNameType record. TYPE_DEPENDENT_NAME = 31, + /// \brief A DependentTemplateSpecializationType record. TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32, + /// \brief A DependentSizedArrayType record. TYPE_DEPENDENT_SIZED_ARRAY = 33, + /// \brief A ParenType record. TYPE_PAREN = 34, + /// \brief A PackExpansionType record. TYPE_PACK_EXPANSION = 35, + /// \brief An AttributedType record. TYPE_ATTRIBUTED = 36, + /// \brief A SubstTemplateTypeParmPackType record. TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37, + /// \brief A AutoType record. TYPE_AUTO = 38, + /// \brief A UnaryTransformType record. TYPE_UNARY_TRANSFORM = 39, + /// \brief An AtomicType record. TYPE_ATOMIC = 40, + /// \brief A DecayedType record. TYPE_DECAYED = 41, + /// \brief An AdjustedType record. TYPE_ADJUSTED = 42, + /// \brief A PipeType record. TYPE_PIPE = 43, + /// \brief An ObjCTypeParamType record. TYPE_OBJC_TYPE_PARAM = 44, + /// \brief A DeducedTemplateSpecializationType record. TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45, + /// \brief A DependentSizedExtVectorType record. TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46, + /// \brief A DependentAddressSpaceType record. TYPE_DEPENDENT_ADDRESS_SPACE = 47 }; @@ -953,18 +1081,25 @@ namespace clang { enum SpecialTypeIDs { /// \brief CFConstantString type SPECIAL_TYPE_CF_CONSTANT_STRING = 0, + /// \brief C FILE typedef type SPECIAL_TYPE_FILE = 1, + /// \brief C jmp_buf typedef type SPECIAL_TYPE_JMP_BUF = 2, + /// \brief C sigjmp_buf typedef type SPECIAL_TYPE_SIGJMP_BUF = 3, + /// \brief Objective-C "id" redefinition type SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4, + /// \brief Objective-C "Class" redefinition type SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5, + /// \brief Objective-C "SEL" redefinition type SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6, + /// \brief C ucontext_t typedef type SPECIAL_TYPE_UCONTEXT_T = 7 }; @@ -1055,57 +1190,84 @@ namespace clang { /// \brief A TypedefDecl record. DECL_TYPEDEF = 51, /// \brief A TypeAliasDecl record. + DECL_TYPEALIAS, + /// \brief An EnumDecl record. DECL_ENUM, + /// \brief A RecordDecl record. DECL_RECORD, + /// \brief An EnumConstantDecl record. DECL_ENUM_CONSTANT, + /// \brief A FunctionDecl record. DECL_FUNCTION, + /// \brief A ObjCMethodDecl record. DECL_OBJC_METHOD, + /// \brief A ObjCInterfaceDecl record. DECL_OBJC_INTERFACE, + /// \brief A ObjCProtocolDecl record. DECL_OBJC_PROTOCOL, + /// \brief A ObjCIvarDecl record. DECL_OBJC_IVAR, + /// \brief A ObjCAtDefsFieldDecl record. DECL_OBJC_AT_DEFS_FIELD, + /// \brief A ObjCCategoryDecl record. DECL_OBJC_CATEGORY, + /// \brief A ObjCCategoryImplDecl record. DECL_OBJC_CATEGORY_IMPL, + /// \brief A ObjCImplementationDecl record. DECL_OBJC_IMPLEMENTATION, + /// \brief A ObjCCompatibleAliasDecl record. DECL_OBJC_COMPATIBLE_ALIAS, + /// \brief A ObjCPropertyDecl record. DECL_OBJC_PROPERTY, + /// \brief A ObjCPropertyImplDecl record. DECL_OBJC_PROPERTY_IMPL, + /// \brief A FieldDecl record. DECL_FIELD, + /// \brief A MSPropertyDecl record. DECL_MS_PROPERTY, + /// \brief A VarDecl record. DECL_VAR, + /// \brief An ImplicitParamDecl record. DECL_IMPLICIT_PARAM, + /// \brief A ParmVarDecl record. DECL_PARM_VAR, + /// \brief A DecompositionDecl record. DECL_DECOMPOSITION, + /// \brief A BindingDecl record. DECL_BINDING, + /// \brief A FileScopeAsmDecl record. DECL_FILE_SCOPE_ASM, + /// \brief A BlockDecl record. DECL_BLOCK, + /// \brief A CapturedDecl record. DECL_CAPTURED, + /// \brief A record that stores the set of declarations that are /// lexically stored within a given DeclContext. /// @@ -1115,6 +1277,7 @@ namespace clang { /// the contents of a DeclContext, e.g., via /// DeclContext::decls_begin() and DeclContext::decls_end(). DECL_CONTEXT_LEXICAL, + /// \brief A record that stores the set of declarations that are /// visible from a given DeclContext. /// @@ -1123,104 +1286,151 @@ namespace clang { /// IDs. This data is used when performing qualified name lookup /// into a DeclContext via DeclContext::lookup. DECL_CONTEXT_VISIBLE, + /// \brief A LabelDecl record. DECL_LABEL, + /// \brief A NamespaceDecl record. DECL_NAMESPACE, + /// \brief A NamespaceAliasDecl record. DECL_NAMESPACE_ALIAS, + /// \brief A UsingDecl record. DECL_USING, + /// \brief A UsingPackDecl record. DECL_USING_PACK, + /// \brief A UsingShadowDecl record. DECL_USING_SHADOW, + /// \brief A ConstructorUsingShadowDecl record. DECL_CONSTRUCTOR_USING_SHADOW, + /// \brief A UsingDirecitveDecl record. DECL_USING_DIRECTIVE, + /// \brief An UnresolvedUsingValueDecl record. DECL_UNRESOLVED_USING_VALUE, + /// \brief An UnresolvedUsingTypenameDecl record. DECL_UNRESOLVED_USING_TYPENAME, + /// \brief A LinkageSpecDecl record. DECL_LINKAGE_SPEC, + /// \brief An ExportDecl record. DECL_EXPORT, + /// \brief A CXXRecordDecl record. DECL_CXX_RECORD, + /// \brief A CXXDeductionGuideDecl record. DECL_CXX_DEDUCTION_GUIDE, + /// \brief A CXXMethodDecl record. DECL_CXX_METHOD, + /// \brief A CXXConstructorDecl record. DECL_CXX_CONSTRUCTOR, + /// \brief A CXXConstructorDecl record for an inherited constructor. DECL_CXX_INHERITED_CONSTRUCTOR, + /// \brief A CXXDestructorDecl record. DECL_CXX_DESTRUCTOR, + /// \brief A CXXConversionDecl record. DECL_CXX_CONVERSION, + /// \brief An AccessSpecDecl record. DECL_ACCESS_SPEC, /// \brief A FriendDecl record. DECL_FRIEND, + /// \brief A FriendTemplateDecl record. DECL_FRIEND_TEMPLATE, + /// \brief A ClassTemplateDecl record. DECL_CLASS_TEMPLATE, + /// \brief A ClassTemplateSpecializationDecl record. DECL_CLASS_TEMPLATE_SPECIALIZATION, + /// \brief A ClassTemplatePartialSpecializationDecl record. DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, + /// \brief A VarTemplateDecl record. DECL_VAR_TEMPLATE, + /// \brief A VarTemplateSpecializationDecl record. DECL_VAR_TEMPLATE_SPECIALIZATION, + /// \brief A VarTemplatePartialSpecializationDecl record. DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION, + /// \brief A FunctionTemplateDecl record. DECL_FUNCTION_TEMPLATE, + /// \brief A TemplateTypeParmDecl record. DECL_TEMPLATE_TYPE_PARM, + /// \brief A NonTypeTemplateParmDecl record. DECL_NON_TYPE_TEMPLATE_PARM, + /// \brief A TemplateTemplateParmDecl record. DECL_TEMPLATE_TEMPLATE_PARM, + /// \brief A TypeAliasTemplateDecl record. DECL_TYPE_ALIAS_TEMPLATE, + /// \brief A StaticAssertDecl record. DECL_STATIC_ASSERT, + /// \brief A record containing CXXBaseSpecifiers. DECL_CXX_BASE_SPECIFIERS, + /// \brief A record containing CXXCtorInitializers. DECL_CXX_CTOR_INITIALIZERS, + /// \brief A IndirectFieldDecl record. DECL_INDIRECTFIELD, + /// \brief A NonTypeTemplateParmDecl record that stores an expanded /// non-type template parameter pack. DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK, + /// \brief A TemplateTemplateParmDecl record that stores an expanded /// template template parameter pack. DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK, + /// \brief A ClassScopeFunctionSpecializationDecl record a class scope /// function specialization. (Microsoft extension). DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, + /// \brief An ImportDecl recording a module import. DECL_IMPORT, + /// \brief An OMPThreadPrivateDecl record. DECL_OMP_THREADPRIVATE, + /// \brief An EmptyDecl record. DECL_EMPTY, + /// \brief An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, + /// \brief An OMPCapturedExprDecl record. DECL_OMP_CAPTUREDEXPR, + /// \brief A PragmaCommentDecl record. DECL_PRAGMA_COMMENT, + /// \brief A PragmaDetectMismatchDecl record. DECL_PRAGMA_DETECT_MISMATCH, + /// \brief An OMPDeclareReductionDecl record. DECL_OMP_DECLARE_REDUCTION, }; @@ -1236,128 +1446,190 @@ namespace clang { /// \brief A marker record that indicates that we are at the end /// of an expression. STMT_STOP = 128, + /// \brief A NULL expression. STMT_NULL_PTR, + /// \brief A reference to a previously [de]serialized Stmt record. STMT_REF_PTR, + /// \brief A NullStmt record. STMT_NULL, + /// \brief A CompoundStmt record. STMT_COMPOUND, + /// \brief A CaseStmt record. STMT_CASE, + /// \brief A DefaultStmt record. STMT_DEFAULT, + /// \brief A LabelStmt record. STMT_LABEL, + /// \brief An AttributedStmt record. STMT_ATTRIBUTED, + /// \brief An IfStmt record. STMT_IF, + /// \brief A SwitchStmt record. STMT_SWITCH, + /// \brief A WhileStmt record. STMT_WHILE, + /// \brief A DoStmt record. STMT_DO, + /// \brief A ForStmt record. STMT_FOR, + /// \brief A GotoStmt record. STMT_GOTO, + /// \brief An IndirectGotoStmt record. STMT_INDIRECT_GOTO, + /// \brief A ContinueStmt record. STMT_CONTINUE, + /// \brief A BreakStmt record. STMT_BREAK, + /// \brief A ReturnStmt record. STMT_RETURN, + /// \brief A DeclStmt record. STMT_DECL, + /// \brief A CapturedStmt record. STMT_CAPTURED, + /// \brief A GCC-style AsmStmt record. STMT_GCCASM, + /// \brief A MS-style AsmStmt record. STMT_MSASM, + /// \brief A PredefinedExpr record. EXPR_PREDEFINED, + /// \brief A DeclRefExpr record. EXPR_DECL_REF, + /// \brief An IntegerLiteral record. EXPR_INTEGER_LITERAL, + /// \brief A FloatingLiteral record. EXPR_FLOATING_LITERAL, + /// \brief An ImaginaryLiteral record. EXPR_IMAGINARY_LITERAL, + /// \brief A StringLiteral record. EXPR_STRING_LITERAL, + /// \brief A CharacterLiteral record. EXPR_CHARACTER_LITERAL, + /// \brief A ParenExpr record. EXPR_PAREN, + /// \brief A ParenListExpr record. EXPR_PAREN_LIST, + /// \brief A UnaryOperator record. EXPR_UNARY_OPERATOR, + /// \brief An OffsetOfExpr record. EXPR_OFFSETOF, + /// \brief A SizefAlignOfExpr record. EXPR_SIZEOF_ALIGN_OF, + /// \brief An ArraySubscriptExpr record. EXPR_ARRAY_SUBSCRIPT, + /// \brief A CallExpr record. EXPR_CALL, + /// \brief A MemberExpr record. EXPR_MEMBER, + /// \brief A BinaryOperator record. EXPR_BINARY_OPERATOR, + /// \brief A CompoundAssignOperator record. EXPR_COMPOUND_ASSIGN_OPERATOR, + /// \brief A ConditionOperator record. EXPR_CONDITIONAL_OPERATOR, + /// \brief An ImplicitCastExpr record. EXPR_IMPLICIT_CAST, + /// \brief A CStyleCastExpr record. EXPR_CSTYLE_CAST, + /// \brief A CompoundLiteralExpr record. EXPR_COMPOUND_LITERAL, + /// \brief An ExtVectorElementExpr record. EXPR_EXT_VECTOR_ELEMENT, + /// \brief An InitListExpr record. EXPR_INIT_LIST, + /// \brief A DesignatedInitExpr record. EXPR_DESIGNATED_INIT, + /// \brief A DesignatedInitUpdateExpr record. EXPR_DESIGNATED_INIT_UPDATE, + /// \brief An NoInitExpr record. EXPR_NO_INIT, + /// \brief An ArrayInitLoopExpr record. EXPR_ARRAY_INIT_LOOP, + /// \brief An ArrayInitIndexExpr record. EXPR_ARRAY_INIT_INDEX, + /// \brief An ImplicitValueInitExpr record. EXPR_IMPLICIT_VALUE_INIT, + /// \brief A VAArgExpr record. EXPR_VA_ARG, + /// \brief An AddrLabelExpr record. EXPR_ADDR_LABEL, + /// \brief A StmtExpr record. EXPR_STMT, + /// \brief A ChooseExpr record. EXPR_CHOOSE, + /// \brief A GNUNullExpr record. EXPR_GNU_NULL, + /// \brief A ShuffleVectorExpr record. EXPR_SHUFFLE_VECTOR, + /// \brief A ConvertVectorExpr record. EXPR_CONVERT_VECTOR, + /// \brief BlockExpr EXPR_BLOCK, + /// \brief A GenericSelectionExpr record. EXPR_GENERIC_SELECTION, + /// \brief A PseudoObjectExpr record. EXPR_PSEUDO_OBJECT, + /// \brief An AtomicExpr record. EXPR_ATOMIC, @@ -1369,45 +1641,61 @@ namespace clang { EXPR_OBJC_BOXED_EXPRESSION, EXPR_OBJC_ARRAY_LITERAL, EXPR_OBJC_DICTIONARY_LITERAL, - - + /// \brief An ObjCEncodeExpr record. EXPR_OBJC_ENCODE, + /// \brief An ObjCSelectorExpr record. EXPR_OBJC_SELECTOR_EXPR, + /// \brief An ObjCProtocolExpr record. EXPR_OBJC_PROTOCOL_EXPR, + /// \brief An ObjCIvarRefExpr record. EXPR_OBJC_IVAR_REF_EXPR, + /// \brief An ObjCPropertyRefExpr record. EXPR_OBJC_PROPERTY_REF_EXPR, + /// \brief An ObjCSubscriptRefExpr record. EXPR_OBJC_SUBSCRIPT_REF_EXPR, + /// \brief UNUSED EXPR_OBJC_KVC_REF_EXPR, + /// \brief An ObjCMessageExpr record. EXPR_OBJC_MESSAGE_EXPR, + /// \brief An ObjCIsa Expr record. EXPR_OBJC_ISA, + /// \brief An ObjCIndirectCopyRestoreExpr record. EXPR_OBJC_INDIRECT_COPY_RESTORE, /// \brief An ObjCForCollectionStmt record. STMT_OBJC_FOR_COLLECTION, + /// \brief An ObjCAtCatchStmt record. STMT_OBJC_CATCH, + /// \brief An ObjCAtFinallyStmt record. STMT_OBJC_FINALLY, + /// \brief An ObjCAtTryStmt record. STMT_OBJC_AT_TRY, + /// \brief An ObjCAtSynchronizedStmt record. STMT_OBJC_AT_SYNCHRONIZED, + /// \brief An ObjCAtThrowStmt record. STMT_OBJC_AT_THROW, + /// \brief An ObjCAutoreleasePoolStmt record. STMT_OBJC_AUTORELEASE_POOL, + /// \brief An ObjCBoolLiteralExpr record. EXPR_OBJC_BOOL_LITERAL, + /// \brief An ObjCAvailabilityCheckExpr record. EXPR_OBJC_AVAILABILITY_CHECK, @@ -1415,37 +1703,52 @@ namespace clang { /// \brief A CXXCatchStmt record. STMT_CXX_CATCH, + /// \brief A CXXTryStmt record. STMT_CXX_TRY, /// \brief A CXXForRangeStmt record. + STMT_CXX_FOR_RANGE, /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, + /// \brief A CXXMemberCallExpr record. EXPR_CXX_MEMBER_CALL, + /// \brief A CXXConstructExpr record. EXPR_CXX_CONSTRUCT, + /// \brief A CXXInheritedCtorInitExpr record. EXPR_CXX_INHERITED_CTOR_INIT, + /// \brief A CXXTemporaryObjectExpr record. EXPR_CXX_TEMPORARY_OBJECT, + /// \brief A CXXStaticCastExpr record. EXPR_CXX_STATIC_CAST, + /// \brief A CXXDynamicCastExpr record. EXPR_CXX_DYNAMIC_CAST, + /// \brief A CXXReinterpretCastExpr record. EXPR_CXX_REINTERPRET_CAST, + /// \brief A CXXConstCastExpr record. EXPR_CXX_CONST_CAST, + /// \brief A CXXFunctionalCastExpr record. EXPR_CXX_FUNCTIONAL_CAST, + /// \brief A UserDefinedLiteral record. EXPR_USER_DEFINED_LITERAL, + /// \brief A CXXStdInitializerListExpr record. EXPR_CXX_STD_INITIALIZER_LIST, + /// \brief A CXXBoolLiteralExpr record. EXPR_CXX_BOOL_LITERAL, + EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr EXPR_CXX_TYPEID_EXPR, // CXXTypeidExpr (of expr). EXPR_CXX_TYPEID_TYPE, // CXXTypeidExpr (of type). @@ -1567,11 +1870,14 @@ namespace clang { enum DesignatorTypes { /// \brief Field designator where only the field name is known. DESIG_FIELD_NAME = 0, + /// \brief Field designator where the field has been resolved to /// a declaration. DESIG_FIELD_DECL = 1, + /// \brief Array designator. DESIG_ARRAY = 2, + /// \brief GNU array range designator. DESIG_ARRAY_RANGE = 3 }; @@ -1587,8 +1893,11 @@ namespace clang { /// \brief Describes the redeclarations of a declaration. struct LocalRedeclarationsInfo { - DeclID FirstID; // The ID of the first declaration - unsigned Offset; // Offset into the array of redeclaration chains. + // The ID of the first declaration + DeclID FirstID; + + // Offset into the array of redeclaration chains. + unsigned Offset; friend bool operator<(const LocalRedeclarationsInfo &X, const LocalRedeclarationsInfo &Y) { @@ -1613,8 +1922,11 @@ namespace clang { /// \brief Describes the categories of an Objective-C class. struct ObjCCategoriesInfo { - DeclID DefinitionID; // The ID of the definition - unsigned Offset; // Offset into the array of category lists. + // The ID of the definition + DeclID DefinitionID; + + // Offset into the array of category lists. + unsigned Offset; friend bool operator<(const ObjCCategoriesInfo &X, const ObjCCategoriesInfo &Y) { @@ -1643,15 +1955,14 @@ namespace clang { /// same key can occasionally represent multiple names (for names that /// contain types, in particular). class DeclarationNameKey { - typedef unsigned NameKind; + using NameKind = unsigned; - NameKind Kind; - uint64_t Data; + NameKind Kind = 0; + uint64_t Data = 0; public: - DeclarationNameKey() : Kind(), Data() {} + DeclarationNameKey() = default; DeclarationNameKey(DeclarationName Name); - DeclarationNameKey(NameKind Kind, uint64_t Data) : Kind(Kind), Data(Data) {} @@ -1663,12 +1974,14 @@ namespace clang { Kind == DeclarationName::CXXDeductionGuideName); return (IdentifierInfo *)Data; } + Selector getSelector() const { assert(Kind == DeclarationName::ObjCZeroArgSelector || Kind == DeclarationName::ObjCOneArgSelector || Kind == DeclarationName::ObjCMultiArgSelector); return Selector(Data); } + OverloadedOperatorKind getOperatorKind() const { assert(Kind == DeclarationName::CXXOperatorName); return (OverloadedOperatorKind)Data; @@ -1684,26 +1997,32 @@ namespace clang { }; /// @} - } -} // end namespace clang + +} // namespace serialization +} // namespace clang namespace llvm { + template <> struct DenseMapInfo { static clang::serialization::DeclarationNameKey getEmptyKey() { return clang::serialization::DeclarationNameKey(-1, 1); } + static clang::serialization::DeclarationNameKey getTombstoneKey() { return clang::serialization::DeclarationNameKey(-1, 2); } + static unsigned getHashValue(const clang::serialization::DeclarationNameKey &Key) { return Key.getHash(); } + static bool isEqual(const clang::serialization::DeclarationNameKey &L, const clang::serialization::DeclarationNameKey &R) { return L == R; } }; -} -#endif +} // namespace llvm + +#endif // LLVM_CLANG_SERIALIZATION_ASTBITCODES_H diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index 244b01b22a..24bfadd0f8 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -1,4 +1,4 @@ -//===--- ContinuousRangeMap.h - Map with int range as key -------*- C++ -*-===// +//===- ContinuousRangeMap.h - Map with int range as key ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" #include +#include #include namespace clang { @@ -35,14 +36,15 @@ namespace clang { template class ContinuousRangeMap { public: - typedef std::pair value_type; - typedef value_type &reference; - typedef const value_type &const_reference; - typedef value_type *pointer; - typedef const value_type *const_pointer; + using value_type = std::pair; + using reference = value_type &; + using const_reference = const value_type &; + using pointer = value_type *; + using const_pointer = const value_type *; private: - typedef SmallVector Representation; + using Representation = SmallVector; + Representation Rep; struct Compare { @@ -52,7 +54,7 @@ private: bool operator ()(Int L, const_reference R) const { return L < R.first; } - bool operator ()(Int L, Int R) const { + bool operator ()(Int L, Int R) const { return L < R; } bool operator ()(const_reference L, const_reference R) const { @@ -80,8 +82,8 @@ public: Rep.insert(I, Val); } - typedef typename Representation::iterator iterator; - typedef typename Representation::const_iterator const_iterator; + using iterator = typename Representation::iterator; + using const_iterator = typename Representation::const_iterator; iterator begin() { return Rep.begin(); } iterator end() { return Rep.end(); } @@ -108,13 +110,12 @@ public: /// from a set of values. class Builder { ContinuousRangeMap &Self; - + + public: + explicit Builder(ContinuousRangeMap &Self) : Self(Self) {} Builder(const Builder&) = delete; Builder &operator=(const Builder&) = delete; - public: - explicit Builder(ContinuousRangeMap &Self) : Self(Self) { } - ~Builder() { std::sort(Self.Rep.begin(), Self.Rep.end(), Compare()); std::unique(Self.Rep.begin(), Self.Rep.end(), @@ -131,9 +132,10 @@ public: Self.Rep.push_back(Val); } }; + friend class Builder; }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H diff --git a/lib/Serialization/MultiOnDiskHashTable.h b/lib/Serialization/MultiOnDiskHashTable.h index fdbbb602b5..44d1616a01 100644 --- a/lib/Serialization/MultiOnDiskHashTable.h +++ b/lib/Serialization/MultiOnDiskHashTable.h @@ -1,4 +1,4 @@ -//===--- MultiOnDiskHashTable.h - Merged set of hash tables -----*- C++ -*-===// +//===- MultiOnDiskHashTable.h - Merged set of hash tables -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,6 +15,7 @@ // files. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H #define LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H @@ -22,33 +23,43 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +#include namespace clang { namespace serialization { -class ModuleFile; - /// \brief A collection of on-disk hash tables, merged when relevant for performance. template class MultiOnDiskHashTable { public: /// A handle to a file, used when overriding tables. - typedef typename Info::file_type file_type; + using file_type = typename Info::file_type; + /// A pointer to an on-disk representation of the hash table. - typedef const unsigned char *storage_type; + using storage_type = const unsigned char *; - typedef typename Info::external_key_type external_key_type; - typedef typename Info::internal_key_type internal_key_type; - typedef typename Info::data_type data_type; - typedef typename Info::data_type_builder data_type_builder; - typedef unsigned hash_value_type; + using external_key_type = typename Info::external_key_type; + using internal_key_type = typename Info::internal_key_type; + using data_type = typename Info::data_type; + using data_type_builder = typename Info::data_type_builder; + using hash_value_type = unsigned; private: + /// The generator is permitted to read our merged table. + template + friend class MultiOnDiskHashTableGenerator; + /// \brief A hash table stored on disk. struct OnDiskTable { - typedef llvm::OnDiskIterableChainedHashTable HashTable; + using HashTable = llvm::OnDiskIterableChainedHashTable; file_type File; HashTable Table; @@ -65,8 +76,8 @@ private: llvm::DenseMap Data; }; - typedef llvm::PointerUnion Table; - typedef llvm::TinyPtrVector TableVector; + using Table = llvm::PointerUnion; + using TableVector = llvm::TinyPtrVector; /// \brief The current set of on-disk and merged tables. /// We manually store the opaque value of the Table because TinyPtrVector @@ -80,14 +91,16 @@ private: llvm::TinyPtrVector PendingOverrides; struct AsOnDiskTable { - typedef OnDiskTable *result_type; + using result_type = OnDiskTable *; + result_type operator()(void *P) const { return Table::getFromOpaqueValue(P).template get(); } }; - typedef llvm::mapped_iterator - table_iterator; - typedef llvm::iterator_range table_range; + + using table_iterator = + llvm::mapped_iterator; + using table_range = llvm::iterator_range; /// \brief The current set of on-disk tables. table_range tables() { @@ -160,17 +173,15 @@ private: Tables.push_back(Table(Merged).getOpaqueValue()); } - /// The generator is permitted to read our merged table. - template - friend class MultiOnDiskHashTableGenerator; - public: - MultiOnDiskHashTable() {} + MultiOnDiskHashTable() = default; + MultiOnDiskHashTable(MultiOnDiskHashTable &&O) : Tables(std::move(O.Tables)), PendingOverrides(std::move(O.PendingOverrides)) { O.Tables.clear(); } + MultiOnDiskHashTable &operator=(MultiOnDiskHashTable &&O) { if (&O == this) return *this; @@ -180,11 +191,13 @@ public: PendingOverrides = std::move(O.PendingOverrides); return *this; } + ~MultiOnDiskHashTable() { clear(); } /// \brief Add the table \p Data loaded from file \p File. void add(file_type File, storage_type Data, Info InfoObj = Info()) { using namespace llvm::support; + storage_type Ptr = Data; uint32_t BucketOffset = endian::readNext(Ptr); @@ -278,8 +291,8 @@ public: /// \brief Writer for the on-disk hash table. template class MultiOnDiskHashTableGenerator { - typedef MultiOnDiskHashTable BaseTable; - typedef llvm::OnDiskChainedHashTableGenerator Generator; + using BaseTable = MultiOnDiskHashTable; + using Generator = llvm::OnDiskChainedHashTableGenerator; Generator Gen; @@ -294,6 +307,7 @@ public: void emit(llvm::SmallVectorImpl &Out, WriterInfo &Info, const BaseTable *Base) { using namespace llvm::support; + llvm::raw_svector_ostream OutStream(Out); // Write our header information. @@ -327,8 +341,7 @@ public: } }; -} // end namespace clang::serialization -} // end namespace clang - +} // namespace serialization +} // namespace clang -#endif +#endif // LLVM_CLANG_LIB_SERIALIZATION_MULTIONDISKHASHTABLE_H -- cgit v1.2.3 From 1c2e4e2c3a1f7f60e1378c11fbece9cace322697 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 2 Nov 2017 21:55:40 +0000 Subject: Modular Codegen: Don't home/modularize static functions in headers Consistent with various workarounds in the backwards compatible modules that allow static functions in headers to exist, be deduplicated to some degree, and not generally fail right out of the gate... do the same with modular codegen as there are enough cases (including in libstdc++ and in LLVM itself - though I cleaned up the easy ones) that it's worth supporting as a migration/backcompat step. Simply create a separate, internal linkage function in each object that needs it. If an available_externally/modularized function references a static function, but the modularized function is eventually dropped and not inlined, the static function will be dropped as unreferenced. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317274 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTWriterDecl.cpp | 25 ++++++++++++++++--------- test/Modules/codegen-opt.test | 12 +++++++++--- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index 803795887c..bf34d01751 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -2258,15 +2258,22 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { assert(FD->doesThisDeclarationHaveABody()); bool ModulesCodegen = false; if (Writer->WritingModule && !FD->isDependentContext()) { - // Under -fmodules-codegen, codegen is performed for all defined functions. - // When building a C++ Modules TS module interface unit, a strong definition - // in the module interface is provided by the compilation of that module - // interface unit, not by its users. (Inline functions are still emitted - // in module users.) - ModulesCodegen = - Writer->Context->getLangOpts().ModulesCodegen || - (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit && - Writer->Context->GetGVALinkageForFunction(FD) == GVA_StrongExternal); + Optional Linkage; + if (Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) { + // When building a C++ Modules TS module interface unit, a strong + // definition in the module interface is provided by the compilation of + // that module interface unit, not by its users. (Inline functions are + // still emitted in module users.) + Linkage = Writer->Context->GetGVALinkageForFunction(FD); + ModulesCodegen = *Linkage == GVA_StrongExternal; + } + if (Writer->Context->getLangOpts().ModulesCodegen) { + // Under -fmodules-codegen, codegen is performed for all non-internal, + // non-always_inline functions. + if (!Linkage) + Linkage = Writer->Context->GetGVALinkageForFunction(FD); + ModulesCodegen = *Linkage != GVA_Internal; + } } Record->push_back(ModulesCodegen); if (ModulesCodegen) diff --git a/test/Modules/codegen-opt.test b/test/Modules/codegen-opt.test index 2f4997a7c7..f62cf38a53 100644 --- a/test/Modules/codegen-opt.test +++ b/test/Modules/codegen-opt.test @@ -25,7 +25,13 @@ FOO-NOT: {{define|declare}} FOO: declare void @_Z2f1Ri(i32* FOO-NOT: {{define|declare}} -FIXME: this internal function should be weak_odr, comdat, and with a new mangling +Internal functions are not modularly code generated - they are +internal wherever they're used. This might not be ideal, but +continues to workaround/support some oddities that backwards +compatible modules have seen and supported in the wild. To remove +the duplication here, the internal functions would need to be +promoted to weak_odr, placed in comdat and given a new mangling - +this would be needed for the C++ Modules TS anyway. FOO: define internal void @_ZL2f2v() #{{[0-9]+}} FOO-NOT: {{define|declare}} @@ -45,7 +51,7 @@ BAR-OPT: define available_externally void @_Z3foov() BAR-CMN-NOT: {{define|declare}} BAR-OPT: declare void @_Z2f1Ri(i32* BAR-OPT-NOT: {{define|declare}} -BAR-OPT: define available_externally void @_ZL2f2v() +BAR-OPT: define internal void @_ZL2f2v() BAR-OPT-NOT: {{define|declare}} @@ -61,5 +67,5 @@ USE-OPT: define available_externally void @_Z3foov() USE-OPT-NOT: {{define|declare}} USE-OPT: declare void @_Z2f1Ri(i32* USE-OPT-NOT: {{define|declare}} -USE-OPT: define available_externally void @_ZL2f2v() +USE-OPT: define internal void @_ZL2f2v() USE-OPT-NOT: {{define|declare}} -- cgit v1.2.3 From 4e3af04476f8d7714ccdcfe6c6bf56050fdfba45 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Thu, 2 Nov 2017 22:28:50 +0000 Subject: Modular Codegen: Don't home always_inline functions Since they'll likely (not always - if the address is taken, etc) be inlined away, even at -O0, separately provided weak definitions are likely to be unused so skip all of that. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317279 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Serialization/ASTWriterDecl.cpp | 8 +++++--- test/Modules/Inputs/codegen/foo.h | 3 +++ test/Modules/Inputs/codegen/use.cpp | 3 +++ test/Modules/codegen.test | 4 +++- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index bf34d01751..e940806094 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -2270,9 +2270,11 @@ void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { if (Writer->Context->getLangOpts().ModulesCodegen) { // Under -fmodules-codegen, codegen is performed for all non-internal, // non-always_inline functions. - if (!Linkage) - Linkage = Writer->Context->GetGVALinkageForFunction(FD); - ModulesCodegen = *Linkage != GVA_Internal; + if (!FD->hasAttr()) { + if (!Linkage) + Linkage = Writer->Context->GetGVALinkageForFunction(FD); + ModulesCodegen = *Linkage != GVA_Internal; + } } } Record->push_back(ModulesCodegen); diff --git a/test/Modules/Inputs/codegen/foo.h b/test/Modules/Inputs/codegen/foo.h index bd3b6489e7..76ad6559cc 100644 --- a/test/Modules/Inputs/codegen/foo.h +++ b/test/Modules/Inputs/codegen/foo.h @@ -29,4 +29,7 @@ inline void inst_decl() { inst(); } +__attribute__((always_inline)) inline void always_inl() { +} + asm("narf"); diff --git a/test/Modules/Inputs/codegen/use.cpp b/test/Modules/Inputs/codegen/use.cpp index cd1a4a642d..3e551881f6 100644 --- a/test/Modules/Inputs/codegen/use.cpp +++ b/test/Modules/Inputs/codegen/use.cpp @@ -6,3 +6,6 @@ void non_modular_use_of_implicit_dtor() { void use_of_instantiated_declaration_without_definition() { inst(); } +void call_always_inline() { + always_inl(); +} diff --git a/test/Modules/codegen.test b/test/Modules/codegen.test index 1bdea5df43..a919933da2 100644 --- a/test/Modules/codegen.test +++ b/test/Modules/codegen.test @@ -4,7 +4,7 @@ REQUIRES: x86-registered-target RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -fmodules-debuginfo -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s -RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s +RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -fmodules -disable-llvm-passes -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s For want of any better definition, inline asm goes "everywhere" the same as it if it were in a header (with the disadvantage that the inline asm will be @@ -23,6 +23,7 @@ USE: module asm "narf" FOO: $_Z2f1PKcz = comdat any FOO: $_ZN13implicit_dtorD1Ev = comdat any USE: $_Z4instIiEvv = comdat any +USE: $_Z10always_inlv = comdat any FOO: $_ZN13implicit_dtorD2Ev = comdat any FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat FOO: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}}) @@ -38,6 +39,7 @@ FOO: define weak_odr void @_ZN13implicit_dtorD2Ev USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev USE: define linkonce_odr void @_Z4instIiEvv +USE: define linkonce_odr void @_Z10always_inlv USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev Modular debug info puts the definition of a class defined in a module in that -- cgit v1.2.3 From 1f1e821de564a14db1a255330f5f605b679d9f12 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 3 Nov 2017 00:36:03 +0000 Subject: [analyzer] do not crash on libcxx03 call_once implementation Addresses https://bugs.llvm.org/show_bug.cgi?id=35075, rdar://35230961 Differential Revision: https://reviews.llvm.org/D39518 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317293 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/BodyFarm.cpp | 24 ++++++++++++------- test/Analysis/call_once.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp index 58a129c411..3e62ae5fe6 100644 --- a/lib/Analysis/BodyFarm.cpp +++ b/lib/Analysis/BodyFarm.cpp @@ -325,6 +325,16 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { const ParmVarDecl *Flag = D->getParamDecl(0); const ParmVarDecl *Callback = D->getParamDecl(1); + + if (!Callback->getType()->isReferenceType()) { + llvm::dbgs() << "libcxx03 std::call_once implementation, skipping.\n"; + return nullptr; + } + if (!Flag->getType()->isReferenceType()) { + llvm::dbgs() << "unknown std::call_once implementation, skipping.\n"; + return nullptr; + } + QualType CallbackType = Callback->getType().getNonReferenceType(); // Nullable pointer, non-null iff function is a CXXRecordDecl. @@ -346,15 +356,13 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { // Otherwise, try libstdc++ implementation, with a field // `_M_once` if (!FlagFieldDecl) { - DEBUG(llvm::dbgs() << "No field __state_ found on std::once_flag struct, " - << "assuming libstdc++ implementation\n"); FlagFieldDecl = M.findMemberField(FlagRecordDecl, "_M_once"); } if (!FlagFieldDecl) { - DEBUG(llvm::dbgs() << "No field _M_once found on std::once flag struct: " - << "unknown std::call_once implementation, " - << "ignoring the call"); + DEBUG(llvm::dbgs() << "No field _M_once or __state_ found on " + << "std::once_flag struct: unknown std::call_once " + << "implementation, ignoring the call."); return nullptr; } @@ -388,9 +396,9 @@ static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { // First two arguments are used for the flag and for the callback. if (D->getNumParams() != CallbackFunctionType->getNumParams() + 2) { - DEBUG(llvm::dbgs() << "Number of params of the callback does not match " - << "the number of params passed to std::call_once, " - << "ignoring the call"); + DEBUG(llvm::dbgs() << "Types of params of the callback do not match " + << "params passed to std::call_once, " + << "ignoring the call\n"); return nullptr; } diff --git a/test/Analysis/call_once.cpp b/test/Analysis/call_once.cpp index 5013cd423e..db9e5cc7ca 100644 --- a/test/Analysis/call_once.cpp +++ b/test/Analysis/call_once.cpp @@ -1,6 +1,11 @@ // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -verify %s // RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBSTDCPP -verify %s +// We do NOT model libcxx03 implementation, but the analyzer should still +// not crash. +// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -verify %s +// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -analyzer-checker=core,debug.ExprInspection -DEMULATE_LIBCXX03 -DEMULATE_LIBSTDCPP -verify %s + void clang_analyzer_eval(bool); // Faking std::std::call_once implementation. @@ -16,8 +21,13 @@ typedef struct once_flag_s { } once_flag; #endif +#ifndef EMULATE_LIBCXX03 template void call_once(once_flag &o, Callable&& func, Args&&... args) {}; +#else +template // libcxx03 call_once +void call_once(once_flag &o, Callable func, Args&&... args) {}; +#endif } // namespace std @@ -28,7 +38,9 @@ void test_called_warning() { std::call_once(g_initialize, [&] { int *x = nullptr; +#ifndef EMULATE_LIBCXX03 int y = *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} +#endif z = 200; }); } @@ -45,8 +57,10 @@ void test_called_on_path_inside_no_warning() { x = &z; }); +#ifndef EMULATE_LIBCXX03 *x = 100; // no-warning clang_analyzer_eval(z == 100); // expected-warning{{TRUE}} +#endif } void test_called_on_path_no_warning() { @@ -59,7 +73,11 @@ void test_called_on_path_no_warning() { x = &y; }); +#ifndef EMULATE_LIBCXX03 *x = 100; // no-warning +#else + *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} +#endif } void test_called_on_path_warning() { @@ -72,7 +90,9 @@ void test_called_on_path_warning() { x = nullptr; }); +#ifndef EMULATE_LIBCXX03 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} +#endif } void test_called_once_warning() { @@ -89,7 +109,9 @@ void test_called_once_warning() { x = &y; }); +#ifndef EMULATE_LIBCXX03 *x = 100; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}} +#endif } void test_called_once_no_warning() { @@ -106,7 +128,9 @@ void test_called_once_no_warning() { x = nullptr; }); +#ifndef EMULATE_LIBCXX03 *x = 100; // no-warning +#endif } static int global = 0; @@ -117,7 +141,9 @@ void funcPointer() { void test_func_pointers() { static std::once_flag flag; std::call_once(flag, &funcPointer); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(global == 1); // expected-warning{{TRUE}} +#endif } template @@ -157,7 +183,9 @@ void test_param_passing_lambda() { }, x); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} +#endif } void test_param_passing_lambda_false() { @@ -169,7 +197,9 @@ void test_param_passing_lambda_false() { }, x); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} +#endif } void test_param_passing_stored_lambda() { @@ -182,7 +212,9 @@ void test_param_passing_stored_lambda() { }; std::call_once(flag, lambda, x); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(y == 120); // expected-warning{{TRUE}} +#endif } void test_multiparam_passing_lambda() { @@ -194,8 +226,10 @@ void test_multiparam_passing_lambda() { }, 1, 2, 3); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(x == 120); // expected-warning{{FALSE}} clang_analyzer_eval(x == 6); // expected-warning{{TRUE}} +#endif } static int global2 = 0; @@ -206,7 +240,9 @@ void test_param_passing_lambda_global() { global2 = a + b + c; }, 1, 2, 3); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(global2 == 6); // expected-warning{{TRUE}} +#endif } static int global3 = 0; @@ -220,7 +256,9 @@ void test_param_passing_funcptr() { std::call_once(flag, &funcptr, 1, 2, 3); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(global3 == 6); // expected-warning{{TRUE}} +#endif } void test_blocks() { @@ -229,7 +267,9 @@ void test_blocks() { std::call_once(flag, ^{ global3 = 120; }); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(global3 == 120); // expected-warning{{TRUE}} +#endif } int call_once() { @@ -238,7 +278,9 @@ int call_once() { void test_non_std_call_once() { int x = call_once(); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(x == 5); // expected-warning{{TRUE}} +#endif } namespace std { @@ -247,28 +289,36 @@ void call_once(d, e); } void g(); void test_no_segfault_on_different_impl() { +#ifndef EMULATE_LIBCXX03 std::call_once(g, false); // no-warning +#endif } void test_lambda_refcapture() { static std::once_flag flag; int a = 6; std::call_once(flag, [&](int &a) { a = 42; }, a); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} +#endif } void test_lambda_refcapture2() { static std::once_flag flag; int a = 6; std::call_once(flag, [=](int &a) { a = 42; }, a); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} +#endif } void test_lambda_fail_refcapture() { static std::once_flag flag; int a = 6; std::call_once(flag, [=](int a) { a = 42; }, a); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} +#endif } void mutator(int ¶m) { @@ -278,7 +328,9 @@ void test_reftypes_funcptr() { static std::once_flag flag; int a = 6; std::call_once(flag, &mutator, a); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(a == 42); // expected-warning{{TRUE}} +#endif } void fail_mutator(int param) { @@ -288,7 +340,9 @@ void test_mutator_noref() { static std::once_flag flag; int a = 6; std::call_once(flag, &fail_mutator, a); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(a == 42); // expected-warning{{FALSE}} +#endif } // Function is implicitly treated as a function pointer @@ -301,5 +355,7 @@ void test_implicit_funcptr() { static std::once_flag flagn; std::call_once(flagn, callbackn, x); +#ifndef EMULATE_LIBCXX03 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} +#endif } -- cgit v1.2.3 From cf0760f2bc21612fb4c0c2ed9eca0e09b98c6f13 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 3 Nov 2017 00:41:29 +0000 Subject: [analyzer] [NFC] very minor ExprEngineC refactoring Differential Revision: https://reviews.llvm.org/D39577 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317294 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/ExprEngineC.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 6f1e8391e6..6c69542bf0 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -92,12 +92,10 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // Process non-assignments except commas or short-circuited // logical expressions (LAnd and LOr). SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); - if (Result.isUnknown()) { - Bldr.generateNode(B, *it, state); - continue; + if (!Result.isUnknown()) { + state = state->BindExpr(B, LCtx, Result); } - state = state->BindExpr(B, LCtx, Result); Bldr.generateNode(B, *it, state); continue; } -- cgit v1.2.3 From 9982bd2e776ef22bd1662b4d5c77810ee025b7ba Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 3 Nov 2017 01:26:01 +0000 Subject: [c++17] Visit class template explicit specializations just like all other class definitions in codegen. If an explicit specialization has a static data member, it may be a definition and we may need to register it for emission. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317296 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CodeGenModule.cpp | 16 +++++++--------- test/CodeGenCXX/cxx1z-inline-variables.cpp | 12 ++++++++++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index b2a18a03f2..b1550170ac 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -4030,6 +4030,13 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::Namespace: EmitDeclContext(cast(D)); break; + case Decl::ClassTemplateSpecialization: { + const auto *Spec = cast(D); + if (DebugInfo && + Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition && + Spec->hasDefinition()) + DebugInfo->completeTemplateDefinition(*Spec); + } LLVM_FALLTHROUGH; case Decl::CXXRecord: if (DebugInfo) { if (auto *ES = D->getASTContext().getExternalSource()) @@ -4216,15 +4223,6 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { EmitOMPThreadPrivateDecl(cast(D)); break; - case Decl::ClassTemplateSpecialization: { - const auto *Spec = cast(D); - if (DebugInfo && - Spec->getSpecializationKind() == TSK_ExplicitInstantiationDefinition && - Spec->hasDefinition()) - DebugInfo->completeTemplateDefinition(*Spec); - break; - } - case Decl::OMPDeclareReduction: EmitOMPDeclareReduction(cast(D)); break; diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp index 0d2ec92a7a..2d16acd8a8 100644 --- a/test/CodeGenCXX/cxx1z-inline-variables.cpp +++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp @@ -67,6 +67,18 @@ int &use3 = X::a; template<> int X::b = 20; template<> inline int X::c = 30; +template struct Y; +template<> struct Y { + static constexpr int a = 123; + static constexpr int b = 456; + static constexpr int c = 789; +}; +// CHECK: @_ZN1YIiE1aE = weak_odr constant i32 123 +constexpr int Y::a; +// CHECK: @_ZN1YIiE1bE = linkonce_odr constant i32 456 +const int &yib = Y::b; +// CHECK-NOT: @_ZN1YIiE1cE + // CHECK-LABEL: define {{.*}}global_var_init // CHECK: call i32 @_Z1fv -- cgit v1.2.3 From 324e0a9695a1682b11e60f5c22024243fa2246d3 Mon Sep 17 00:00:00 2001 From: Justin Lebar Date: Fri, 3 Nov 2017 02:30:00 +0000 Subject: [CUDA] Mark CUDA as a no-errno platform. Summary: CUDA doesn't support errno at all, so this is the right thing -- or at least, in the right direction. But also, this unbreaks the CUDA test-suite math tests [0] after D39481. __cuda_cmath.h forwards nexttoward() to __builtin_nexttoward, which, after that patch, was lowering to a libcall that doesn't exist in NVPTX. [0] http://lab.llvm.org:8011/builders/clang-cuda-build/builds/14999 Reviewers: tra Subscribers: sanjoy, cfe-commits Differential Revision: https://reviews.llvm.org/D39586 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317297 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Driver/ToolChains/Cuda.h | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Driver/ToolChains/Cuda.h b/lib/Driver/ToolChains/Cuda.h index 414c9445c7..3101cb3ab7 100644 --- a/lib/Driver/ToolChains/Cuda.h +++ b/lib/Driver/ToolChains/Cuda.h @@ -157,6 +157,7 @@ public: bool isPICDefaultForced() const override { return false; } bool SupportsProfiling() const override { return false; } bool SupportsObjCGC() const override { return false; } + bool IsMathErrnoDefault() const override { return false; } void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; -- cgit v1.2.3 From 16962ce7c214f12f7362c41bfbe79689bc07ea2f Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 3 Nov 2017 09:40:07 +0000 Subject: [preamble] Also record the "skipping" state of the preprocessor When a preamble ends in a conditional preprocessor block that is being skipped, the preprocessor needs to continue skipping that block when the preamble is used. This fixes PR34570. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317308 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/Preprocessor.h | 33 +++++++++++++++++++++++++-- lib/Lex/PPDirectives.cpp | 31 ++++++++++++++++--------- lib/Lex/Preprocessor.cpp | 7 ++++++ lib/Serialization/ASTReader.cpp | 16 +++++++++++-- lib/Serialization/ASTWriter.cpp | 11 +++++++++ test/Index/preamble-conditionals-inverted.cpp | 4 +++- test/Index/preamble-conditionals-skipping.cpp | 16 +++++++++++++ 7 files changed, 102 insertions(+), 16 deletions(-) create mode 100644 test/Index/preamble-conditionals-skipping.cpp diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 4f211a3eb6..5e847effdc 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -286,6 +286,23 @@ class Preprocessor { /// This is used when loading a precompiled preamble. std::pair SkipMainFilePreamble; +public: + struct PreambleSkipInfo { + PreambleSkipInfo(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc, + bool FoundNonSkipPortion, bool FoundElse, + SourceLocation ElseLoc) + : HashTokenLoc(HashTokenLoc), IfTokenLoc(IfTokenLoc), + FoundNonSkipPortion(FoundNonSkipPortion), FoundElse(FoundElse), + ElseLoc(ElseLoc) {} + + SourceLocation HashTokenLoc; + SourceLocation IfTokenLoc; + bool FoundNonSkipPortion; + bool FoundElse; + SourceLocation ElseLoc; + }; + +private: class PreambleConditionalStackStore { enum State { Off = 0, @@ -319,6 +336,12 @@ class Preprocessor { bool hasRecordedPreamble() const { return !ConditionalStack.empty(); } + bool reachedEOFWhileSkipping() const { return SkipInfo.hasValue(); } + + void clearSkipInfo() { SkipInfo.reset(); } + + llvm::Optional SkipInfo; + private: SmallVector ConditionalStack; State ConditionalStackState; @@ -1839,7 +1862,7 @@ private: /// \p FoundElse is false, then \#else directives are ok, if not, then we have /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. - void SkipExcludedConditionalBlock(const Token &HashToken, + void SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc = SourceLocation()); @@ -2019,9 +2042,15 @@ public: PreambleConditionalStack.setStack(s); } - void setReplayablePreambleConditionalStack(ArrayRef s) { + void setReplayablePreambleConditionalStack(ArrayRef s, + llvm::Optional SkipInfo) { PreambleConditionalStack.startReplaying(); PreambleConditionalStack.setStack(s); + PreambleConditionalStack.SkipInfo = SkipInfo; + } + + llvm::Optional getPreambleSkipInfo() const { + return PreambleConditionalStack.SkipInfo; } private: diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index f9a97505bf..ca3e70fd10 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -350,7 +350,7 @@ void Preprocessor::CheckEndOfDirective(const char *DirType, bool EnableMacros) { /// If ElseOk is true, then \#else directives are ok, if not, then we have /// already seen one so a \#else directive is a duplicate. When this returns, /// the caller can lex the first valid token. -void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken, +void Preprocessor::SkipExcludedConditionalBlock(SourceLocation HashTokenLoc, SourceLocation IfTokenLoc, bool FoundNonSkipPortion, bool FoundElse, @@ -358,8 +358,11 @@ void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken, ++NumSkipped; assert(!CurTokenLexer && CurPPLexer && "Lexing a macro, not a file?"); - CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/false, - FoundNonSkipPortion, FoundElse); + if (PreambleConditionalStack.reachedEOFWhileSkipping()) + PreambleConditionalStack.clearSkipInfo(); + else + CurPPLexer->pushConditionalLevel(IfTokenLoc, /*isSkipping*/ false, + FoundNonSkipPortion, FoundElse); if (CurPTHLexer) { PTHSkipExcludedConditionalBlock(); @@ -385,6 +388,9 @@ void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken, // We don't emit errors for unterminated conditionals here, // Lexer::LexEndOfFile can do that propertly. // Just return and let the caller lex after this #include. + if (PreambleConditionalStack.isRecording()) + PreambleConditionalStack.SkipInfo.emplace( + HashTokenLoc, IfTokenLoc, FoundNonSkipPortion, FoundElse, ElseLoc); break; } @@ -554,7 +560,7 @@ void Preprocessor::SkipExcludedConditionalBlock(const Token &HashToken, if (Callbacks) Callbacks->SourceRangeSkipped( - SourceRange(HashToken.getLocation(), CurPPLexer->getSourceLocation()), + SourceRange(HashTokenLoc, CurPPLexer->getSourceLocation()), Tok.getLocation()); } @@ -2676,7 +2682,8 @@ void Preprocessor::HandleIfdefDirective(Token &Result, if (MacroNameTok.is(tok::eod)) { // Skip code until we get to #endif. This helps with recovery by not // emitting an error when the #endif is reached. - SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(), + SkipExcludedConditionalBlock(HashToken.getLocation(), + DirectiveTok.getLocation(), /*Foundnonskip*/ false, /*FoundElse*/ false); return; } @@ -2725,7 +2732,8 @@ void Preprocessor::HandleIfdefDirective(Token &Result, /*foundelse*/false); } else { // No, skip the contents of this block. - SkipExcludedConditionalBlock(HashToken, DirectiveTok.getLocation(), + SkipExcludedConditionalBlock(HashToken.getLocation(), + DirectiveTok.getLocation(), /*Foundnonskip*/ false, /*FoundElse*/ false); } @@ -2772,7 +2780,7 @@ void Preprocessor::HandleIfDirective(Token &IfToken, /*foundnonskip*/true, /*foundelse*/false); } else { // No, skip the contents of this block. - SkipExcludedConditionalBlock(HashToken, IfToken.getLocation(), + SkipExcludedConditionalBlock(HashToken.getLocation(), IfToken.getLocation(), /*Foundnonskip*/ false, /*FoundElse*/ false); } @@ -2837,7 +2845,8 @@ void Preprocessor::HandleElseDirective(Token &Result, const Token &HashToken) { } // Finally, skip the rest of the contents of this block. - SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true, + SkipExcludedConditionalBlock(HashToken.getLocation(), CI.IfLoc, + /*Foundnonskip*/ true, /*FoundElse*/ true, Result.getLocation()); } @@ -2881,7 +2890,7 @@ void Preprocessor::HandleElifDirective(Token &ElifToken, } // Finally, skip the rest of the contents of this block. - SkipExcludedConditionalBlock(HashToken, CI.IfLoc, /*Foundnonskip*/ true, - /*FoundElse*/ CI.FoundElse, - ElifToken.getLocation()); + SkipExcludedConditionalBlock( + HashToken.getLocation(), CI.IfLoc, /*Foundnonskip*/ true, + /*FoundElse*/ CI.FoundElse, ElifToken.getLocation()); } diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 65df6a57f1..d80899de8f 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -550,6 +550,13 @@ void Preprocessor::replayPreambleConditionalStack() { "CurPPLexer is null when calling replayPreambleConditionalStack."); CurPPLexer->setConditionalLevels(PreambleConditionalStack.getStack()); PreambleConditionalStack.doneReplaying(); + if (PreambleConditionalStack.reachedEOFWhileSkipping()) + SkipExcludedConditionalBlock( + PreambleConditionalStack.SkipInfo->HashTokenLoc, + PreambleConditionalStack.SkipInfo->IfTokenLoc, + PreambleConditionalStack.SkipInfo->FoundNonSkipPortion, + PreambleConditionalStack.SkipInfo->FoundElse, + PreambleConditionalStack.SkipInfo->ElseLoc); } } diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 5a3423a3ec..dacdac6658 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -2995,8 +2995,20 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { case PP_CONDITIONAL_STACK: if (!Record.empty()) { + unsigned Idx = 0, End = Record.size() - 1; + bool ReachedEOFWhileSkipping = Record[Idx++]; + llvm::Optional SkipInfo; + if (ReachedEOFWhileSkipping) { + SourceLocation HashToken = ReadSourceLocation(F, Record, Idx); + SourceLocation IfTokenLoc = ReadSourceLocation(F, Record, Idx); + bool FoundNonSkipPortion = Record[Idx++]; + bool FoundElse = Record[Idx++]; + SourceLocation ElseLoc = ReadSourceLocation(F, Record, Idx); + SkipInfo.emplace(HashToken, IfTokenLoc, FoundNonSkipPortion, + FoundElse, ElseLoc); + } SmallVector ConditionalStack; - for (unsigned Idx = 0, N = Record.size() - 1; Idx < N; /* in loop */) { + while (Idx < End) { auto Loc = ReadSourceLocation(F, Record, Idx); bool WasSkipping = Record[Idx++]; bool FoundNonSkip = Record[Idx++]; @@ -3004,7 +3016,7 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { ConditionalStack.push_back( {Loc, WasSkipping, FoundNonSkip, FoundElse}); } - PP.setReplayablePreambleConditionalStack(ConditionalStack); + PP.setReplayablePreambleConditionalStack(ConditionalStack, SkipInfo); } break; diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index dec8d8f7d7..3834314109 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -2407,6 +2407,17 @@ void ASTWriter::WritePreprocessor(const Preprocessor &PP, bool IsModule) { if (PP.isRecordingPreamble() && PP.hasRecordedPreamble()) { assert(!IsModule); + auto SkipInfo = PP.getPreambleSkipInfo(); + if (SkipInfo.hasValue()) { + Record.push_back(true); + AddSourceLocation(SkipInfo->HashTokenLoc, Record); + AddSourceLocation(SkipInfo->IfTokenLoc, Record); + Record.push_back(SkipInfo->FoundNonSkipPortion); + Record.push_back(SkipInfo->FoundElse); + AddSourceLocation(SkipInfo->ElseLoc, Record); + } else { + Record.push_back(false); + } for (const auto &Cond : PP.getPreambleConditionalStack()) { AddSourceLocation(Cond.IfLoc, Record); Record.push_back(Cond.WasSkipping); diff --git a/test/Index/preamble-conditionals-inverted.cpp b/test/Index/preamble-conditionals-inverted.cpp index 1d67ccb61a..f5cf1205e3 100644 --- a/test/Index/preamble-conditionals-inverted.cpp +++ b/test/Index/preamble-conditionals-inverted.cpp @@ -3,6 +3,8 @@ // RUN: | FileCheck %s --implicit-check-not "error:" #ifdef FOO_H -void foo(); +void foo() {} #endif + +int foo() { return 0; } diff --git a/test/Index/preamble-conditionals-skipping.cpp b/test/Index/preamble-conditionals-skipping.cpp new file mode 100644 index 0000000000..fa5764cd5d --- /dev/null +++ b/test/Index/preamble-conditionals-skipping.cpp @@ -0,0 +1,16 @@ +// RUN: env CINDEXTEST_EDITING=1 c-index-test -test-load-source-reparse 5 \ +// RUN: local -std=c++14 %s 2>&1 \ +// RUN: | FileCheck %s --implicit-check-not "error:" + +#ifdef MYCPLUSPLUS +extern "C" { +#endif + +#ifdef MYCPLUSPLUS +} +#endif + +int main() +{ + return 0; +} -- cgit v1.2.3 From 65464028eeba52041750efe82a35567dc77b3453 Mon Sep 17 00:00:00 2001 From: Krasimir Georgiev Date: Fri, 3 Nov 2017 14:38:07 +0000 Subject: [clang-format] Sort using-declarations case sensitively with a special case for '_' Summary: This makes clang-format sort using declarations case-sensitive with the exception that '_' comes just before 'A'. This is better than the current case insensitive version, because it groups uppercase names in the same namespace together. Reviewers: bkramer Reviewed By: bkramer Subscribers: cfe-commits, klimek Differential Revision: https://reviews.llvm.org/D39549 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317325 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/UsingDeclarationsSorter.cpp | 23 +++++++++- unittests/Format/UsingDeclarationsSorterTest.cpp | 55 ++++++------------------ 2 files changed, 33 insertions(+), 45 deletions(-) diff --git a/lib/Format/UsingDeclarationsSorter.cpp b/lib/Format/UsingDeclarationsSorter.cpp index d6753b545e..e9c535da92 100644 --- a/lib/Format/UsingDeclarationsSorter.cpp +++ b/lib/Format/UsingDeclarationsSorter.cpp @@ -33,8 +33,27 @@ struct UsingDeclaration { UsingDeclaration(const AnnotatedLine *Line, const std::string &Label) : Line(Line), Label(Label) {} + // Compares lexicographically with the exception that '_' is just before 'A'. bool operator<(const UsingDeclaration &Other) const { - return StringRef(Label).compare_lower(Other.Label) < 0; + size_t Size = Label.size(); + size_t OtherSize = Other.Label.size(); + for (size_t I = 0, E = std::min(Size, OtherSize); I < E; ++I) { + char Rank = rank(Label[I]); + char OtherRank = rank(Other.Label[I]); + if (Rank != OtherRank) + return Rank < OtherRank; + } + return Size < OtherSize; + } + + // Returns the position of c in a lexicographic ordering with the exception + // that '_' is just before 'A'. + static char rank(char c) { + if (c == '_') + return 'A'; + if ('A' <= c && c < '_') + return c + 1; + return c; } }; @@ -77,7 +96,7 @@ void endUsingDeclarationBlock( SmallVectorImpl *UsingDeclarations, const SourceManager &SourceMgr, tooling::Replacements *Fixes) { bool BlockAffected = false; - for (const UsingDeclaration& Declaration : *UsingDeclarations) { + for (const UsingDeclaration &Declaration : *UsingDeclarations) { if (Declaration.Line->Affected) { BlockAffected = true; break; diff --git a/unittests/Format/UsingDeclarationsSorterTest.cpp b/unittests/Format/UsingDeclarationsSorterTest.cpp index caa2f4380b..6ce96ed962 100644 --- a/unittests/Format/UsingDeclarationsSorterTest.cpp +++ b/unittests/Format/UsingDeclarationsSorterTest.cpp @@ -86,19 +86,25 @@ TEST_F(UsingDeclarationsSorterTest, SwapsTwoConsecutiveUsingDeclarations) { "using a, b;")); } -TEST_F(UsingDeclarationsSorterTest, SortsCaseInsensitively) { +TEST_F(UsingDeclarationsSorterTest, SortsCaseSensitively) { EXPECT_EQ("using A;\n" "using a;", sortUsingDeclarations("using A;\n" "using a;")); - EXPECT_EQ("using a;\n" - "using A;", + EXPECT_EQ("using A;\n" + "using a;", sortUsingDeclarations("using a;\n" "using A;")); - EXPECT_EQ("using a;\n" - "using B;", + EXPECT_EQ("using B;\n" + "using a;", sortUsingDeclarations("using B;\n" "using a;")); + + // Sorts '_' right before 'A'. + EXPECT_EQ("using _;\n" + "using A;", + sortUsingDeclarations("using A;\n" + "using _;")); EXPECT_EQ("using _;\n" "using a;", sortUsingDeclarations("using a;\n" @@ -110,8 +116,8 @@ TEST_F(UsingDeclarationsSorterTest, SortsCaseInsensitively) { EXPECT_EQ("using ::testing::_;\n" "using ::testing::Aardvark;\n" - "using ::testing::apple::Honeycrisp;\n" "using ::testing::Xylophone;\n" + "using ::testing::apple::Honeycrisp;\n" "using ::testing::zebra::Stripes;", sortUsingDeclarations("using ::testing::Aardvark;\n" "using ::testing::Xylophone;\n" @@ -120,43 +126,6 @@ TEST_F(UsingDeclarationsSorterTest, SortsCaseInsensitively) { "using ::testing::zebra::Stripes;")); } -TEST_F(UsingDeclarationsSorterTest, SortsStably) { - EXPECT_EQ("using a;\n" - "using a;\n" - "using A;\n" - "using a;\n" - "using A;\n" - "using a;\n" - "using A;\n" - "using a;\n" - "using B;\n" - "using b;\n" - "using b;\n" - "using B;\n" - "using b;\n" - "using b;\n" - "using b;\n" - "using B;\n" - "using b;", - sortUsingDeclarations("using a;\n" - "using B;\n" - "using a;\n" - "using b;\n" - "using A;\n" - "using a;\n" - "using b;\n" - "using B;\n" - "using b;\n" - "using A;\n" - "using a;\n" - "using b;\n" - "using b;\n" - "using B;\n" - "using b;\n" - "using A;\n" - "using a;")); -} - TEST_F(UsingDeclarationsSorterTest, SortsMultipleTopLevelDeclarations) { EXPECT_EQ("using a;\n" "using b;\n" -- cgit v1.2.3 From 26d6ffeb2225d97ba3e5a59fcda9eb6f2e4689d5 Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Fri, 3 Nov 2017 15:20:57 +0000 Subject: [Tooling] Put createExecutorFromCommandLineArgs implementation in a wrapper. NFC git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317328 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Tooling/Execution.h | 7 +++++++ lib/Tooling/Execution.cpp | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h index 9d07c5659e..1a44c4788c 100644 --- a/include/clang/Tooling/Execution.h +++ b/include/clang/Tooling/Execution.h @@ -162,6 +162,13 @@ createExecutorFromCommandLineArgs(int &argc, const char **argv, llvm::cl::OptionCategory &Category, const char *Overview = nullptr); +namespace internal { +llvm::Expected> +createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview = nullptr); +} // end namespace internal + } // end namespace tooling } // end namespace clang diff --git a/lib/Tooling/Execution.cpp b/lib/Tooling/Execution.cpp index 1a078ef7e1..0e3404f91c 100644 --- a/lib/Tooling/Execution.cpp +++ b/lib/Tooling/Execution.cpp @@ -54,10 +54,11 @@ llvm::Error ToolExecutor::execute(std::unique_ptr Action, return execute(Actions); } +namespace internal { llvm::Expected> -createExecutorFromCommandLineArgs(int &argc, const char **argv, - llvm::cl::OptionCategory &Category, - const char *Overview) { +createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview) { auto OptionsParser = CommonOptionsParser::create(argc, argv, Category, llvm::cl::ZeroOrMore, /*Overview=*/nullptr); @@ -84,6 +85,15 @@ createExecutorFromCommandLineArgs(int &argc, const char **argv, llvm::Twine("Executor \"") + ExecutorName + "\" is not registered.", llvm::inconvertibleErrorCode()); } +} // end namespace internal + +llvm::Expected> +createExecutorFromCommandLineArgs(int &argc, const char **argv, + llvm::cl::OptionCategory &Category, + const char *Overview) { + return internal::createExecutorFromCommandLineArgsImpl(argc, argv, Category, + Overview); +} } // end namespace tooling } // end namespace clang -- cgit v1.2.3 From 5e73ee6e4fd225c7b40b132889ec08de0977777f Mon Sep 17 00:00:00 2001 From: Eric Liu Date: Fri, 3 Nov 2017 15:57:27 +0000 Subject: [Tooling] Fix linking of StandaloneToolExecutorPlugin. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317332 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Tooling/Execution.cpp | 8 +++++++- lib/Tooling/StandaloneExecution.cpp | 8 ++++---- unittests/Tooling/ExecutionTest.cpp | 7 ------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/lib/Tooling/Execution.cpp b/lib/Tooling/Execution.cpp index 0e3404f91c..498d683f89 100644 --- a/lib/Tooling/Execution.cpp +++ b/lib/Tooling/Execution.cpp @@ -61,7 +61,7 @@ createExecutorFromCommandLineArgsImpl(int &argc, const char **argv, const char *Overview) { auto OptionsParser = CommonOptionsParser::create(argc, argv, Category, llvm::cl::ZeroOrMore, - /*Overview=*/nullptr); + /*Overview=*/Overview); if (!OptionsParser) return OptionsParser.takeError(); for (auto I = ToolExecutorPluginRegistry::begin(), @@ -95,5 +95,11 @@ createExecutorFromCommandLineArgs(int &argc, const char **argv, Overview); } +// This anchor is used to force the linker to link in the generated object file +// and thus register the StandaloneToolExecutorPlugin. +extern volatile int StandaloneToolExecutorAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED StandaloneToolExecutorAnchorDest = + StandaloneToolExecutorAnchorSource; + } // end namespace tooling } // end namespace clang diff --git a/lib/Tooling/StandaloneExecution.cpp b/lib/Tooling/StandaloneExecution.cpp index e52e4a611f..eea8e39d13 100644 --- a/lib/Tooling/StandaloneExecution.cpp +++ b/lib/Tooling/StandaloneExecution.cpp @@ -79,13 +79,13 @@ public: } }; -// This anchor is used to force the linker to link in the generated object file -// and thus register the plugin. -volatile int ToolExecutorPluginAnchorSource = 0; - static ToolExecutorPluginRegistry::Add X("standalone", "Runs FrontendActions on a set of files provided " "via positional arguments."); +// This anchor is used to force the linker to link in the generated object file +// and thus register the plugin. +volatile int StandaloneToolExecutorAnchorSource = 0; + } // end namespace tooling } // end namespace clang diff --git a/unittests/Tooling/ExecutionTest.cpp b/unittests/Tooling/ExecutionTest.cpp index 44e37b4009..09dfdb6cf0 100644 --- a/unittests/Tooling/ExecutionTest.cpp +++ b/unittests/Tooling/ExecutionTest.cpp @@ -125,13 +125,6 @@ public: } }; -// This anchor is used to force the linker to link in the generated object file -// and thus register the plugin. -extern volatile int ToolExecutorPluginAnchorSource; - -static int LLVM_ATTRIBUTE_UNUSED TestToolExecutorPluginAnchorDest = - ToolExecutorPluginAnchorSource; - static ToolExecutorPluginRegistry::Add X("test-executor", "Plugin for TestToolExecutor."); -- cgit v1.2.3 From 5b442b4dde99fa84ac7cc022a379bb997725f298 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Fri, 3 Nov 2017 16:27:27 +0000 Subject: [CodeGen] add libcall attr tests to show errno-related diffs; NFC See rL317220 for the builtin siblings. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317336 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/CodeGen/libcalls-errno.c | 732 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 732 insertions(+) create mode 100644 test/CodeGen/libcalls-errno.c diff --git a/test/CodeGen/libcalls-errno.c b/test/CodeGen/libcalls-errno.c new file mode 100644 index 0000000000..64bd83fece --- /dev/null +++ b/test/CodeGen/libcalls-errno.c @@ -0,0 +1,732 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm %s | FileCheck %s -check-prefix=NO__ERRNO +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -w -S -o - -emit-llvm -fmath-errno %s | FileCheck %s -check-prefix=HAS_ERRNO + +// Test attributes of library calls to see how errno affects the resulting codegen. + + +double *d; +float f; +float *fp; +long double *l; +int *i; +const char *c; + +void foo() { + atan2(f,f); atan2f(f,f) ; atan2l(f, f); + +// NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]] +// NO__ERRNO: declare float @atan2f(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE:#[0-9]+]] +// HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]] + + copysign(f,f); copysignf(f,f);copysignl(f,f); + +// NO__ERRNO: declare double @copysign(double, double) [[READNONE]] +// NO__ERRNO: declare float @copysignf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @copysign(double, double) [[READNONE:#[0-9]+]] +// HAS_ERRNO: declare float @copysignf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @copysignl(x86_fp80, x86_fp80) [[READNONE]] + + fabs(f); fabsf(f); fabsl(f); + +// NO__ERRNO: declare double @fabs(double) [[READNONE]] +// NO__ERRNO: declare float @fabsf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @fabsl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fabs(double) [[READNONE]] +// HAS_ERRNO: declare float @fabsf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @fabsl(x86_fp80) [[READNONE]] + + fmod(f,f); fmodf(f,f); fmodl(f,f); + +// NO__ERRNO: declare double @fmod(double, double) [[READNONE]] +// NO__ERRNO: declare float @fmodf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]] + + frexp(f,i); frexpf(f,i); frexpl(f,i); + +// NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]] +// NO__ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare float @frexpf(float, i32*) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @frexpl(x86_fp80, i32*) [[NOT_READNONE]] + + ldexp(f,f); ldexpf(f,f); ldexpl(f,f); + +// NO__ERRNO: declare double @ldexp(double, i32) [[READNONE]] +// NO__ERRNO: declare float @ldexpf(float, i32) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[READNONE]] +// HAS_ERRNO: declare double @ldexp(double, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare float @ldexpf(float, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @ldexpl(x86_fp80, i32) [[NOT_READNONE]] + + modf(f,d); modff(f,fp); modfl(f,l); + +// NO__ERRNO: declare double @modf(double, double*) [[NOT_READNONE]] +// NO__ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]] +// HAS_ERRNO: declare double @modf(double, double*) [[NOT_READNONE]] +// HAS_ERRNO: declare float @modff(float, float*) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @modfl(x86_fp80, x86_fp80*) [[NOT_READNONE]] + + nan(c); nanf(c); nanl(c); + +// NO__ERRNO: declare double @nan(i8*) [[READONLY:#[0-9]+]] +// NO__ERRNO: declare float @nanf(i8*) [[READONLY]] +// NO__ERRNO: declare x86_fp80 @nanl(i8*) [[READONLY]] +// HAS_ERRNO: declare double @nan(i8*) [[READONLY:#[0-9]+]] +// HAS_ERRNO: declare float @nanf(i8*) [[READONLY]] +// HAS_ERRNO: declare x86_fp80 @nanl(i8*) [[READONLY]] + + pow(f,f); powf(f,f); powl(f,f); + +// NO__ERRNO: declare double @llvm.pow.f64(double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// NO__ERRNO: declare float @llvm.pow.f32(float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @pow(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @powf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @powl(x86_fp80, x86_fp80) [[NOT_READNONE]] + + /* math */ + acos(f); acosf(f); acosl(f); + +// NO__ERRNO: declare double @acos(double) [[READNONE]] +// NO__ERRNO: declare float @acosf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @acosl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @acos(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @acosf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @acosl(x86_fp80) [[NOT_READNONE]] + + acosh(f); acoshf(f); acoshl(f); + +// NO__ERRNO: declare double @acosh(double) [[READNONE]] +// NO__ERRNO: declare float @acoshf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @acosh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @acoshf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @acoshl(x86_fp80) [[NOT_READNONE]] + + asin(f); asinf(f); asinl(f); + +// NO__ERRNO: declare double @asin(double) [[READNONE]] +// NO__ERRNO: declare float @asinf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @asinl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @asin(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @asinf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @asinl(x86_fp80) [[NOT_READNONE]] + + asinh(f); asinhf(f); asinhl(f); + +// NO__ERRNO: declare double @asinh(double) [[READNONE]] +// NO__ERRNO: declare float @asinhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @asinh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @asinhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @asinhl(x86_fp80) [[NOT_READNONE]] + + atan(f); atanf(f); atanl(f); + +// NO__ERRNO: declare double @atan(double) [[READNONE]] +// NO__ERRNO: declare float @atanf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @atanl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atan(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @atanf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @atanl(x86_fp80) [[NOT_READNONE]] + + atanh(f); atanhf(f); atanhl(f); + +// NO__ERRNO: declare double @atanh(double) [[READNONE]] +// NO__ERRNO: declare float @atanhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @atanh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @atanhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @atanhl(x86_fp80) [[NOT_READNONE]] + + cbrt(f); cbrtf(f); cbrtl(f); + +// NO__ERRNO: declare double @cbrt(double) [[READNONE]] +// NO__ERRNO: declare float @cbrtf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cbrt(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @cbrtf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @cbrtl(x86_fp80) [[NOT_READNONE]] + + ceil(f); ceilf(f); ceill(f); + +// NO__ERRNO: declare double @ceil(double) [[READNONE]] +// NO__ERRNO: declare float @ceilf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @ceill(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @ceil(double) [[READNONE]] +// HAS_ERRNO: declare float @ceilf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @ceill(x86_fp80) [[READNONE]] + + cos(f); cosf(f); cosl(f); + +// NO__ERRNO: declare double @cos(double) [[READNONE]] +// NO__ERRNO: declare float @cosf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cosl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cos(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @cosf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @cosl(x86_fp80) [[NOT_READNONE]] + + cosh(f); coshf(f); coshl(f); + +// NO__ERRNO: declare double @cosh(double) [[READNONE]] +// NO__ERRNO: declare float @coshf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @coshl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @cosh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @coshf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @coshl(x86_fp80) [[NOT_READNONE]] + + erf(f); erff(f); erfl(f); + +// NO__ERRNO: declare double @erf(double) [[READNONE]] +// NO__ERRNO: declare float @erff(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @erfl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @erf(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @erff(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @erfl(x86_fp80) [[NOT_READNONE]] + + erfc(f); erfcf(f); erfcl(f); + +// NO__ERRNO: declare double @erfc(double) [[READNONE]] +// NO__ERRNO: declare float @erfcf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @erfc(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @erfcf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @erfcl(x86_fp80) [[NOT_READNONE]] + + exp(f); expf(f); expl(f); + +// NO__ERRNO: declare double @exp(double) [[READNONE]] +// NO__ERRNO: declare float @expf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @expl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @exp(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @expf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @expl(x86_fp80) [[NOT_READNONE]] + + exp2(f); exp2f(f); exp2l(f); + +// NO__ERRNO: declare double @exp2(double) [[READNONE]] +// NO__ERRNO: declare float @exp2f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @exp2(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @exp2f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @exp2l(x86_fp80) [[NOT_READNONE]] + + expm1(f); expm1f(f); expm1l(f); + +// NO__ERRNO: declare double @expm1(double) [[READNONE]] +// NO__ERRNO: declare float @expm1f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @expm1(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @expm1f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @expm1l(x86_fp80) [[NOT_READNONE]] + + fdim(f,f); fdimf(f,f); fdiml(f,f); + +// NO__ERRNO: declare double @fdim(double, double) [[READNONE]] +// NO__ERRNO: declare float @fdimf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fdim(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @fdimf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @fdiml(x86_fp80, x86_fp80) [[NOT_READNONE]] + + floor(f); floorf(f); floorl(f); + +// NO__ERRNO: declare double @floor(double) [[READNONE]] +// NO__ERRNO: declare float @floorf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @floorl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @floor(double) [[READNONE]] +// HAS_ERRNO: declare float @floorf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @floorl(x86_fp80) [[READNONE]] + + fma(f,f,f); fmaf(f,f,f); fmal(f,f,f); + +// NO__ERRNO: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @llvm.fma.f64(double, double, double) [[READNONE_INTRINSIC:#[0-9]+]] +// HAS_ERRNO: declare float @llvm.fma.f32(float, float, float) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare x86_fp80 @llvm.fma.f80(x86_fp80, x86_fp80, x86_fp80) [[READNONE_INTRINSIC]] + + fmax(f,f); fmaxf(f,f); fmaxl(f,f); + +// NO__ERRNO: declare double @fmax(double, double) [[READNONE]] +// NO__ERRNO: declare float @fmaxf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fmax(double, double) [[READNONE]] +// HAS_ERRNO: declare float @fmaxf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @fmaxl(x86_fp80, x86_fp80) [[READNONE]] + + fmin(f,f); fminf(f,f); fminl(f,f); + +// NO__ERRNO: declare double @fmin(double, double) [[READNONE]] +// NO__ERRNO: declare float @fminf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @fmin(double, double) [[READNONE]] +// HAS_ERRNO: declare float @fminf(float, float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @fminl(x86_fp80, x86_fp80) [[READNONE]] + + hypot(f,f); hypotf(f,f); hypotl(f,f); + +// NO__ERRNO: declare double @hypot(double, double) [[READNONE]] +// NO__ERRNO: declare float @hypotf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @hypot(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @hypotf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @hypotl(x86_fp80, x86_fp80) [[NOT_READNONE]] + + ilogb(f); ilogbf(f); ilogbl(f); + +// NO__ERRNO: declare i32 @ilogb(double) [[READNONE]] +// NO__ERRNO: declare i32 @ilogbf(float) [[READNONE]] +// NO__ERRNO: declare i32 @ilogbl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i32 @ilogb(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i32 @ilogbf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i32 @ilogbl(x86_fp80) [[NOT_READNONE]] + + lgamma(f); lgammaf(f); lgammal(f); + +// NO__ERRNO: declare double @lgamma(double) [[NOT_READNONE]] +// NO__ERRNO: declare float @lgammaf(float) [[NOT_READNONE]] +// NO__ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[NOT_READNONE]] +// HAS_ERRNO: declare double @lgamma(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @lgammaf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @lgammal(x86_fp80) [[NOT_READNONE]] + + llrint(f); llrintf(f); llrintl(f); + +// NO__ERRNO: declare i64 @llrint(double) [[READNONE]] +// NO__ERRNO: declare i64 @llrintf(float) [[READNONE]] +// NO__ERRNO: declare i64 @llrintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @llrint(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llrintf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llrintl(x86_fp80) [[NOT_READNONE]] + + llround(f); llroundf(f); llroundl(f); + +// NO__ERRNO: declare i64 @llround(double) [[READNONE]] +// NO__ERRNO: declare i64 @llroundf(float) [[READNONE]] +// NO__ERRNO: declare i64 @llroundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @llround(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llroundf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @llroundl(x86_fp80) [[NOT_READNONE]] + + log(f); logf(f); logl(f); + +// NO__ERRNO: declare double @log(double) [[READNONE]] +// NO__ERRNO: declare float @logf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @logl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @logf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @logl(x86_fp80) [[NOT_READNONE]] + + log10(f); log10f(f); log10l(f); + +// NO__ERRNO: declare double @log10(double) [[READNONE]] +// NO__ERRNO: declare float @log10f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @log10l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log10(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @log10f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @log10l(x86_fp80) [[NOT_READNONE]] + + log1p(f); log1pf(f); log1pl(f); + +// NO__ERRNO: declare double @log1p(double) [[READNONE]] +// NO__ERRNO: declare float @log1pf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log1p(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @log1pf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @log1pl(x86_fp80) [[NOT_READNONE]] + + log2(f); log2f(f); log2l(f); + +// NO__ERRNO: declare double @log2(double) [[READNONE]] +// NO__ERRNO: declare float @log2f(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @log2l(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @log2(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @log2f(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @log2l(x86_fp80) [[NOT_READNONE]] + + logb(f); logbf(f); logbl(f); + +// NO__ERRNO: declare double @logb(double) [[READNONE]] +// NO__ERRNO: declare float @logbf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @logbl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @logb(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @logbf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @logbl(x86_fp80) [[NOT_READNONE]] + + lrint(f); lrintf(f); lrintl(f); + +// NO__ERRNO: declare i64 @lrint(double) [[READNONE]] +// NO__ERRNO: declare i64 @lrintf(float) [[READNONE]] +// NO__ERRNO: declare i64 @lrintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @lrint(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lrintf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lrintl(x86_fp80) [[NOT_READNONE]] + + lround(f); lroundf(f); lroundl(f); + +// NO__ERRNO: declare i64 @lround(double) [[READNONE]] +// NO__ERRNO: declare i64 @lroundf(float) [[READNONE]] +// NO__ERRNO: declare i64 @lroundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare i64 @lround(double) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lroundf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare i64 @lroundl(x86_fp80) [[NOT_READNONE]] + + nearbyint(f); nearbyintf(f); nearbyintl(f); + +// NO__ERRNO: declare double @nearbyint(double) [[READNONE]] +// NO__ERRNO: declare float @nearbyintf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nearbyint(double) [[READNONE]] +// HAS_ERRNO: declare float @nearbyintf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @nearbyintl(x86_fp80) [[READNONE]] + + nextafter(f,f); nextafterf(f,f); nextafterl(f,f); + +// NO__ERRNO: declare double @nextafter(double, double) [[READNONE]] +// NO__ERRNO: declare float @nextafterf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nextafter(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @nextafterf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @nextafterl(x86_fp80, x86_fp80) [[NOT_READNONE]] + + nexttoward(f,f); nexttowardf(f,f);nexttowardl(f,f); + +// NO__ERRNO: declare double @nexttoward(double, x86_fp80) [[READNONE]] +// NO__ERRNO: declare float @nexttowardf(float, x86_fp80) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @nexttoward(double, x86_fp80) [[NOT_READNONE]] +// HAS_ERRNO: declare float @nexttowardf(float, x86_fp80) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @nexttowardl(x86_fp80, x86_fp80) [[NOT_READNONE]] + + remainder(f,f); remainderf(f,f); remainderl(f,f); + +// NO__ERRNO: declare double @remainder(double, double) [[READNONE]] +// NO__ERRNO: declare float @remainderf(float, float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @remainder(double, double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @remainderf(float, float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @remainderl(x86_fp80, x86_fp80) [[NOT_READNONE]] + +// +// FIXME: remquo is not recognized as a mathlib call. +// + // remquo(f,f,i); remquof(f,f,i); remquol(f,f,i); + + rint(f); rintf(f); rintl(f); + +// NO__ERRNO: declare double @rint(double) [[READNONE]] +// NO__ERRNO: declare float @rintf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @rintl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @rint(double) [[READNONE]] +// HAS_ERRNO: declare float @rintf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @rintl(x86_fp80) [[READNONE]] + + round(f); roundf(f); roundl(f); + +// NO__ERRNO: declare double @round(double) [[READNONE]] +// NO__ERRNO: declare float @roundf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @roundl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @round(double) [[READNONE]] +// HAS_ERRNO: declare float @roundf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @roundl(x86_fp80) [[READNONE]] + + scalbln(f,f); scalblnf(f,f); scalblnl(f,f); + +// NO__ERRNO: declare double @scalbln(double, i64) [[READNONE]] +// NO__ERRNO: declare float @scalblnf(float, i64) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[READNONE]] +// HAS_ERRNO: declare double @scalbln(double, i64) [[NOT_READNONE]] +// HAS_ERRNO: declare float @scalblnf(float, i64) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @scalblnl(x86_fp80, i64) [[NOT_READNONE]] + + scalbn(f,f); scalbnf(f,f); scalbnl(f,f); + +// NO__ERRNO: declare double @scalbn(double, i32) [[READNONE]] +// NO__ERRNO: declare float @scalbnf(float, i32) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[READNONE]] +// HAS_ERRNO: declare double @scalbn(double, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare float @scalbnf(float, i32) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @scalbnl(x86_fp80, i32) [[NOT_READNONE]] + + sin(f); sinf(f); sinl(f); + +// NO__ERRNO: declare double @sin(double) [[READNONE]] +// NO__ERRNO: declare float @sinf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @sinl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sin(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @sinf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @sinl(x86_fp80) [[NOT_READNONE]] + + sinh(f); sinhf(f); sinhl(f); + +// NO__ERRNO: declare double @sinh(double) [[READNONE]] +// NO__ERRNO: declare float @sinhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @sinh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @sinhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @sinhl(x86_fp80) [[NOT_READNONE]] + + sqrt(f); sqrtf(f); sqrtl(f); + +// NO__ERRNO: declare double @llvm.sqrt.f64(double) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare float @llvm.sqrt.f32(float) [[READNONE_INTRINSIC]] +// NO__ERRNO: declare x86_fp80 @llvm.sqrt.f80(x86_fp80) [[READNONE_INTRINSIC]] +// HAS_ERRNO: declare double @sqrt(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @sqrtf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @sqrtl(x86_fp80) [[NOT_READNONE]] + + tan(f); tanf(f); tanl(f); + +// NO__ERRNO: declare double @tan(double) [[READNONE]] +// NO__ERRNO: declare float @tanf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @tanl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tan(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @tanf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @tanl(x86_fp80) [[NOT_READNONE]] + + tanh(f); tanhf(f); tanhl(f); + +// NO__ERRNO: declare double @tanh(double) [[READNONE]] +// NO__ERRNO: declare float @tanhf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tanh(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @tanhf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @tanhl(x86_fp80) [[NOT_READNONE]] + + tgamma(f); tgammaf(f); tgammal(f); + +// NO__ERRNO: declare double @tgamma(double) [[READNONE]] +// NO__ERRNO: declare float @tgammaf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @tgamma(double) [[NOT_READNONE]] +// HAS_ERRNO: declare float @tgammaf(float) [[NOT_READNONE]] +// HAS_ERRNO: declare x86_fp80 @tgammal(x86_fp80) [[NOT_READNONE]] + + trunc(f); truncf(f); truncl(f); + +// NO__ERRNO: declare double @trunc(double) [[READNONE]] +// NO__ERRNO: declare float @truncf(float) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @truncl(x86_fp80) [[READNONE]] +// HAS_ERRNO: declare double @trunc(double) [[READNONE]] +// HAS_ERRNO: declare float @truncf(float) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @truncl(x86_fp80) [[READNONE]] + + /* complex */ + + cabs(f); cabsf(f); cabsl(f); + +// NO__ERRNO: declare double @cabs(double, double) [[READNONE]] +// NO__ERRNO: declare float @cabsf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cabsl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare double @cabs(double, double) [[READNONE]] +// HAS_ERRNO: declare float @cabsf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @cabsl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + cacos(f); cacosf(f); cacosl(f); + +// NO__ERRNO: declare { double, double } @cacos(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cacosf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cacosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cacos(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cacosf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cacosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + cacosh(f); cacoshf(f); cacoshl(f); + +// NO__ERRNO: declare { double, double } @cacosh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cacoshf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cacoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cacosh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cacoshf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cacoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + carg(f); cargf(f); cargl(f); + +// NO__ERRNO: declare double @carg(double, double) [[READNONE]] +// NO__ERRNO: declare float @cargf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare x86_fp80 @cargl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare double @carg(double, double) [[READNONE]] +// HAS_ERRNO: declare float @cargf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare x86_fp80 @cargl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + casin(f); casinf(f); casinl(f); + +// NO__ERRNO: declare { double, double } @casin(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @casinf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @casinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @casin(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @casinf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + casinh(f); casinhf(f); casinhl(f); + +// NO__ERRNO: declare { double, double } @casinh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @casinhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @casinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @casinh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @casinhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @casinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + catan(f); catanf(f); catanl(f); + +// NO__ERRNO: declare { double, double } @catan(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @catanf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @catanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @catan(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @catanf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @catanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + catanh(f); catanhf(f); catanhl(f); + +// NO__ERRNO: declare { double, double } @catanh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @catanhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @catanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @catanh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @catanhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @catanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + ccos(f); ccosf(f); ccosl(f); + +// NO__ERRNO: declare { double, double } @ccos(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ccosf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ccosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ccos(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ccosf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ccosl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + ccosh(f); ccoshf(f); ccoshl(f); + +// NO__ERRNO: declare { double, double } @ccosh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ccoshf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ccoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ccosh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ccoshf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ccoshl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + cexp(f); cexpf(f); cexpl(f); + +// NO__ERRNO: declare { double, double } @cexp(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cexpf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cexpl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cexp(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cexpf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cexpl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + cimag(f); cimagf(f); cimagl(f); + +// NO__ERRNO-NOT: .cimag +// NO__ERRNO-NOT: @cimag +// HAS_ERRNO-NOT: .cimag +// HAS_ERRNO-NOT: @cimag + + conj(f); conjf(f); conjl(f); + +// NO__ERRNO: declare { double, double } @conj(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @conjf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @conjl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @conj(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @conjf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @conjl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + clog(f); clogf(f); clogl(f); + +// NO__ERRNO: declare { double, double } @clog(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @clogf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @clogl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @clog(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @clogf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @clogl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + cproj(f); cprojf(f); cprojl(f); + +// NO__ERRNO: declare { double, double } @cproj(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + cpow(f,f); cpowf(f,f); cpowl(f,f); + +// NO__ERRNO: declare { double, double } @cpow(double, double, double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @cpowl({ x86_fp80, x86_fp80 }* byval align 16, { x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @cpow(double, double, double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @cpowf(<2 x float>, <2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cpowl({ x86_fp80, x86_fp80 }* byval align 16, { x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + creal(f); crealf(f); creall(f); + +// NO__ERRNO-NOT: .creal +// NO__ERRNO-NOT: @creal +// HAS_ERRNO-NOT: .creal +// HAS_ERRNO-NOT: @creal + + csin(f); csinf(f); csinl(f); + +// NO__ERRNO: declare { double, double } @csin(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @csinf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @csinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @csin(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @csinf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csinl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + csinh(f); csinhf(f); csinhl(f); + +// NO__ERRNO: declare { double, double } @csinh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @csinhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @csinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @csinh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @csinhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csinhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + csqrt(f); csqrtf(f); csqrtl(f); + +// NO__ERRNO: declare { double, double } @csqrt(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @csqrtl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @csqrt(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @csqrtf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @csqrtl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + ctan(f); ctanf(f); ctanl(f); + +// NO__ERRNO: declare { double, double } @ctan(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ctanf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ctanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ctan(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ctanf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] + + ctanh(f); ctanhf(f); ctanhl(f); + +// NO__ERRNO: declare { double, double } @ctanh(double, double) [[READNONE]] +// NO__ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[READNONE]] +// NO__ERRNO: declare { x86_fp80, x86_fp80 } @ctanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { double, double } @ctanh(double, double) [[READNONE]] +// HAS_ERRNO: declare <2 x float> @ctanhf(<2 x float>) [[READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @ctanhl({ x86_fp80, x86_fp80 }* byval align 16) [[NOT_READNONE]] +}; + + +// NO__ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// NO__ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// NO__ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } +// NO__ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } + +// HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind "correctly{{.*}} } +// HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[READONLY]] = { {{.*}}readonly{{.*}} } +// HAS_ERRNO: attributes [[READNONE_INTRINSIC]] = { {{.*}}readnone{{.*}} } + -- cgit v1.2.3 From c7e8e8e2edf48ee98341a80e713e2947a4861a55 Mon Sep 17 00:00:00 2001 From: Kostya Kortchinsky Date: Fri, 3 Nov 2017 17:04:13 +0000 Subject: [Driver] Add Scudo as a possible -fsanitize= option Summary: This change adds Scudo as a possible Sanitizer option via -fsanitize=. This allows for easier static & shared linking of the Scudo library, it allows us to enforce PIE (otherwise the security of the allocator is moot), and check for incompatible Sanitizers combo. In its current form, Scudo is not compatible with any other Sanitizer, but the plan is to make it work in conjunction with UBsan (-fsanitize=scudo,undefined), which will require additional work outside of the scope of this change. Reviewers: eugenis, kcc, alekseyshl Reviewed By: eugenis, alekseyshl Subscribers: llvm-commits, srhines Differential Revision: https://reviews.llvm.org/D39334 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317337 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Sanitizers.def | 3 +++ include/clang/Driver/SanitizerArgs.h | 1 + lib/Driver/SanitizerArgs.cpp | 23 ++++++++--------- lib/Driver/ToolChains/CommonArgs.cpp | 8 +++++- lib/Driver/ToolChains/Linux.cpp | 5 ++-- lib/Lex/PPMacroExpansion.cpp | 1 + test/Driver/fsanitize.c | 26 +++++++++++++++++++ test/Driver/sanitizer-ld.c | 50 ++++++++++++++++++++++++++++++++++++ 8 files changed, 101 insertions(+), 16 deletions(-) diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index d6df617172..3586fc228d 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -135,6 +135,9 @@ SANITIZER("efficiency-working-set", EfficiencyWorkingSet) SANITIZER_GROUP("efficiency-all", Efficiency, EfficiencyCacheFrag | EfficiencyWorkingSet) +// Scudo hardened allocator +SANITIZER("scudo", Scudo) + // Magic group, containing all sanitizers. For example, "-fno-sanitize=all" // can be used to disable all the sanitizers. SANITIZER_GROUP("all", All, ~0ULL) diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index 19309c3f3b..44083aec16 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -72,6 +72,7 @@ class SanitizerArgs { bool needsEsanRt() const { return Sanitizers.hasOneOf(SanitizerKind::Efficiency); } + bool needsScudoRt() const { return Sanitizers.has(SanitizerKind::Scudo); } bool requiresPIE() const; bool needsUnwindTables() const; diff --git a/lib/Driver/SanitizerArgs.cpp b/lib/Driver/SanitizerArgs.cpp index 32c1c43a5b..8d9f32f848 100644 --- a/lib/Driver/SanitizerArgs.cpp +++ b/lib/Driver/SanitizerArgs.cpp @@ -30,7 +30,7 @@ enum : SanitizerMask { NeedsUbsanCxxRt = Vptr | CFI, NotAllowedWithTrap = Vptr, NotAllowedWithMinimalRuntime = Vptr, - RequiresPIE = DataFlow, + RequiresPIE = DataFlow | Scudo, NeedsUnwindTables = Address | Thread | Memory | DataFlow, SupportsCoverage = Address | KernelAddress | Memory | Leak | Undefined | Integer | Nullability | DataFlow | Fuzzer | FuzzerNoLink, @@ -173,7 +173,7 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D, bool SanitizerArgs::needsUbsanRt() const { // All of these include ubsan. if (needsAsanRt() || needsMsanRt() || needsTsanRt() || needsDfsanRt() || - needsLsanRt() || needsCfiDiagRt()) + needsLsanRt() || needsCfiDiagRt() || needsScudoRt()) return false; return (Sanitizers.Mask & NeedsUbsanRt & ~TrapSanitizers.Mask) || @@ -370,17 +370,14 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, // Warn about incompatible groups of sanitizers. std::pair IncompatibleGroups[] = { - std::make_pair(Address, Thread), std::make_pair(Address, Memory), - std::make_pair(Thread, Memory), std::make_pair(Leak, Thread), - std::make_pair(Leak, Memory), std::make_pair(KernelAddress, Address), - std::make_pair(KernelAddress, Leak), - std::make_pair(KernelAddress, Thread), - std::make_pair(KernelAddress, Memory), - std::make_pair(Efficiency, Address), - std::make_pair(Efficiency, Leak), - std::make_pair(Efficiency, Thread), - std::make_pair(Efficiency, Memory), - std::make_pair(Efficiency, KernelAddress)}; + std::make_pair(Address, Thread | Memory), + std::make_pair(Thread, Memory), + std::make_pair(Leak, Thread | Memory), + std::make_pair(KernelAddress, Address| Leak | Thread | Memory), + std::make_pair(Efficiency, Address | Leak | Thread | Memory | + KernelAddress), + std::make_pair(Scudo, Address | Leak | Thread | Memory | KernelAddress | + Efficiency) }; for (auto G : IncompatibleGroups) { SanitizerMask Group = G.first; if (Kinds & Group) { diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index b359cbb77e..91f653a53e 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -566,7 +566,6 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, if (!Args.hasArg(options::OPT_shared) && !TC.getTriple().isAndroid()) HelperStaticRuntimes.push_back("asan-preinit"); } - if (SanArgs.needsUbsanRt()) { if (SanArgs.requiresMinimalRuntime()) { SharedRuntimes.push_back("ubsan_minimal"); @@ -574,6 +573,8 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, SharedRuntimes.push_back("ubsan_standalone"); } } + if (SanArgs.needsScudoRt()) + SharedRuntimes.push_back("scudo"); } // The stats_client library is also statically linked into DSOs. @@ -630,6 +631,11 @@ collectSanitizerRuntimes(const ToolChain &TC, const ArgList &Args, } if (SanArgs.needsEsanRt()) StaticRuntimes.push_back("esan"); + if (SanArgs.needsScudoRt()) { + StaticRuntimes.push_back("scudo"); + if (SanArgs.linkCXXRuntimes()) + StaticRuntimes.push_back("scudo_cxx"); + } } // Should be called before we add system libraries (C++ ABI, libstdc++/libc++, diff --git a/lib/Driver/ToolChains/Linux.cpp b/lib/Driver/ToolChains/Linux.cpp index 613a9f3c88..9b722166c5 100644 --- a/lib/Driver/ToolChains/Linux.cpp +++ b/lib/Driver/ToolChains/Linux.cpp @@ -845,9 +845,10 @@ SanitizerMask Linux::getSupportedSanitizers() const { Res |= SanitizerKind::Memory; if (IsX86_64 || IsMIPS64) Res |= SanitizerKind::Efficiency; - if (IsX86 || IsX86_64) { + if (IsX86 || IsX86_64) Res |= SanitizerKind::Function; - } + if (IsX86_64 || IsMIPS64 || IsAArch64 || IsX86 || IsArmArch) + Res |= SanitizerKind::Scudo; return Res; } diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index b0330f2881..9f0c88dd97 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -1138,6 +1138,7 @@ static bool HasFeature(const Preprocessor &PP, StringRef Feature) { .Case("dataflow_sanitizer", LangOpts.Sanitize.has(SanitizerKind::DataFlow)) .Case("efficiency_sanitizer", LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) + .Case("scudo", LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) // Objective-C features .Case("objc_arr", LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? .Case("objc_arc", LangOpts.ObjCAutoRefCount) diff --git a/test/Driver/fsanitize.c b/test/Driver/fsanitize.c index dcca96ff3a..3de6fa0b35 100644 --- a/test/Driver/fsanitize.c +++ b/test/Driver/fsanitize.c @@ -608,3 +608,29 @@ // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-trap=cfi-derived-cast,cfi-unrelated-cast,cfi-nvcall,cfi-vcall" // CHECK-CFI-NOICALL-MINIMAL: "-fsanitize-minimal-runtime" + +// RUN: %clang -target aarch64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO +// RUN: %clang -target arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO +// RUN: %clang -target i386-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO +// CHECK-SCUDO: "-fsanitize=scudo" + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE +// RUN: %clang -target arm-linux-androideabi -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-PIE +// CHECK-SCUDO-PIE: "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" +// CHECK-SCUDO-PIE: "-pie" + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-UBSAN +// CHECK-SCUDO-UBSAN: "-fsanitize={{.*}}scudo" + +// RUN: %clang -target powerpc-unknown-linux -fsanitize=scudo %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-SCUDO +// CHECK-NO-SCUDO: unsupported option + +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-ASAN +// CHECK-SCUDO-ASAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=address' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,leak %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-LSAN +// CHECK-SCUDO-LSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=leak' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,memory %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-MSAN +// CHECK-SCUDO-MSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=memory' +// RUN: %clang -target x86_64-linux-gnu -fsanitize=scudo,thread %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SCUDO-TSAN +// CHECK-SCUDO-TSAN: error: invalid argument '-fsanitize=scudo' not allowed with '-fsanitize=thread' diff --git a/test/Driver/sanitizer-ld.c b/test/Driver/sanitizer-ld.c index f03714c4b5..8fc31fe37a 100644 --- a/test/Driver/sanitizer-ld.c +++ b/test/Driver/sanitizer-ld.c @@ -644,3 +644,53 @@ // // CHECK-ESAN-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" // CHECK-ESAN-LINUX: libclang_rt.esan-x86_64.a + +// RUN: %clang -fsanitize=scudo %s -### -o %t.o 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-SCUDO-LINUX %s +// CHECK-SCUDO-LINUX: "{{.*}}ld{{(.exe)?}}" +// CHECK-SCUDO-LINUX: "-pie" +// CHECK-SCUDO-LINUX: "-whole-archive" "{{.*}}libclang_rt.scudo-i386.a" "-no-whole-archive" +// CHECK-SCUDO-LINUX-NOT: "-lstdc++" +// CHECK-SCUDO-LINUX: "-lpthread" +// CHECK-SCUDO-LINUX: "-ldl" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.so -shared 2>&1 \ +// RUN: -target i386-unknown-linux -fuse-ld=ld -fsanitize=scudo -shared-libsan \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: --sysroot=%S/Inputs/basic_linux_tree \ +// RUN: | FileCheck --check-prefix=CHECK-SCUDO-SHARED-LINUX %s +// +// CHECK-SCUDO-SHARED-LINUX: "{{(.*[^-.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-SCUDO-SHARED-LINUX-NOT: "-lc" +// CHECK-SCUDO-SHARED-LINUX-NOT: libclang_rt.scudo-i386.a" +// CHECK-SCUDO-SHARED-LINUX: libclang_rt.scudo-i386.so" +// CHECK-SCUDO-SHARED-LINUX-NOT: "-lpthread" +// CHECK-SCUDO-SHARED-LINUX-NOT: "-lrt" +// CHECK-SCUDO-SHARED-LINUX-NOT: "-ldl" +// CHECK-SCUDO-SHARED-LINUX-NOT: "-export-dynamic" +// CHECK-SCUDO-SHARED-LINUX-NOT: "--dynamic-list" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=scudo \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: | FileCheck --check-prefix=CHECK-SCUDO-ANDROID %s +// +// CHECK-SCUDO-ANDROID: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-SCUDO-ANDROID-NOT: "-lc" +// CHECK-SCUDO-ANDROID: "-pie" +// CHECK-SCUDO-ANDROID-NOT: "-lpthread" +// CHECK-SCUDO-ANDROID: libclang_rt.scudo-arm-android.so" +// CHECK-SCUDO-ANDROID-NOT: "-lpthread" + +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target arm-linux-androideabi -fuse-ld=ld -fsanitize=scudo \ +// RUN: --sysroot=%S/Inputs/basic_android_tree/sysroot \ +// RUN: -static-libsan \ +// RUN: | FileCheck --check-prefix=CHECK-SCUDO-ANDROID-STATIC %s +// CHECK-SCUDO-ANDROID-STATIC: "{{(.*[^.0-9A-Z_a-z])?}}ld{{(.exe)?}}" +// CHECK-SCUDO-ANDROID-STATIC: "-pie" +// CHECK-SCUDO-ANDROID-STATIC: "-whole-archive" "{{.*}}libclang_rt.scudo-arm-android.a" "-no-whole-archive" +// CHECK-SCUDO-ANDROID-STATIC-NOT: "-lstdc++" +// CHECK-SCUDO-ANDROID-STATIC: "-lpthread" -- cgit v1.2.3 From 92684aa6d4f1860a13ae9ea702b711afaaa94168 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Fri, 3 Nov 2017 18:11:22 +0000 Subject: [refactor][extract] insert semicolons into extracted/inserted code when needed This commit implements the semicolon insertion logic into the extract refactoring. The following rules are used: - extracting expression: add terminating ';' to the extracted function. - extracting statements that don't require terminating ';' (e.g. switch): add terminating ';' to the callee. - extracting statements with ';': move (if possible) the original ';' from the callee and add terminating ';'. - otherwise, add ';' to both places. Differential Revision: https://reviews.llvm.org/D39441 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317343 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/Lexer.h | 7 + lib/Lex/Lexer.cpp | 36 ++-- lib/Tooling/Refactoring/CMakeLists.txt | 3 +- lib/Tooling/Refactoring/Extract.cpp | 10 +- .../Refactoring/Extract/SourceExtraction.cpp | 112 ++++++++++++ lib/Tooling/Refactoring/Extract/SourceExtraction.h | 52 ++++++ test/Refactor/Extract/ExtractExprIntoFunction.cpp | 4 +- .../Refactor/Extract/ExtractionSemicolonPolicy.cpp | 192 +++++++++++++++++++++ test/Refactor/Extract/ExtractionSemicolonPolicy.m | 56 ++++++ 9 files changed, 450 insertions(+), 22 deletions(-) create mode 100644 lib/Tooling/Refactoring/Extract/SourceExtraction.cpp create mode 100644 lib/Tooling/Refactoring/Extract/SourceExtraction.h create mode 100644 test/Refactor/Extract/ExtractionSemicolonPolicy.cpp create mode 100644 test/Refactor/Extract/ExtractionSemicolonPolicy.m diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 603ce10f64..9ad3e21476 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -466,6 +466,13 @@ public: const LangOptions &LangOpts, unsigned MaxLines = 0); + /// Finds the token that comes right after the given location. + /// + /// Returns the next token, or none if the location is inside a macro. + static Optional findNextToken(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts); + /// \brief Checks that the given token is the first token that occurs after /// the given location (this excludes comments and whitespace). Returns the /// location immediately after the specified token. If the token is not found diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 5132d0e62c..67dcff6b71 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -1212,18 +1212,12 @@ const char *Lexer::SkipEscapedNewLines(const char *P) { } } -/// \brief Checks that the given token is the first token that occurs after the -/// given location (this excludes comments and whitespace). Returns the location -/// immediately after the specified token. If the token is not found or the -/// location is inside a macro, the returned source location will be invalid. -SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc, - tok::TokenKind TKind, - const SourceManager &SM, - const LangOptions &LangOpts, - bool SkipTrailingWhitespaceAndNewLine) { +Optional Lexer::findNextToken(SourceLocation Loc, + const SourceManager &SM, + const LangOptions &LangOpts) { if (Loc.isMacroID()) { if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc)) - return SourceLocation(); + return None; } Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts); @@ -1234,7 +1228,7 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc, bool InvalidTemp = false; StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp); if (InvalidTemp) - return SourceLocation(); + return None; const char *TokenBegin = File.data() + LocInfo.second; @@ -1244,15 +1238,25 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc, // Find the token. Token Tok; lexer.LexFromRawLexer(Tok); - if (Tok.isNot(TKind)) + return Tok; +} + +/// \brief Checks that the given token is the first token that occurs after the +/// given location (this excludes comments and whitespace). Returns the location +/// immediately after the specified token. If the token is not found or the +/// location is inside a macro, the returned source location will be invalid. +SourceLocation Lexer::findLocationAfterToken( + SourceLocation Loc, tok::TokenKind TKind, const SourceManager &SM, + const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine) { + Optional Tok = findNextToken(Loc, SM, LangOpts); + if (!Tok || Tok->isNot(TKind)) return SourceLocation(); - SourceLocation TokenLoc = Tok.getLocation(); + SourceLocation TokenLoc = Tok->getLocation(); // Calculate how much whitespace needs to be skipped if any. unsigned NumWhitespaceChars = 0; if (SkipTrailingWhitespaceAndNewLine) { - const char *TokenEnd = SM.getCharacterData(TokenLoc) + - Tok.getLength(); + const char *TokenEnd = SM.getCharacterData(TokenLoc) + Tok->getLength(); unsigned char C = *TokenEnd; while (isHorizontalWhitespace(C)) { C = *(++TokenEnd); @@ -1269,7 +1273,7 @@ SourceLocation Lexer::findLocationAfterToken(SourceLocation Loc, } } - return TokenLoc.getLocWithOffset(Tok.getLength() + NumWhitespaceChars); + return TokenLoc.getLocWithOffset(Tok->getLength() + NumWhitespaceChars); } /// getCharAndSizeSlow - Peek a single 'character' from the specified buffer, diff --git a/lib/Tooling/Refactoring/CMakeLists.txt b/lib/Tooling/Refactoring/CMakeLists.txt index 5d3ddd45b6..402b5d3c6a 100644 --- a/lib/Tooling/Refactoring/CMakeLists.txt +++ b/lib/Tooling/Refactoring/CMakeLists.txt @@ -4,7 +4,8 @@ add_clang_library(clangToolingRefactor ASTSelection.cpp ASTSelectionRequirements.cpp AtomicChange.cpp - Extract.cpp + Extract/Extract.cpp + Extract/SourceExtraction.cpp RefactoringActions.cpp Rename/RenamingAction.cpp Rename/SymbolOccurrences.cpp diff --git a/lib/Tooling/Refactoring/Extract.cpp b/lib/Tooling/Refactoring/Extract.cpp index 3f5a839318..b0847a7400 100644 --- a/lib/Tooling/Refactoring/Extract.cpp +++ b/lib/Tooling/Refactoring/Extract.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "clang/Tooling/Refactoring/Extract/Extract.h" +#include "SourceExtraction.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" @@ -145,6 +146,8 @@ ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) { PP.SuppressLifetimeQualifiers = true; PP.SuppressUnwrittenScope = true; + ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute( + Code[Code.size() - 1], ExtractedRange, SM, LangOpts); AtomicChange Change(SM, ExtractedDeclLocation); // Create the replacement for the extracted declaration. { @@ -162,8 +165,8 @@ ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) { if (IsExpr && !ReturnType->isVoidType()) OS << "return "; OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange); - // FIXME: Compute the correct semicolon policy. - OS << ';'; + if (Semicolons.isNeededInExtractedFunction()) + OS << ';'; OS << "\n}\n\n"; auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str()); if (Err) @@ -178,7 +181,8 @@ ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) { OS << DeclName << '('; // FIXME: Forward arguments. OS << ')'; - // FIXME: Add semicolon if needed. + if (Semicolons.isNeededInOriginalFunction()) + OS << ';'; auto Err = Change.replace( SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str()); diff --git a/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp b/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp new file mode 100644 index 0000000000..7fd8cc2d3c --- /dev/null +++ b/lib/Tooling/Refactoring/Extract/SourceExtraction.cpp @@ -0,0 +1,112 @@ +//===--- SourceExtraction.cpp - Clang refactoring library -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SourceExtraction.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Lex/Lexer.h" + +using namespace clang; + +namespace { + +/// Returns true if the token at the given location is a semicolon. +bool isSemicolonAtLocation(SourceLocation TokenLoc, const SourceManager &SM, + const LangOptions &LangOpts) { + return Lexer::getSourceText( + CharSourceRange::getTokenRange(TokenLoc, TokenLoc), SM, + LangOpts) == ";"; +} + +/// Returns true if there should be a semicolon after the given statement. +bool isSemicolonRequiredAfter(const Stmt *S) { + if (isa(S)) + return false; + if (const auto *If = dyn_cast(S)) + return isSemicolonRequiredAfter(If->getElse() ? If->getElse() + : If->getThen()); + if (const auto *While = dyn_cast(S)) + return isSemicolonRequiredAfter(While->getBody()); + if (const auto *For = dyn_cast(S)) + return isSemicolonRequiredAfter(For->getBody()); + if (const auto *CXXFor = dyn_cast(S)) + return isSemicolonRequiredAfter(CXXFor->getBody()); + if (const auto *ObjCFor = dyn_cast(S)) + return isSemicolonRequiredAfter(ObjCFor->getBody()); + switch (S->getStmtClass()) { + case Stmt::SwitchStmtClass: + case Stmt::CXXTryStmtClass: + case Stmt::ObjCAtSynchronizedStmtClass: + case Stmt::ObjCAutoreleasePoolStmtClass: + case Stmt::ObjCAtTryStmtClass: + return false; + default: + return true; + } +} + +/// Returns true if the two source locations are on the same line. +bool areOnSameLine(SourceLocation Loc1, SourceLocation Loc2, + const SourceManager &SM) { + return !Loc1.isMacroID() && !Loc2.isMacroID() && + SM.getSpellingLineNumber(Loc1) == SM.getSpellingLineNumber(Loc2); +} + +} // end anonymous namespace + +namespace clang { +namespace tooling { + +ExtractionSemicolonPolicy +ExtractionSemicolonPolicy::compute(const Stmt *S, SourceRange &ExtractedRange, + const SourceManager &SM, + const LangOptions &LangOpts) { + auto neededInExtractedFunction = []() { + return ExtractionSemicolonPolicy(true, false); + }; + auto neededInOriginalFunction = []() { + return ExtractionSemicolonPolicy(false, true); + }; + + /// The extracted expression should be terminated with a ';'. The call to + /// the extracted function will replace this expression, so it won't need + /// a terminating ';'. + if (isa(S)) + return neededInExtractedFunction(); + + /// Some statements don't need to be terminated with ';'. The call to the + /// extracted function will be a standalone statement, so it should be + /// terminated with a ';'. + bool NeedsSemi = isSemicolonRequiredAfter(S); + if (!NeedsSemi) + return neededInOriginalFunction(); + + /// Some statements might end at ';'. The extraction will move that ';', so + /// the call to the extracted function should be terminated with a ';'. + SourceLocation End = ExtractedRange.getEnd(); + if (isSemicolonAtLocation(End, SM, LangOpts)) + return neededInOriginalFunction(); + + /// Other statements should generally have a trailing ';'. We can try to find + /// it and move it together it with the extracted code. + Optional NextToken = Lexer::findNextToken(End, SM, LangOpts); + if (NextToken && NextToken->is(tok::semi) && + areOnSameLine(NextToken->getLocation(), End, SM)) { + ExtractedRange.setEnd(NextToken->getLocation()); + return neededInOriginalFunction(); + } + + /// Otherwise insert semicolons in both places. + return ExtractionSemicolonPolicy(true, true); +} + +} // end namespace tooling +} // end namespace clang diff --git a/lib/Tooling/Refactoring/Extract/SourceExtraction.h b/lib/Tooling/Refactoring/Extract/SourceExtraction.h new file mode 100644 index 0000000000..4b4bd8b477 --- /dev/null +++ b/lib/Tooling/Refactoring/Extract/SourceExtraction.h @@ -0,0 +1,52 @@ +//===--- SourceExtraction.cpp - Clang refactoring library -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H +#define LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H + +#include "clang/Basic/LLVM.h" + +namespace clang { + +class LangOptions; +class SourceManager; +class SourceRange; +class Stmt; + +namespace tooling { + +/// Determines which semicolons should be inserted during extraction. +class ExtractionSemicolonPolicy { +public: + bool isNeededInExtractedFunction() const { + return IsNeededInExtractedFunction; + } + + bool isNeededInOriginalFunction() const { return IsNeededInOriginalFunction; } + + /// Returns the semicolon insertion policy that is needed for extraction of + /// the given statement from the given source range. + static ExtractionSemicolonPolicy compute(const Stmt *S, + SourceRange &ExtractedRange, + const SourceManager &SM, + const LangOptions &LangOpts); + +private: + ExtractionSemicolonPolicy(bool IsNeededInExtractedFunction, + bool IsNeededInOriginalFunction) + : IsNeededInExtractedFunction(IsNeededInExtractedFunction), + IsNeededInOriginalFunction(IsNeededInOriginalFunction) {} + bool IsNeededInExtractedFunction; + bool IsNeededInOriginalFunction; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_LIB_TOOLING_REFACTORING_EXTRACT_SOURCE_EXTRACTION_H diff --git a/test/Refactor/Extract/ExtractExprIntoFunction.cpp b/test/Refactor/Extract/ExtractExprIntoFunction.cpp index be610fc303..b4f0b59543 100644 --- a/test/Refactor/Extract/ExtractExprIntoFunction.cpp +++ b/test/Refactor/Extract/ExtractExprIntoFunction.cpp @@ -20,10 +20,10 @@ void simpleExtractStmtNoCaptures() { // CHECK: 1 'astatement' results: // CHECK: static void extracted() { // CHECK-NEXT: int a = 1; -// CHECK-NEXT: int b = 2;;{{$}} +// CHECK-NEXT: int b = 2;{{$}} // CHECK-NEXT: }{{[[:space:]].*}} // CHECK-NEXT: void simpleExtractStmtNoCaptures() { -// CHECK-NEXT: /*range astatement=->+1:13*/extracted(){{$}} +// CHECK-NEXT: /*range astatement=->+1:13*/extracted();{{$}} // CHECK-NEXT: } diff --git a/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp b/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp new file mode 100644 index 0000000000..22e7f3272e --- /dev/null +++ b/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp @@ -0,0 +1,192 @@ +// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 2>&1 | grep -v CHECK | FileCheck %s + +struct Rectangle { int width, height; }; + +void extractStatement(const Rectangle &r) { + /*range adeclstmt=->+0:59*/int area = r.width * r.height; +} +// CHECK: 1 'adeclstmt' results: +// CHECK: static void extracted() { +// CHECK-NEXT: int area = r.width * r.height;{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatement(const Rectangle &r) { +// CHECK-NEXT: /*range adeclstmt=->+0:59*/extracted();{{$}} +// CHECK-NEXT: } + +void extractStatementNoSemiIf(const Rectangle &r) { + /*range bextractif=->+2:4*/if (r.width) { + int x = r.height; + } +} +// CHECK: 1 'bextractif' results: +// CHECK: static void extracted() { +// CHECK-NEXT: if (r.width) { +// CHECK-NEXT: int x = r.height; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementNoSemiIf(const Rectangle &r) { +// CHECK-NEXT: /*range bextractif=->+2:4*/extracted();{{$}} +// CHECK-NEXT: } + +void extractStatementDontExtraneousSemi(const Rectangle &r) { + /*range cextractif=->+2:4*/if (r.width) { + int x = r.height; + } ; +} //^ This semicolon shouldn't be extracted. +// CHECK: 1 'cextractif' results: +// CHECK: static void extracted() { +// CHECK-NEXT: if (r.width) { +// CHECK-NEXT: int x = r.height; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementDontExtraneousSemi(const Rectangle &r) { +// CHECK-NEXT: extracted(); ;{{$}} +// CHECK-NEXT: } + +void extractStatementNotSemiSwitch() { + /*range dextract=->+5:4*/switch (2) { + case 1: + break; + case 2: + break; + } +} +// CHECK: 1 'dextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: switch (2) { +// CHECK-NEXT: case 1: +// CHECK-NEXT: break; +// CHECK-NEXT: case 2: +// CHECK-NEXT: break; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementNotSemiSwitch() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +void extractStatementNotSemiWhile() { + /*range eextract=->+2:4*/while (true) { + int x = 0; + } +} +// CHECK: 1 'eextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: while (true) { +// CHECK-NEXT: int x = 0; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementNotSemiWhile() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +void extractStatementNotSemiFor() { + /*range fextract=->+1:4*/for (int i = 0; i < 10; ++i) { + } +} +// CHECK: 1 'fextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: for (int i = 0; i < 10; ++i) { +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementNotSemiFor() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +struct XS { + int *begin() { return 0; } + int *end() { return 0; } +}; + +void extractStatementNotSemiRangedFor(XS xs) { + /*range gextract=->+1:4*/for (int i : xs) { + } +} +// CHECK: 1 'gextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: for (int i : xs) { +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementNotSemiRangedFor(XS xs) { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +void extractStatementNotSemiRangedTryCatch() { + /*range hextract=->+3:4*/try { int x = 0; } + catch (const int &i) { + int y = i; + } +} +// CHECK: 1 'hextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: try { int x = 0; } +// CHECK-NEXT: catch (const int &i) { +// CHECK-NEXT: int y = i; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractStatementNotSemiRangedTryCatch() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +void extractCantFindSemicolon() { + /*range iextract=->+1:17*/do { + } while (true) + // Add a semicolon in both the extracted and original function as we don't + // want to extract the semicolon below. + ; +} +// CHECK: 1 'iextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: do { +// CHECK-NEXT: } while (true);{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractCantFindSemicolon() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: // +// CHECK-NEXT: // +// CHECK-NEXT: ; +// CHECK-NEXT: } + +void extractFindSemicolon() { + /*range jextract=->+1:17*/do { + } while (true) /*grab*/ ; +} +// CHECK: 1 'jextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: do { +// CHECK-NEXT: } while (true) /*grab*/ ;{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void extractFindSemicolon() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +void call(); + +void careForNonCompoundSemicolons1() { + /*range kextract=->+1:11*/if (true) + call(); +} +// CHECK: 1 'kextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: if (true) +// CHECK-NEXT: call();{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void careForNonCompoundSemicolons1() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: } + +void careForNonCompoundSemicolons2() { + /*range lextract=->+3:1*/for (int i = 0; i < 10; ++i) + while (i != 0) + ; + // end right here111! +} +// CHECK: 1 'lextract' results: +// CHECK: static void extracted() { +// CHECK-NEXT: for (int i = 0; i < 10; ++i) +// CHECK-NEXT: while (i != 0) +// CHECK-NEXT: ;{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} +// CHECK-NEXT: void careForNonCompoundSemicolons2() { +// CHECK-NEXT: extracted();{{$}} +// CHECK-NEXT: // +// CHECK-NEXT: } diff --git a/test/Refactor/Extract/ExtractionSemicolonPolicy.m b/test/Refactor/Extract/ExtractionSemicolonPolicy.m new file mode 100644 index 0000000000..10e6a164f2 --- /dev/null +++ b/test/Refactor/Extract/ExtractionSemicolonPolicy.m @@ -0,0 +1,56 @@ +// RUN: clang-refactor extract -selection=test:%s %s -- 2>&1 | grep -v CHECK | FileCheck %s + +@interface NSArray ++ (id)arrayWithObjects:(const id [])objects count:(unsigned long)cnt; +@end + +void extractStatementNoSemiObjCFor(NSArray *array) { + /*range astmt=->+2:4*/for (id i in array) { + int x = 0; + } +} +// CHECK: 1 'astmt' results: +// CHECK: static void extracted() { +// CHECK-NEXT: for (id i in array) { +// CHECK-NEXT: int x = 0; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} + +void extractStatementNoSemiSync() { + id lock; + /*range bstmt=->+2:4*/@synchronized(lock) { + int x = 0; + } +} +// CHECK: 1 'bstmt' results: +// CHECK: static void extracted() { +// CHECK-NEXT: @synchronized(lock) { +// CHECK-NEXT: int x = 0; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} + +void extractStatementNoSemiAutorel() { + /*range cstmt=->+2:4*/@autoreleasepool { + int x = 0; + } +} +// CHECK: 1 'cstmt' results: +// CHECK: static void extracted() { +// CHECK-NEXT: @autoreleasepool { +// CHECK-NEXT: int x = 0; +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} + +void extractStatementNoSemiTryFinalllllly() { + /*range dstmt=->+3:4*/@try { + int x = 0; + } @finally { + } +} +// CHECK: 1 'dstmt' results: +// CHECK: static void extracted() { +// CHECK-NEXT: @try { +// CHECK-NEXT: int x = 0; +// CHECK-NEXT: } @finally { +// CHECK-NEXT: }{{$}} +// CHECK-NEXT: }{{[[:space:]].*}} -- cgit v1.2.3 From 7688b529d4f4c8b70083590dc335dee2ef7130fd Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Fri, 3 Nov 2017 18:21:06 +0000 Subject: Move Extract.cpp that wasn't moved in r317343 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317344 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Tooling/Refactoring/Extract.cpp | 199 ---------------------------- lib/Tooling/Refactoring/Extract/Extract.cpp | 199 ++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+), 199 deletions(-) delete mode 100644 lib/Tooling/Refactoring/Extract.cpp create mode 100644 lib/Tooling/Refactoring/Extract/Extract.cpp diff --git a/lib/Tooling/Refactoring/Extract.cpp b/lib/Tooling/Refactoring/Extract.cpp deleted file mode 100644 index b0847a7400..0000000000 --- a/lib/Tooling/Refactoring/Extract.cpp +++ /dev/null @@ -1,199 +0,0 @@ -//===--- Extract.cpp - Clang refactoring library --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief Implements the "extract" refactoring that can pull code into -/// new functions, methods or declare new variables. -/// -//===----------------------------------------------------------------------===// - -#include "clang/Tooling/Refactoring/Extract/Extract.h" -#include "SourceExtraction.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/Expr.h" -#include "clang/AST/ExprObjC.h" -#include "clang/Rewrite/Core/Rewriter.h" - -namespace clang { -namespace tooling { - -namespace { - -/// Returns true if \c E is a simple literal or a reference expression that -/// should not be extracted. -bool isSimpleExpression(const Expr *E) { - if (!E) - return false; - switch (E->IgnoreParenCasts()->getStmtClass()) { - case Stmt::DeclRefExprClass: - case Stmt::PredefinedExprClass: - case Stmt::IntegerLiteralClass: - case Stmt::FloatingLiteralClass: - case Stmt::ImaginaryLiteralClass: - case Stmt::CharacterLiteralClass: - case Stmt::StringLiteralClass: - return true; - default: - return false; - } -} - -SourceLocation computeFunctionExtractionLocation(const Decl *D) { - if (isa(D)) { - // Code from method that is defined in class body should be extracted to a - // function defined just before the class. - while (const auto *RD = dyn_cast(D->getLexicalDeclContext())) - D = RD; - } - return D->getLocStart(); -} - -} // end anonymous namespace - -const RefactoringDescriptor &ExtractFunction::describe() { - static const RefactoringDescriptor Descriptor = { - "extract-function", - "Extract Function", - "(WIP action; use with caution!) Extracts code into a new function", - }; - return Descriptor; -} - -Expected -ExtractFunction::initiate(RefactoringRuleContext &Context, - CodeRangeASTSelection Code, - Optional DeclName) { - // We would like to extract code out of functions/methods/blocks. - // Prohibit extraction from things like global variable / field - // initializers and other top-level expressions. - if (!Code.isInFunctionLikeBodyOfCode()) - return Context.createDiagnosticError( - diag::err_refactor_code_outside_of_function); - - if (Code.size() == 1) { - // Avoid extraction of simple literals and references. - if (isSimpleExpression(dyn_cast(Code[0]))) - return Context.createDiagnosticError( - diag::err_refactor_extract_simple_expression); - - // Property setters can't be extracted. - if (const auto *PRE = dyn_cast(Code[0])) { - if (!PRE->isMessagingGetter()) - return Context.createDiagnosticError( - diag::err_refactor_extract_prohibited_expression); - } - } - - return ExtractFunction(std::move(Code), DeclName); -} - -// FIXME: Support C++ method extraction. -// FIXME: Support Objective-C method extraction. -Expected -ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) { - const Decl *ParentDecl = Code.getFunctionLikeNearestParent(); - assert(ParentDecl && "missing parent"); - - // Compute the source range of the code that should be extracted. - SourceRange ExtractedRange(Code[0]->getLocStart(), - Code[Code.size() - 1]->getLocEnd()); - // FIXME (Alex L): Add code that accounts for macro locations. - - ASTContext &AST = Context.getASTContext(); - SourceManager &SM = AST.getSourceManager(); - const LangOptions &LangOpts = AST.getLangOpts(); - Rewriter ExtractedCodeRewriter(SM, LangOpts); - - // FIXME: Capture used variables. - - // Compute the return type. - QualType ReturnType = AST.VoidTy; - // FIXME (Alex L): Account for the return statement in extracted code. - // FIXME (Alex L): Check for lexical expression instead. - bool IsExpr = Code.size() == 1 && isa(Code[0]); - if (IsExpr) { - // FIXME (Alex L): Get a more user-friendly type if needed. - ReturnType = cast(Code[0])->getType(); - } - - // FIXME: Rewrite the extracted code performing any required adjustments. - - // FIXME: Capture any field if necessary (method -> function extraction). - - // FIXME: Sort captured variables by name. - - // FIXME: Capture 'this' / 'self' if necessary. - - // FIXME: Compute the actual parameter types. - - // Compute the location of the extracted declaration. - SourceLocation ExtractedDeclLocation = - computeFunctionExtractionLocation(ParentDecl); - // FIXME: Adjust the location to account for any preceding comments. - - // FIXME: Adjust with PP awareness like in Sema to get correct 'bool' - // treatment. - PrintingPolicy PP = AST.getPrintingPolicy(); - // FIXME: PP.UseStdFunctionForLambda = true; - PP.SuppressStrongLifetime = true; - PP.SuppressLifetimeQualifiers = true; - PP.SuppressUnwrittenScope = true; - - ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute( - Code[Code.size() - 1], ExtractedRange, SM, LangOpts); - AtomicChange Change(SM, ExtractedDeclLocation); - // Create the replacement for the extracted declaration. - { - std::string ExtractedCode; - llvm::raw_string_ostream OS(ExtractedCode); - // FIXME: Use 'inline' in header. - OS << "static "; - ReturnType.print(OS, PP, DeclName); - OS << '('; - // FIXME: Arguments. - OS << ')'; - - // Function body. - OS << " {\n"; - if (IsExpr && !ReturnType->isVoidType()) - OS << "return "; - OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange); - if (Semicolons.isNeededInExtractedFunction()) - OS << ';'; - OS << "\n}\n\n"; - auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str()); - if (Err) - return std::move(Err); - } - - // Create the replacement for the call to the extracted declaration. - { - std::string ReplacedCode; - llvm::raw_string_ostream OS(ReplacedCode); - - OS << DeclName << '('; - // FIXME: Forward arguments. - OS << ')'; - if (Semicolons.isNeededInOriginalFunction()) - OS << ';'; - - auto Err = Change.replace( - SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str()); - if (Err) - return std::move(Err); - } - - // FIXME: Add support for assocciated symbol location to AtomicChange to mark - // the ranges of the name of the extracted declaration. - return AtomicChanges{std::move(Change)}; -} - -} // end namespace tooling -} // end namespace clang diff --git a/lib/Tooling/Refactoring/Extract/Extract.cpp b/lib/Tooling/Refactoring/Extract/Extract.cpp new file mode 100644 index 0000000000..b0847a7400 --- /dev/null +++ b/lib/Tooling/Refactoring/Extract/Extract.cpp @@ -0,0 +1,199 @@ +//===--- Extract.cpp - Clang refactoring library --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Implements the "extract" refactoring that can pull code into +/// new functions, methods or declare new variables. +/// +//===----------------------------------------------------------------------===// + +#include "clang/Tooling/Refactoring/Extract/Extract.h" +#include "SourceExtraction.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" +#include "clang/Rewrite/Core/Rewriter.h" + +namespace clang { +namespace tooling { + +namespace { + +/// Returns true if \c E is a simple literal or a reference expression that +/// should not be extracted. +bool isSimpleExpression(const Expr *E) { + if (!E) + return false; + switch (E->IgnoreParenCasts()->getStmtClass()) { + case Stmt::DeclRefExprClass: + case Stmt::PredefinedExprClass: + case Stmt::IntegerLiteralClass: + case Stmt::FloatingLiteralClass: + case Stmt::ImaginaryLiteralClass: + case Stmt::CharacterLiteralClass: + case Stmt::StringLiteralClass: + return true; + default: + return false; + } +} + +SourceLocation computeFunctionExtractionLocation(const Decl *D) { + if (isa(D)) { + // Code from method that is defined in class body should be extracted to a + // function defined just before the class. + while (const auto *RD = dyn_cast(D->getLexicalDeclContext())) + D = RD; + } + return D->getLocStart(); +} + +} // end anonymous namespace + +const RefactoringDescriptor &ExtractFunction::describe() { + static const RefactoringDescriptor Descriptor = { + "extract-function", + "Extract Function", + "(WIP action; use with caution!) Extracts code into a new function", + }; + return Descriptor; +} + +Expected +ExtractFunction::initiate(RefactoringRuleContext &Context, + CodeRangeASTSelection Code, + Optional DeclName) { + // We would like to extract code out of functions/methods/blocks. + // Prohibit extraction from things like global variable / field + // initializers and other top-level expressions. + if (!Code.isInFunctionLikeBodyOfCode()) + return Context.createDiagnosticError( + diag::err_refactor_code_outside_of_function); + + if (Code.size() == 1) { + // Avoid extraction of simple literals and references. + if (isSimpleExpression(dyn_cast(Code[0]))) + return Context.createDiagnosticError( + diag::err_refactor_extract_simple_expression); + + // Property setters can't be extracted. + if (const auto *PRE = dyn_cast(Code[0])) { + if (!PRE->isMessagingGetter()) + return Context.createDiagnosticError( + diag::err_refactor_extract_prohibited_expression); + } + } + + return ExtractFunction(std::move(Code), DeclName); +} + +// FIXME: Support C++ method extraction. +// FIXME: Support Objective-C method extraction. +Expected +ExtractFunction::createSourceReplacements(RefactoringRuleContext &Context) { + const Decl *ParentDecl = Code.getFunctionLikeNearestParent(); + assert(ParentDecl && "missing parent"); + + // Compute the source range of the code that should be extracted. + SourceRange ExtractedRange(Code[0]->getLocStart(), + Code[Code.size() - 1]->getLocEnd()); + // FIXME (Alex L): Add code that accounts for macro locations. + + ASTContext &AST = Context.getASTContext(); + SourceManager &SM = AST.getSourceManager(); + const LangOptions &LangOpts = AST.getLangOpts(); + Rewriter ExtractedCodeRewriter(SM, LangOpts); + + // FIXME: Capture used variables. + + // Compute the return type. + QualType ReturnType = AST.VoidTy; + // FIXME (Alex L): Account for the return statement in extracted code. + // FIXME (Alex L): Check for lexical expression instead. + bool IsExpr = Code.size() == 1 && isa(Code[0]); + if (IsExpr) { + // FIXME (Alex L): Get a more user-friendly type if needed. + ReturnType = cast(Code[0])->getType(); + } + + // FIXME: Rewrite the extracted code performing any required adjustments. + + // FIXME: Capture any field if necessary (method -> function extraction). + + // FIXME: Sort captured variables by name. + + // FIXME: Capture 'this' / 'self' if necessary. + + // FIXME: Compute the actual parameter types. + + // Compute the location of the extracted declaration. + SourceLocation ExtractedDeclLocation = + computeFunctionExtractionLocation(ParentDecl); + // FIXME: Adjust the location to account for any preceding comments. + + // FIXME: Adjust with PP awareness like in Sema to get correct 'bool' + // treatment. + PrintingPolicy PP = AST.getPrintingPolicy(); + // FIXME: PP.UseStdFunctionForLambda = true; + PP.SuppressStrongLifetime = true; + PP.SuppressLifetimeQualifiers = true; + PP.SuppressUnwrittenScope = true; + + ExtractionSemicolonPolicy Semicolons = ExtractionSemicolonPolicy::compute( + Code[Code.size() - 1], ExtractedRange, SM, LangOpts); + AtomicChange Change(SM, ExtractedDeclLocation); + // Create the replacement for the extracted declaration. + { + std::string ExtractedCode; + llvm::raw_string_ostream OS(ExtractedCode); + // FIXME: Use 'inline' in header. + OS << "static "; + ReturnType.print(OS, PP, DeclName); + OS << '('; + // FIXME: Arguments. + OS << ')'; + + // Function body. + OS << " {\n"; + if (IsExpr && !ReturnType->isVoidType()) + OS << "return "; + OS << ExtractedCodeRewriter.getRewrittenText(ExtractedRange); + if (Semicolons.isNeededInExtractedFunction()) + OS << ';'; + OS << "\n}\n\n"; + auto Err = Change.insert(SM, ExtractedDeclLocation, OS.str()); + if (Err) + return std::move(Err); + } + + // Create the replacement for the call to the extracted declaration. + { + std::string ReplacedCode; + llvm::raw_string_ostream OS(ReplacedCode); + + OS << DeclName << '('; + // FIXME: Forward arguments. + OS << ')'; + if (Semicolons.isNeededInOriginalFunction()) + OS << ';'; + + auto Err = Change.replace( + SM, CharSourceRange::getTokenRange(ExtractedRange), OS.str()); + if (Err) + return std::move(Err); + } + + // FIXME: Add support for assocciated symbol location to AtomicChange to mark + // the ranges of the name of the extracted declaration. + return AtomicChanges{std::move(Change)}; +} + +} // end namespace tooling +} // end namespace clang -- cgit v1.2.3 From fdab8abec144a73be8214108bc736102446e6703 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Fri, 3 Nov 2017 20:09:17 +0000 Subject: Replace a use of std::for_each() with llvm::for_each(); NFC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317359 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaPseudoObject.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Sema/SemaPseudoObject.cpp b/lib/Sema/SemaPseudoObject.cpp index d159172a69..58980be64a 100644 --- a/lib/Sema/SemaPseudoObject.cpp +++ b/lib/Sema/SemaPseudoObject.cpp @@ -1442,8 +1442,7 @@ MSPropertyOpBuilder::getBaseMSProperty(MSPropertySubscriptExpr *E) { Expr *MSPropertyOpBuilder::rebuildAndCaptureObject(Expr *syntacticBase) { InstanceBase = capture(RefExpr->getBaseExpr()); - std::for_each(CallArgs.begin(), CallArgs.end(), - [this](Expr *&Arg) { Arg = capture(Arg); }); + llvm::for_each(CallArgs, [this](Expr *&Arg) { Arg = capture(Arg); }); syntacticBase = Rebuilder(S, [=](Expr *, unsigned Idx) -> Expr * { switch (Idx) { case 0: -- cgit v1.2.3 From 74ca23f2aca0856c94fe84522aa48f692aea4c8f Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Fri, 3 Nov 2017 21:31:10 +0000 Subject: Add -fcxx-exceptions for ExtractionSemicolonPolicy.cpp to appease PS4 bots git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317372 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Refactor/Extract/ExtractionSemicolonPolicy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp b/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp index 22e7f3272e..5caf9d4526 100644 --- a/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp +++ b/test/Refactor/Extract/ExtractionSemicolonPolicy.cpp @@ -1,4 +1,4 @@ -// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 2>&1 | grep -v CHECK | FileCheck %s +// RUN: clang-refactor extract -selection=test:%s %s -- -std=c++11 -fcxx-exceptions | grep -v CHECK | FileCheck %s struct Rectangle { int width, height; }; -- cgit v1.2.3 From dbacc64bb6b227c2a2eea2c7aab097a9c3f8f791 Mon Sep 17 00:00:00 2001 From: Eugene Zelenko Date: Fri, 3 Nov 2017 22:35:27 +0000 Subject: [Basic] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317381 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/IdentifierTable.h | 83 ++++++++++++++-------------- include/clang/Basic/Module.h | 62 ++++++++++++--------- include/clang/Basic/SourceManager.h | 72 ++++++++++++------------ include/clang/Basic/SourceManagerInternals.h | 22 +++++--- lib/Basic/IdentifierTable.cpp | 68 ++++++++++++++--------- lib/Basic/Module.cpp | 25 ++++++--- lib/Basic/SourceManager.cpp | 55 +++++++++--------- 7 files changed, 217 insertions(+), 170 deletions(-) diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 3938e09890..8e3c15afbf 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -1,4 +1,4 @@ -//===--- IdentifierTable.h - Hash table for identifier lookup ---*- C++ -*-===// +//===- IdentifierTable.h - Hash table for identifier lookup -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,11 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and /// clang::Selector interfaces. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H @@ -18,35 +18,29 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" #include #include #include #include -#include #include #include -namespace llvm { - - template struct DenseMapInfo; - -} // end namespace llvm - namespace clang { - class LangOptions; - class IdentifierInfo; - class IdentifierTable; - class SourceLocation; - class MultiKeywordSelector; // private class used by Selector - class DeclarationName; // AST class that stores declaration names +class IdentifierInfo; +class LangOptions; +class MultiKeywordSelector; +class SourceLocation; - /// \brief A simple pair of identifier info and location. - typedef std::pair IdentifierLocPair; +/// \brief A simple pair of identifier info and location. +using IdentifierLocPair = std::pair; /// One of these records is kept for each identifier that /// is lexed. This contains information about whether the token was \#define'd, @@ -85,8 +79,10 @@ class IdentifierInfo { // keyword. // 29 bit left in 64-bit word. - void *FETokenInfo; // Managed by the language front-end. - llvm::StringMapEntry *Entry; + // Managed by the language front-end. + void *FETokenInfo = nullptr; + + llvm::StringMapEntry *Entry = nullptr; public: IdentifierInfo(); @@ -104,7 +100,6 @@ public: /// \brief Return the beginning of the actual null-terminated string for this /// identifier. - /// const char *getNameStart() const { if (Entry) return Entry->getKeyData(); // FIXME: This is gross. It would be best not to embed specific details @@ -112,12 +107,12 @@ public: // The 'this' pointer really points to a // std::pair, where internal pointer // points to the external string data. - typedef std::pair actualtype; + using actualtype = std::pair; + return ((const actualtype*) this)->second; } /// \brief Efficiently return the length of this identifier info. - /// unsigned getLength() const { if (Entry) return Entry->getKeyLength(); // FIXME: This is gross. It would be best not to embed specific details @@ -125,7 +120,8 @@ public: // The 'this' pointer really points to a // std::pair, where internal pointer // points to the external string data. - typedef std::pair actualtype; + using actualtype = std::pair; + const char* p = ((const actualtype*) this)->second - 2; return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; } @@ -465,7 +461,7 @@ public: class IdentifierTable { // Shark shows that using MallocAllocator is *much* slower than using this // BumpPtrAllocator! - typedef llvm::StringMap HashTableTy; + using HashTableTy = llvm::StringMap; HashTableTy HashTable; IdentifierInfoLookup* ExternalLookup; @@ -551,8 +547,8 @@ public: return *II; } - typedef HashTableTy::const_iterator iterator; - typedef HashTableTy::const_iterator const_iterator; + using iterator = HashTableTy::const_iterator; + using const_iterator = HashTableTy::const_iterator; iterator begin() const { return HashTable.begin(); } iterator end() const { return HashTable.end(); } @@ -654,7 +650,9 @@ class Selector { MultiArg = 0x3, ArgFlags = ZeroArg|OneArg }; - uintptr_t InfoPtr; // a pointer to the MultiKeywordSelector or IdentifierInfo. + + // a pointer to the MultiKeywordSelector or IdentifierInfo. + uintptr_t InfoPtr = 0; Selector(IdentifierInfo *II, unsigned nArgs) { InfoPtr = reinterpret_cast(II); @@ -662,6 +660,7 @@ class Selector { assert(nArgs < 2 && "nArgs not equal to 0/1"); InfoPtr |= nArgs+1; } + Selector(MultiKeywordSelector *SI) { InfoPtr = reinterpret_cast(SI); assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); @@ -692,7 +691,7 @@ public: /// The default ctor should only be used when creating data structures that /// will contain selectors. - Selector() : InfoPtr(0) {} + Selector() = default; Selector(uintptr_t V) : InfoPtr(V) {} /// operator==/!= - Indicate whether the specified selectors are identical. @@ -776,7 +775,8 @@ public: /// \brief This table allows us to fully hide how we implement /// multi-keyword caching. class SelectorTable { - void *Impl; // Actually a SelectorTableImpl + // Actually a SelectorTableImpl + void *Impl; public: SelectorTable(); @@ -793,6 +793,7 @@ public: Selector getUnarySelector(IdentifierInfo *ID) { return Selector(ID, 1); } + Selector getNullarySelector(IdentifierInfo *ID) { return Selector(ID, 0); } @@ -848,7 +849,7 @@ public: unsigned ExtraKindOrNumArgs; }; -} // end namespace clang +} // namespace clang namespace llvm { @@ -856,11 +857,11 @@ namespace llvm { /// DenseSets. template <> struct DenseMapInfo { - static inline clang::Selector getEmptyKey() { + static clang::Selector getEmptyKey() { return clang::Selector::getEmptyMarker(); } - static inline clang::Selector getTombstoneKey() { + static clang::Selector getTombstoneKey() { return clang::Selector::getTombstoneMarker(); } @@ -874,15 +875,13 @@ struct DenseMapInfo { template <> struct isPodLike { static const bool value = true; }; -template struct PointerLikeTypeTraits; - template<> struct PointerLikeTypeTraits { - static inline const void *getAsVoidPointer(clang::Selector P) { + static const void *getAsVoidPointer(clang::Selector P) { return P.getAsOpaquePtr(); } - static inline clang::Selector getFromVoidPointer(const void *P) { + static clang::Selector getFromVoidPointer(const void *P) { return clang::Selector(reinterpret_cast(P)); } @@ -893,11 +892,11 @@ struct PointerLikeTypeTraits { // are not guaranteed to be 8-byte aligned. template<> struct PointerLikeTypeTraits { - static inline void *getAsVoidPointer(clang::IdentifierInfo* P) { + static void *getAsVoidPointer(clang::IdentifierInfo* P) { return P; } - static inline clang::IdentifierInfo *getFromVoidPointer(void *P) { + static clang::IdentifierInfo *getFromVoidPointer(void *P) { return static_cast(P); } @@ -906,17 +905,17 @@ struct PointerLikeTypeTraits { template<> struct PointerLikeTypeTraits { - static inline const void *getAsVoidPointer(const clang::IdentifierInfo* P) { + static const void *getAsVoidPointer(const clang::IdentifierInfo* P) { return P; } - static inline const clang::IdentifierInfo *getFromVoidPointer(const void *P) { + static const clang::IdentifierInfo *getFromVoidPointer(const void *P) { return static_cast(P); } enum { NumLowBitsAvailable = 1 }; }; -} // end namespace llvm +} // namespace llvm #endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 0b2a665f05..6631721e35 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -1,4 +1,4 @@ -//===--- Module.h - Describe a module ---------------------------*- C++ -*-===// +//===- Module.h - Describe a module -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,12 +6,13 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the clang::Module class, which describes a module in the /// source code. -/// +// //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_BASIC_MODULE_H #define LLVM_CLANG_BASIC_MODULE_H @@ -19,6 +20,7 @@ #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SetVector.h" @@ -26,22 +28,28 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include +#include +#include +#include #include #include #include namespace llvm { - class raw_ostream; -} + +class raw_ostream; + +} // namespace llvm namespace clang { class LangOptions; class TargetInfo; -class IdentifierInfo; - + /// \brief Describes the name of a module. -typedef SmallVector, 2> ModuleId; +using ModuleId = SmallVector, 2>; /// The signature of a module, which is a hash of the AST content. struct ASTFileSignature : std::array { @@ -85,7 +93,7 @@ public: /// \brief The build directory of this module. This is the directory in /// which the module is notionally built, and relative to which its headers /// are found. - const DirectoryEntry *Directory; + const DirectoryEntry *Directory = nullptr; /// \brief The presumed file name for the module map defining this module. /// Only non-empty when building from preprocessed source. @@ -114,7 +122,7 @@ private: /// \brief The AST file if this is a top-level module which has a /// corresponding serialized AST file, or null otherwise. - const FileEntry *ASTFile; + const FileEntry *ASTFile = nullptr; /// \brief The top-level headers associated with this module. llvm::SmallSetVector TopHeaders; @@ -181,7 +189,7 @@ public: /// \brief An individual requirement: a feature name and a flag indicating /// the required state of that feature. - typedef std::pair Requirement; + using Requirement = std::pair; /// \brief The set of language features required to use this module. /// @@ -270,7 +278,7 @@ public: /// /// The pointer is the module being re-exported, while the bit will be true /// to indicate that this is a wildcard export. - typedef llvm::PointerIntPair ExportDecl; + using ExportDecl = llvm::PointerIntPair; /// \brief The set of export declarations. SmallVector Exports; @@ -302,9 +310,9 @@ public: /// \brief A library or framework to link against when an entity from this /// module is used. struct LinkLibrary { - LinkLibrary() : IsFramework(false) { } + LinkLibrary() = default; LinkLibrary(const std::string &Library, bool IsFramework) - : Library(Library), IsFramework(IsFramework) { } + : Library(Library), IsFramework(IsFramework) {} /// \brief The library to link against. /// @@ -313,7 +321,7 @@ public: std::string Library; /// \brief Whether this is a framework rather than a library. - bool IsFramework; + bool IsFramework = false; }; /// \brief The set of libraries or frameworks to link against when @@ -432,7 +440,6 @@ public: const Module *getTopLevelModule() const; /// \brief Retrieve the name of the top-level module. - /// StringRef getTopLevelModuleName() const { return getTopLevelModule()->Name; } @@ -525,8 +532,8 @@ public: unsigned getVisibilityID() const { return VisibilityID; } - typedef std::vector::iterator submodule_iterator; - typedef std::vector::const_iterator submodule_const_iterator; + using submodule_iterator = std::vector::iterator; + using submodule_const_iterator = std::vector::const_iterator; submodule_iterator submodule_begin() { return SubModules.begin(); } submodule_const_iterator submodule_begin() const {return SubModules.begin();} @@ -551,7 +558,6 @@ public: } /// \brief Print the module map for this module to the given stream. - /// void print(raw_ostream &OS, unsigned Indent = 0) const; /// \brief Dump the contents of this module to the given output stream. @@ -564,7 +570,7 @@ private: /// \brief A set of visible modules. class VisibleModuleSet { public: - VisibleModuleSet() : Generation(0) {} + VisibleModuleSet() = default; VisibleModuleSet(VisibleModuleSet &&O) : ImportLocs(std::move(O.ImportLocs)), Generation(O.Generation ? 1 : 0) { O.ImportLocs.clear(); @@ -599,13 +605,15 @@ public: /// \brief A callback to call when a module is made visible (directly or /// indirectly) by a call to \ref setVisible. - typedef llvm::function_ref VisibleCallback; + using VisibleCallback = llvm::function_ref; + /// \brief A callback to call when a module conflict is found. \p Path /// consists of a sequence of modules from the conflicting module to the one /// made visible, where each was exported by the next. - typedef llvm::function_ref Path, - Module *Conflict, StringRef Message)> - ConflictCallback; + using ConflictCallback = + llvm::function_ref Path, Module *Conflict, + StringRef Message)>; + /// \brief Make a specific module visible. void setVisible(Module *M, SourceLocation Loc, VisibleCallback Vis = [](Module *) {}, @@ -616,11 +624,11 @@ private: /// Import locations for each visible module. Indexed by the module's /// VisibilityID. std::vector ImportLocs; + /// Visibility generation, bumped every time the visibility state changes. - unsigned Generation; + unsigned Generation = 0; }; -} // end namespace clang - +} // namespace clang #endif // LLVM_CLANG_BASIC_MODULE_H diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 16bd5616a6..397ad2e77f 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -1,4 +1,4 @@ -//===--- SourceManager.h - Track and cache source files ---------*- C++ -*-===// +//===- SourceManager.h - Track and cache source files -----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,7 +6,7 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines the SourceManager interface. /// @@ -29,14 +29,13 @@ /// location in the source where the macro was originally defined, /// and the presumed location is where the line directive states that /// the line is 17, or any other line. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H #define LLVM_CLANG_BASIC_SOURCEMANAGER_H #include "clang/Basic/FileManager.h" -#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -49,10 +48,8 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/MemoryBuffer.h" -#include #include #include -#include #include #include #include @@ -69,7 +66,6 @@ class SourceManager; /// \brief Public enums and private classes that are part of the /// SourceManager implementation. -/// namespace SrcMgr { /// \brief Indicates whether a file or directory holds normal user code, @@ -100,6 +96,7 @@ namespace SrcMgr { enum CCFlags { /// \brief Whether the buffer is invalid. InvalidFlag = 0x01, + /// \brief Whether the buffer should not be freed on destruction. DoNotFreeFlag = 0x02 }; @@ -130,12 +127,12 @@ namespace SrcMgr { /// /// This is lazily computed. This is owned by the SourceManager /// BumpPointerAllocator object. - unsigned *SourceLineCache; + unsigned *SourceLineCache = nullptr; /// \brief The number of lines in this ContentCache. /// /// This is only valid if SourceLineCache is non-null. - unsigned NumLines; + unsigned NumLines = 0; /// \brief Indicates whether the buffer itself was provided to override /// the actual file contents. @@ -157,15 +154,14 @@ namespace SrcMgr { ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) : Buffer(nullptr, false), OrigEntry(Ent), ContentsEntry(contentEnt), - SourceLineCache(nullptr), NumLines(0), BufferOverridden(false), - IsSystemFile(false), IsTransient(false) {} + BufferOverridden(false), IsSystemFile(false), IsTransient(false) {} /// The copy ctor does not allow copies where source object has either /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory /// is not transferred, so this is a logical error. ContentCache(const ContentCache &RHS) - : Buffer(nullptr, false), SourceLineCache(nullptr), - BufferOverridden(false), IsSystemFile(false), IsTransient(false) { + : Buffer(nullptr, false), BufferOverridden(false), IsSystemFile(false), + IsTransient(false) { OrigEntry = RHS.OrigEntry; ContentsEntry = RHS.ContentsEntry; @@ -246,6 +242,10 @@ namespace SrcMgr { /// FileInfos contain a "ContentCache *", with the contents of the file. /// class FileInfo { + friend class clang::SourceManager; + friend class clang::ASTWriter; + friend class clang::ASTReader; + /// \brief The location of the \#include that brought in this file. /// /// This is an invalid SLOC for the main file (top of the \#include chain). @@ -264,10 +264,6 @@ namespace SrcMgr { llvm::PointerIntPair ContentAndKind; - friend class clang::SourceManager; - friend class clang::ASTWriter; - friend class clang::ASTReader; - public: /// \brief Return a FileInfo object. static FileInfo get(SourceLocation IL, const ContentCache *Con, @@ -448,7 +444,7 @@ namespace SrcMgr { } }; -} // end SrcMgr namespace. +} // namespace SrcMgr /// \brief External source of source location entries. class ExternalSLocEntrySource { @@ -546,7 +542,7 @@ public: /// \brief The stack used when building modules on demand, which is used /// to provide a link between the source managers of the different compiler /// instances. -typedef ArrayRef> ModuleBuildStack; +using ModuleBuildStack = ArrayRef>; /// \brief This class handles loading and caching of source files into memory. /// @@ -578,7 +574,7 @@ class SourceManager : public RefCountedBase { /// \brief True if the ContentCache for files that are overridden by other /// files, should report the original file name. Defaults to true. - bool OverridenFilesKeepOriginalName; + bool OverridenFilesKeepOriginalName = true; /// \brief True if non-system source files should be treated as volatile /// (likely to change while trying to use them). Defaults to false. @@ -587,12 +583,13 @@ class SourceManager : public RefCountedBase { /// \brief True if all files read during this compilation should be treated /// as transient (may not be present in later compilations using a module /// file created from this compilation). Defaults to false. - bool FilesAreTransient; + bool FilesAreTransient = false; struct OverriddenFilesInfoTy { /// \brief Files that have been overridden with the contents from another /// file. llvm::DenseMap OverriddenFiles; + /// \brief Files that were overridden with a memory buffer. llvm::DenseSet OverriddenFilesWithBuffer; }; @@ -647,7 +644,7 @@ class SourceManager : public RefCountedBase { llvm::BitVector SLocEntryLoaded; /// \brief An external source for source location entries. - ExternalSLocEntrySource *ExternalSLocEntries; + ExternalSLocEntrySource *ExternalSLocEntries = nullptr; /// \brief A one-entry cache to speed up getFileID. /// @@ -658,7 +655,7 @@ class SourceManager : public RefCountedBase { /// \brief Holds information for \#line directives. /// /// This is referenced by indices from SLocEntryTable. - LineTableInfo *LineTable; + LineTableInfo *LineTable = nullptr; /// \brief These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. @@ -674,7 +671,8 @@ class SourceManager : public RefCountedBase { FileID PreambleFileID; // Statistics for -print-stats. - mutable unsigned NumLinearScans, NumBinaryProbes; + mutable unsigned NumLinearScans = 0; + mutable unsigned NumBinaryProbes = 0; /// \brief Associates a FileID with its "included/expanded in" decomposed /// location. @@ -684,12 +682,12 @@ class SourceManager : public RefCountedBase { mutable llvm::DenseMap> IncludedLocMap; /// The key value into the IsBeforeInTUCache table. - typedef std::pair IsBeforeInTUCacheKey; + using IsBeforeInTUCacheKey = std::pair; /// The IsBeforeInTranslationUnitCache is a mapping from FileID pairs /// to cache results. - typedef llvm::DenseMap - InBeforeInTUCache; + using InBeforeInTUCache = + llvm::DenseMap; /// Cache results for the isBeforeInTranslationUnit method. mutable InBeforeInTUCache IBTUCache; @@ -706,7 +704,7 @@ class SourceManager : public RefCountedBase { /// \brief Lazily computed map of macro argument chunks to their expanded /// source location. - typedef std::map MacroArgsMap; + using MacroArgsMap = std::map; mutable llvm::DenseMap> MacroArgsCacheMap; @@ -1417,7 +1415,6 @@ public: //===--------------------------------------------------------------------===// /// \brief Return the uniqued ID for the specified filename. - /// unsigned getLineTableFilenameID(StringRef Str); /// \brief Add a line note to the line table for the FileID and offset @@ -1538,8 +1535,9 @@ public: } // Iterators over FileInfos. - typedef llvm::DenseMap - ::const_iterator fileinfo_iterator; + using fileinfo_iterator = + llvm::DenseMap::const_iterator; + fileinfo_iterator fileinfo_begin() const { return FileInfos.begin(); } fileinfo_iterator fileinfo_end() const { return FileInfos.end(); } bool hasFileInfo(const FileEntry *File) const { @@ -1547,7 +1545,6 @@ public: } /// \brief Print statistics to stderr. - /// void PrintStats() const; void dump() const; @@ -1638,6 +1635,9 @@ public: } private: + friend class ASTReader; + friend class ASTWriter; + llvm::MemoryBuffer *getFakeBufferForRecovery() const; const SrcMgr::ContentCache *getFakeContentCacheForRecovery() const; @@ -1729,8 +1729,6 @@ private: SourceLocation SpellLoc, SourceLocation ExpansionLoc, unsigned ExpansionLength) const; - friend class ASTReader; - friend class ASTWriter; }; /// \brief Comparison function object. @@ -1743,7 +1741,7 @@ class BeforeThanCompare { SourceManager &SM; public: - explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } + explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} bool operator()(SourceLocation LHS, SourceLocation RHS) const { return SM.isBeforeInTranslationUnit(LHS, RHS); @@ -1756,13 +1754,13 @@ class BeforeThanCompare { SourceManager &SM; public: - explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } + explicit BeforeThanCompare(SourceManager &SM) : SM(SM) {} bool operator()(SourceRange LHS, SourceRange RHS) const { return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin()); } }; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index 9403dea888..edd910e704 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -1,4 +1,4 @@ -//===--- SourceManagerInternals.h - SourceManager Internals -----*- C++ -*-===// +//===- SourceManagerInternals.h - SourceManager Internals -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file /// \brief Defines implementation details of the clang::SourceManager class. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H @@ -18,7 +18,11 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include #include +#include namespace clang { @@ -86,7 +90,8 @@ class LineTableInfo { /// \brief Map from FileIDs to a list of line entries (sorted by the offset /// at which they occur in the file). - std::map > LineEntries; + std::map> LineEntries; + public: void clear() { FilenameIDs.clear(); @@ -95,10 +100,12 @@ public: } unsigned getLineTableFilenameID(StringRef Str); + StringRef getFilename(unsigned ID) const { assert(ID < FilenamesByID.size() && "Invalid FilenameID"); return FilenamesByID[ID]->getKey(); } + unsigned getNumFilenames() const { return FilenamesByID.size(); } void AddLineNote(FileID FID, unsigned Offset, @@ -112,7 +119,8 @@ public: const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset); // Low-level access - typedef std::map >::iterator iterator; + using iterator = std::map>::iterator; + iterator begin() { return LineEntries.begin(); } iterator end() { return LineEntries.end(); } @@ -121,6 +129,6 @@ public: void AddEntry(FileID FID, const std::vector &Entries); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index fe7829ec50..2bed531ae3 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -1,4 +1,4 @@ -//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===// +//===- IdentifierTable.cpp - Hash table for identifier lookup -------------===// // // The LLVM Compiler Infrastructure // @@ -12,17 +12,24 @@ // //===----------------------------------------------------------------------===// -#include "clang/Basic/CharInfo.h" #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" -#include "llvm/ADT/DenseMap.h" +#include "clang/Basic/TokenKinds.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include #include +#include +#include using namespace clang; @@ -46,27 +53,27 @@ IdentifierInfo::IdentifierInfo() { RevertedTokenID = false; OutOfDate = false; IsModulesImport = false; - FETokenInfo = nullptr; - Entry = nullptr; } //===----------------------------------------------------------------------===// // IdentifierTable Implementation //===----------------------------------------------------------------------===// -IdentifierIterator::~IdentifierIterator() { } +IdentifierIterator::~IdentifierIterator() = default; -IdentifierInfoLookup::~IdentifierInfoLookup() {} +IdentifierInfoLookup::~IdentifierInfoLookup() = default; namespace { - /// \brief A simple identifier lookup iterator that represents an - /// empty sequence of identifiers. - class EmptyLookupIterator : public IdentifierIterator - { - public: - StringRef Next() override { return StringRef(); } - }; -} + +/// \brief A simple identifier lookup iterator that represents an +/// empty sequence of identifiers. +class EmptyLookupIterator : public IdentifierIterator +{ +public: + StringRef Next() override { return StringRef(); } +}; + +} // namespace IdentifierIterator *IdentifierInfoLookup::getIdentifiers() { return new EmptyLookupIterator(); @@ -76,11 +83,9 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts, IdentifierInfoLookup* externalLookup) : HashTable(8192), // Start with space for 8K identifiers. ExternalLookup(externalLookup) { - // Populate the identifier table with info about keywords for the current // language. AddKeywords(LangOpts); - // Add the '_experimental_modules_import' contextual keyword. get("import").setModulesImport(true); @@ -92,6 +97,7 @@ IdentifierTable::IdentifierTable(const LangOptions &LangOpts, // Constants for TokenKinds.def namespace { + enum { KEYC99 = 0x1, KEYCXX = 0x2, @@ -127,7 +133,8 @@ namespace { KS_Enabled, // Enabled KS_Future // Is a keyword in future standard }; -} + +} // namespace /// \brief Translates flags as specified in TokenKinds.def into keyword status /// in the given language standard. @@ -366,6 +373,7 @@ unsigned llvm::DenseMapInfo::getHashValue(clang::Selector S) { } namespace clang { + /// MultiKeywordSelector - One of these variable length records is kept for each /// selector containing more than one keyword. We use a folding set /// to unique aggregate names (keyword selectors in ObjC parlance). Access to @@ -375,6 +383,7 @@ class MultiKeywordSelector MultiKeywordSelector(unsigned nKeys) { ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys; } + public: // Constructor for keyword selectors. MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) { @@ -392,28 +401,34 @@ public: unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; } - typedef IdentifierInfo *const *keyword_iterator; + using keyword_iterator = IdentifierInfo *const *; + keyword_iterator keyword_begin() const { return reinterpret_cast(this+1); } + keyword_iterator keyword_end() const { return keyword_begin()+getNumArgs(); } + IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const { assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index"); return keyword_begin()[i]; } + static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, unsigned NumArgs) { ID.AddInteger(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) ID.AddPointer(ArgTys[i]); } + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, keyword_begin(), getNumArgs()); } }; -} // end namespace clang. + +} // namespace clang. unsigned Selector::getNumArgs() const { unsigned IIF = getIdentifierInfoFlag(); @@ -431,6 +446,7 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const { assert(argIndex == 0 && "illegal keyword index"); return getAsIdentifierInfo(); } + // We point to a MultiKeywordSelector. MultiKeywordSelector *SI = getMultiKeywordSelector(); return SI->getIdentifierInfoForSlot(argIndex); @@ -592,11 +608,13 @@ ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) { } namespace { - struct SelectorTableImpl { - llvm::FoldingSet Table; - llvm::BumpPtrAllocator Allocator; - }; -} // end anonymous namespace. + +struct SelectorTableImpl { + llvm::FoldingSet Table; + llvm::BumpPtrAllocator Allocator; +}; + +} // namespace static SelectorTableImpl &getSelectorTableImpl(void *P) { return *static_cast(P); diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index 621b1b23d7..7124184865 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -1,4 +1,4 @@ -//===--- Module.cpp - Describe a module -----------------------------------===// +//===- Module.cpp - Describe a module -------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -16,23 +16,33 @@ #include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include +#include +#include +#include using namespace clang; Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, bool IsExplicit, unsigned VisibilityID) - : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), Directory(), - Umbrella(), ASTFile(nullptr), VisibilityID(VisibilityID), - IsMissingRequirement(false), HasIncompatibleModuleFile(false), - IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), - IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), - IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false), + : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), + VisibilityID(VisibilityID), IsMissingRequirement(false), + HasIncompatibleModuleFile(false), IsAvailable(true), + IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit), + IsSystem(false), IsExternC(false), IsInferred(false), + InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false), ConfigMacrosExhaustive(false), NoUndeclaredIncludes(false), NameVisibility(Hidden) { if (Parent) { @@ -130,6 +140,7 @@ static StringRef getModuleNameFromComponent( const std::pair &IdComponent) { return IdComponent.first; } + static StringRef getModuleNameFromComponent(StringRef R) { return R; } template diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index 620f05c637..e664879639 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -1,4 +1,4 @@ -//===--- SourceManager.cpp - Track and cache source files -----------------===// +//===- SourceManager.cpp - Track and cache source files -------------------===// // // The LLVM Compiler Infrastructure // @@ -14,17 +14,33 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManagerInternals.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/Capacity.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" #include -#include +#include +#include +#include +#include +#include +#include +#include using namespace clang; using namespace SrcMgr; @@ -222,7 +238,6 @@ void LineTableInfo::AddLineNote(FileID FID, unsigned Offset, unsigned LineNo, IncludeOffset)); } - /// FindNearestLineEntry - Find the line entry nearest to FID that is before /// it. If there is no line entry before Offset in FID, return null. const LineEntry *LineTableInfo::FindNearestLineEntry(FileID FID, @@ -250,7 +265,6 @@ void LineTableInfo::AddEntry(FileID FID, } /// getLineTableFilenameID - Return the uniqued ID for the specified filename. -/// unsigned SourceManager::getLineTableFilenameID(StringRef Name) { return getLineTable().getLineTableFilenameID(Name); } @@ -298,10 +312,7 @@ LineTableInfo &SourceManager::getLineTable() { SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr, bool UserFilesAreVolatile) - : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), - UserFilesAreVolatile(UserFilesAreVolatile), FilesAreTransient(false), - ExternalSLocEntries(nullptr), LineTable(nullptr), NumLinearScans(0), - NumBinaryProbes(0) { + : Diag(Diag), FileMgr(FileMgr), UserFilesAreVolatile(UserFilesAreVolatile) { clearIDTables(); Diag.setSourceManager(this); } @@ -342,7 +353,7 @@ void SourceManager::clearIDTables() { // Use up FileID #0 as an invalid expansion. NextLocalOffset = 0; CurrentLoadedOffset = MaxLoadedOffset; - createExpansionLoc(SourceLocation(),SourceLocation(),SourceLocation(), 1); + createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1); } void SourceManager::initializeForReplay(const SourceManager &Old) { @@ -408,7 +419,6 @@ SourceManager::getOrCreateContentCache(const FileEntry *FileEnt, return Entry; } - /// Create a new ContentCache for the specified memory buffer. /// This does no caching. const ContentCache * @@ -716,7 +726,7 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const { // Find the FileID that contains this. "I" is an iterator that points to a // FileID whose offset is known to be larger than SLocOffset. unsigned NumProbes = 0; - while (1) { + while (true) { --I; if (I->getOffset() <= SLocOffset) { FileID Res = FileID::get(int(I - LocalSLocEntryTable.begin())); @@ -740,7 +750,7 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const { // SLocOffset. unsigned LessIndex = 0; NumProbes = 0; - while (1) { + while (true) { bool Invalid = false; unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex; unsigned MidOffset = getLocalSLocEntry(MiddleIndex, &Invalid).getOffset(); @@ -817,7 +827,7 @@ FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const { unsigned GreaterIndex = I; unsigned LessIndex = LoadedSLocEntryTable.size(); NumProbes = 0; - while (1) { + while (true) { ++NumProbes; unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex; const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex); @@ -935,7 +945,6 @@ SourceLocation SourceManager::getImmediateSpellingLoc(SourceLocation Loc) const{ return Loc.getLocWithOffset(LocInfo.second); } - /// getImmediateExpansionRange - Loc is required to be an expansion location. /// Return the start/end of the expansion information. std::pair @@ -1055,7 +1064,6 @@ bool SourceManager::isAtEndOfImmediateMacroExpansion(SourceLocation Loc, return true; } - //===----------------------------------------------------------------------===// // Queries about the code at a SourceLocation. //===----------------------------------------------------------------------===// @@ -1084,7 +1092,6 @@ const char *SourceManager::getCharacterData(SourceLocation SL, return Buffer->getBufferStart() + (CharDataInvalid? 0 : LocInfo.second); } - /// getColumnNumber - Return the column # for the specified file position. /// this is significantly cheaper to compute than the line number. unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, @@ -1189,7 +1196,7 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); unsigned Offs = 0; - while (1) { + while (true) { // Skip over the contents of the line. const unsigned char *NextBuf = (const unsigned char *)Buf; @@ -1419,7 +1426,6 @@ StringRef SourceManager::getBufferName(SourceLocation Loc, return getBuffer(getFileID(Loc), Invalid)->getBufferIdentifier(); } - /// getPresumedLoc - This method returns the "presumed" location of a /// SourceLocation specifies. A "presumed location" can be modified by \#line /// or GNU line marker directives. This provides a view on the data that a @@ -1767,7 +1773,7 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap &MacroArgsCache, MacroArgsCache.insert(std::make_pair(0, SourceLocation())); int ID = FID.ID; - while (1) { + while (true) { ++ID; // Stop if there are no more FileIDs to check. if (ID > 0) { @@ -1830,7 +1836,7 @@ void SourceManager::associateFileChunkWithMacroArgExp( FileID SpellFID; // Current FileID in the spelling range. unsigned SpellRelativeOffs; std::tie(SpellFID, SpellRelativeOffs) = getDecomposedLoc(SpellLoc); - while (1) { + while (true) { const SLocEntry &Entry = getSLocEntry(SpellFID); unsigned SpellFIDBeginOffs = Entry.getOffset(); unsigned SpellFIDSize = getFileIDSize(SpellFID); @@ -1857,7 +1863,6 @@ void SourceManager::associateFileChunkWithMacroArgExp( ++SpellFID.ID; SpellRelativeOffs = 0; } - } assert(SpellLoc.isFileID()); @@ -1937,8 +1942,8 @@ SourceManager::getDecomposedIncludedLoc(FileID FID) const { // Uses IncludedLocMap to retrieve/cache the decomposed loc. - typedef std::pair DecompTy; - typedef llvm::DenseMap MapTy; + using DecompTy = std::pair; + using MapTy = llvm::DenseMap; std::pair InsertOp = IncludedLocMap.insert(std::make_pair(FID, DecompTy())); DecompTy &DecompLoc = InsertOp.first->second; @@ -2085,7 +2090,7 @@ std::pair SourceManager::isInTheSameTranslationUnit( // of the other looking for a match. // We use a map from FileID to Offset to store the chain. Easier than writing // a custom set hash info that only depends on the first part of a pair. - typedef llvm::SmallDenseMap LocSet; + using LocSet = llvm::SmallDenseMap; LocSet LChain; do { LChain.insert(LOffs); @@ -2197,7 +2202,7 @@ LLVM_DUMP_METHOD void SourceManager::dump() const { } } -ExternalSLocEntrySource::~ExternalSLocEntrySource() { } +ExternalSLocEntrySource::~ExternalSLocEntrySource() = default; /// Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. -- cgit v1.2.3 From a1ccce852a6764d4ee9fee0a9fa57c65a3291a5f Mon Sep 17 00:00:00 2001 From: Richard Trieu Date: Sat, 4 Nov 2017 01:20:50 +0000 Subject: Update ODR hashing tests Add a mix of postive and negative tests to check that wrong Decls won't be flagged in the diagnostic. Split the check everything test and moved the pieces closer to where the related tests are. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@317394 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Modules/odr_hash.cpp | 843 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 723 insertions(+), 120 deletions(-) diff --git a/test/Modules/odr_hash.cpp b/test/Modules/odr_hash.cpp index 8ff95d2566..b672695dce 100644 --- a/test/Modules/odr_hash.cpp +++ b/test/Modules/odr_hash.cpp @@ -12,6 +12,10 @@ // RUN: echo "#define SECOND" >> %t/Inputs/second.h // RUN: cat %s >> %t/Inputs/second.h +// Test that each header can compile +// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/first.h +// RUN: %clang_cc1 -fsyntax-only -x c++ -std=c++1z %t/Inputs/second.h + // Build module map file // RUN: echo "module FirstModule {" >> %t/Inputs/module.map // RUN: echo " header \"first.h\"" >> %t/Inputs/module.map @@ -28,6 +32,13 @@ #include "second.h" #endif +// Used for testing +#if defined(FIRST) +#define ACCESS public: +#elif defined(SECOND) +#define ACCESS private: +#endif + namespace AccessSpecifiers { #if defined(FIRST) struct S1 { @@ -55,6 +66,32 @@ S2 s2; // expected-error@second.h:* {{'AccessSpecifiers::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found protected access specifier}} // expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} #endif + +#define DECLS \ +public: \ +private: \ +protected: + +#if defined(FIRST) || defined(SECOND) +struct Valid1 { + DECLS +}; +#else +Valid1 v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS + ACCESS +}; +#else +Invalid1 i1; +// expected-error@second.h:* {{'AccessSpecifiers::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} +#endif + +#undef DECLS } // namespace AccessSpecifiers namespace StaticAssert { @@ -113,7 +150,31 @@ S4 s4; // expected-error@second.h:* {{'StaticAssert::S4' has different definitions in different modules; first difference is definition in module 'SecondModule' found public access specifier}} // expected-note@first.h:* {{but in 'FirstModule' found static assert}} #endif -} + +#define DECLS \ + static_assert(4 == 4, "Message"); \ + static_assert(5 == 5); + +#if defined(FIRST) || defined(SECOND) +struct Valid1 { + DECLS +}; +#else +Valid1 v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS + ACCESS +}; +#else +Invalid1 i1; +// expected-error@second.h:* {{'StaticAssert::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} +#endif +#undef DECLS +} // namespace StaticAssert namespace Field { #if defined(FIRST) @@ -302,6 +363,38 @@ S13 s13; // expected-error@first.h:* {{'Field::S13::x' from module 'FirstModule' is not present in definition of 'Field::S13' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'x' does not match}} #endif + +#define DECLS \ + int a; \ + int b : 3; \ + unsigned c : 1 + 2; \ + s d; \ + double e = 1.0; \ + long f[5]; + +#if defined(FIRST) || defined(SECOND) +typedef short s; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Valid1 { + DECLS +}; +#else +Valid1 v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS + ACCESS +}; +#else +Invalid1 i1; +// expected-error@second.h:* {{'Field::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} +#endif +#undef DECLS } // namespace Field namespace Method { @@ -531,6 +624,40 @@ S15 s15; // expected-error@first.h:* {{'Method::S15::A' from module 'FirstModule' is not present in definition of 'Method::S15' in module 'SecondModule'}} // expected-note@second.h:* {{declaration of 'A' does not match}} #endif + +#define DECLS \ + void A(); \ + static void B(); \ + virtual void C(); \ + virtual void D() = 0; \ + inline void E(); \ + void F() const; \ + void G() volatile; \ + void H(int x); \ + void I(int x = 5 + 5); \ + void J(int); \ + void K(int x[2]); \ + int L(); + +#if defined(FIRST) || defined(SECOND) +struct Valid1 { + DECLS +}; +#else +Valid1* v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS + ACCESS +}; +#else +Invalid1* i1; +// expected-error@second.h:* {{'Method::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} +#endif +#undef DECLS } // namespace Method namespace Constructor { @@ -565,6 +692,31 @@ S2* s2; // expected-error@second.h:* {{'Constructor::S2' has different definitions in different modules; first difference is definition in module 'SecondModule' found constructor that has 2 parameters}} // expected-note@first.h:* {{but in 'FirstModule' found constructor that has 1 parameter}} #endif + +#define DECLS(CLASS) \ + CLASS(int); \ + CLASS(double); \ + CLASS(int, int); + +#if defined(FIRST) || defined(SECOND) +struct Valid1 { + DECLS(Valid1) +}; +#else +Valid1* v1; +#endif + +#if defined(FIRST) || defined(SECOND) +struct Invalid1 { + DECLS(Invalid1) + ACCESS +}; +#else +Invalid1* i1; +// expected-error@second.h:* {{'Constructor::Invalid1' has different definitions in different modules; first difference is definition in module 'SecondModule' found private access specifier}} +// expected-note@first.h:* {{but in 'FirstModule' found public access specifier}} +#endif +#undef DECLS } // namespace Constructor namespace Destructor { @@ -600,32 +752,44 @@ S2 s2; // expected-note@first.h:* {{but in 'FirstModule' found destructor is virtual}} #endif -} // namespace Destructor - -// Naive parsing of AST can lead to cycles in processing. Ensure -// self-references don't trigger an endless cycles of AST node processing. -namespace SelfReference { -#if defined(FIRST) -template