Index: include/clang/Basic/DiagnosticFrontendKinds.td =================================================================== --- include/clang/Basic/DiagnosticFrontendKinds.td +++ include/clang/Basic/DiagnosticFrontendKinds.td @@ -224,4 +224,11 @@ def warn_option_invalid_ocl_version : Warning< "OpenCL version %0 does not support the option '%1'">, InGroup; + +def remark_ssp_applied_reason + : Remark<"SSP applied to function due to %select{an unknown reason|a " + "call to alloca|a stack allocated buffer or struct containing a " + "buffer|the address of a local variable being taken|a function " + "attribute or use of -fstack-protector-all}0">, + InGroup; } Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -905,3 +905,7 @@ // A warning group for warnings about code that clang accepts when // compiling OpenCL C/C++ but which is not compatible with the SPIR spec. def SpirCompat : DiagGroup<"spir-compat">; + +// A remark group for remarks about why stack protection was applied to a +// function. +def SSPReason : DiagGroup<"ssp-reason">; Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -307,6 +307,9 @@ const llvm::OptimizationRemarkAnalysisAliasing &D); void OptimizationFailureHandler( const llvm::DiagnosticInfoOptimizationFailure &D); + + /// \brief Specialized handler for Stack Protector remark diagnostics. + void SSPRemarkHandler(const DiagnosticInfoSSP &D); }; void BackendConsumer::anchor() {} @@ -631,6 +634,15 @@ EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); } +void BackendConsumer::SSPRemarkHandler(const DiagnosticInfoSSP &D) { + StringRef Filename; + unsigned Line, Column; + bool BadDebugInfo = false; + FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, + Line, Column); + Diags.Report(Loc, diag::remark_ssp_applied_reason) << D.Reason(); +} + /// \brief This function is invoked when the backend needs /// to report something to the user. void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { @@ -688,6 +700,9 @@ case llvm::DK_Unsupported: UnsupportedDiagHandler(cast(DI)); return; + case llvm::DK_SSPReason: + SSPRemarkHandler(cast(DI)); + return; default: // Plugin IDs are not bound to any value as they are set dynamically. ComputeDiagRemarkID(Severity, backend_plugin, DiagID); Index: test/CodeGen/stack-protector-remarks.c =================================================================== --- test/CodeGen/stack-protector-remarks.c +++ test/CodeGen/stack-protector-remarks.c @@ -0,0 +1,60 @@ +// RUN: %clang_cc1 -emit-obj %s -Rssp-reason -stack-protector 2 -o /dev/null 2>&1 | FileCheck %s -check-prefix=CHECK1 +// CHECK1-NOT: no_ssp +// CHECK1: call to alloca +// CHECK1-NEXT: alloca_ssp() +// CHECK1: stack allocated buffer or struct +// CHECK1-NEXT: buffer_ssp() +// CHECK1: stack allocated buffer or struct +// CHECK1-NEXT: struct_ssp() +// CHECK1: address of a local variable +// CHECK1-NEXT: address_ssp() +// CHECK1: stack allocated buffer or struct +// CHECK1-NEXT: multiple_ssp +// CHECK1: stack allocated buffer or struct +// CHECK1: address of a local variable +// CHECK1: call to alloca + +// RUN: %clang_cc1 -emit-obj %s -Rssp-reason -stack-protector 3 -o /dev/null 2>&1 | FileCheck %s -check-prefix=CHECK2 +// CHECK2: function attribute or use of -fstack-protector-all +// CHECK2-NEXT: no_ssp +// CHECK2: function attribute or use of -fstack-protector-all +// CHECK2-NEXT: alloca_ssp() +// CHECK2: function attribute or use of -fstack-protector-all +// CHECK2-NEXT: buffer_ssp() +// CHECK2: function attribute or use of -fstack-protector-all +// CHECK2-NEXT: struct_ssp() +// CHECK2: function attribute or use of -fstack-protector-all +// CHECK2-NEXT: address_ssp() +// CHECK2: function attribute or use of -fstack-protector-all +// CHECK2-NEXT: multiple_ssp + +void no_ssp() { +} + +void alloca_ssp() { + __builtin_alloca(2); +} + +void buffer_ssp() { + int x[64]; +} + +struct X { + int x[64]; +}; +void struct_ssp() { + struct X x; +} + +void address_ssp() { + int x = 32; + int * y = &x; +} + +void multiple_ssp() { + struct X x; + int y[64]; + __builtin_alloca(2); + int a = 32; + int * b = &a; +}