Index: clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h =================================================================== --- clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -67,15 +67,6 @@ /// Returns a reference to the cache for the translation unit: virtual HeaderIncludesCache &headerIncludesCache() const = 0; - - /// Returns the text indicating that the user needs to provide input there: - virtual std::string - getUserFillPlaceHolder(StringRef HintTextToUser = "placeholder") const { - std::string s = std::string("<# "); - s += HintTextToUser; - s += " #>"; - return s; - } }; // This function invokes the analysis and allows the caller to react to it Index: clang/lib/Analysis/UnsafeBufferUsage.cpp =================================================================== --- clang/lib/Analysis/UnsafeBufferUsage.cpp +++ clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1117,6 +1117,14 @@ return EOL; } +// Returns the text indicating that the user needs to provide input there: +std::string getUserFillPlaceHolder(StringRef HintTextToUser = "placeholder") { + std::string s = std::string("<# "); + s += HintTextToUser; + s += " #>"; + return s; +} + // Return the text representation of the given `APInt Val`: static std::string getAPIntText(APInt Val) { SmallVector Txt; @@ -1507,15 +1515,28 @@ } // Returns the text representation of clang::unsafe_buffer_usage attribute. -// (FIXME:) The text could vary depending on whether macros over the attribute -// are defined. -static std::string getUnsafeBufferUsageAttributeText() { - std::stringstream SS; - - SS << "#if __has_cpp_attribute(clang::unsafe_buffer_usage)" - << getEndOfLine().data() << "[[clang::unsafe_buffer_usage]]" - << getEndOfLine().data() << "#endif" << getEndOfLine().data(); - return SS.str(); +// `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace +// characters. +static std::string +getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc, Sema &S, + StringRef WSSuffix = "") { + Preprocessor &PP = S.getPreprocessor(); + TokenValue ClangUnsafeBufferUsageTokens[] = { + tok::l_square, + tok::l_square, + PP.getIdentifierInfo("clang"), + tok::coloncolon, + PP.getIdentifierInfo("unsafe_buffer_usage"), + tok::r_square, + tok::r_square}; + + StringRef MacroName; + + // The returned macro (it returns) is guaranteed not to be function-like: + MacroName = PP.getLastMacroWithSpelling(Loc, ClangUnsafeBufferUsageTokens); + if (MacroName.empty()) + MacroName = "[[clang::unsafe_buffer_usage]]"; + return MacroName.str() + WSSuffix.str(); } // Returns the name of `FD` including qualifiers if `FD` is declared with qualifiers. @@ -1620,13 +1641,13 @@ // A lambda that creates the text representation of a function definition with // the original signature: const auto OldOverloadDefCreator = - [&SM, &Handler](const FunctionDecl *FD, unsigned ParmIdx, + [&SM, &S](const FunctionDecl *FD, unsigned ParmIdx, StringRef NewTypeText) -> std::string { std::stringstream SS; SS << getEndOfLine().data(); // Appending: attr-name ret-type func-name "(" param-list ")" "{" - SS << getUnsafeBufferUsageAttributeText() + SS << getUnsafeBufferUsageAttributeTextAt(FD->getBeginLoc(), S, " ") << std::string(SM.getCharacterData(FD->getBeginLoc()), SM.getCharacterData(FD->getBody()->getBeginLoc())) << "{"; @@ -1645,7 +1666,7 @@ if (i == ParmIdx) // This is our spanified paramter! SS << NewTypeText.data() << "(" << Parm->getName().str() << ", " - << Handler.getUserFillPlaceHolder("size") << ")"; + << getUserFillPlaceHolder("size") << ")"; else SS << Parm->getName().str(); if (i != NumParms - 1) @@ -1673,7 +1694,8 @@ // Adds the unsafe-buffer attribute (if not already there) to `FReDecl`: if (!FReDecl->hasAttr()) { FixIts.emplace_back(FixItHint::CreateInsertion( - FReDecl->getBeginLoc(), getUnsafeBufferUsageAttributeText())); + FReDecl->getBeginLoc(), + getUnsafeBufferUsageAttributeTextAt(FReDecl->getBeginLoc(), S, " "))); } // Inserts a declaration with the new signature to the end of `FReDecl`: FixIts.emplace_back(FixItHint::CreateInsertion( @@ -1735,7 +1757,7 @@ (void)DS; // FIXME: handle cases where DS has multiple declarations - return fixVarDeclWithSpan(VD, Ctx, Handler.getUserFillPlaceHolder()); + return fixVarDeclWithSpan(VD, Ctx, getUserFillPlaceHolder()); } // TODO: we should be consistent to use `std::nullopt` to represent no-fix due Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-attributes-spelling.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-attributes-spelling.cpp @@ -0,0 +1,69 @@ +// RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -DCMD_UNSAFE_ATTR=[[clang::unsafe_buffer_usage]] %s 2>&1 | FileCheck %s + + +// no need to check fix-its for definition in this test ... +void foo(int *p) { + int tmp = p[5]; +} + +// Will use the macro defined from the command line: +void foo(int *); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"CMD_UNSAFE_ATTR " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span)" + + +#undef CMD_UNSAFE_ATTR +void foo(int *); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span)" + + +#define UNSAFE_ATTR [[clang::unsafe_buffer_usage]] + +void foo(int *); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span)" + +#undef UNSAFE_ATTR + +#if __has_cpp_attribute(clang::unsafe_buffer_usage) +#define UNSAFE_ATTR [[clang::unsafe_buffer_usage]] +#endif + +void foo(int *); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span)" + +#undef UNSAFE_ATTR + +#if __has_cpp_attribute(clang::unsafe_buffer_usage) +// we don't know how to use this macro +#define UNSAFE_ATTR(x) [[clang::unsafe_buffer_usage]] +#endif + +void foo(int *); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:16-[[@LINE-2]]:16}:";\nvoid foo(std::span)" + +#undef UNSAFE_ATTR + +#define UNSAFE_ATTR_1 [[clang::unsafe_buffer_usage]] +#define UNSAFE_ATTR_2 [[clang::unsafe_buffer_usage]] +#define UNSAFE_ATTR_3 [[clang::unsafe_buffer_usage]] + +// Should use the last defined macro (i.e., UNSAFE_ATTR_3) for +// `[[clang::unsafe_buffer_usage]]` +void foo(int *p); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR_3 " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:17-[[@LINE-2]]:17}:";\nvoid foo(std::span p)" + + +#define WRONG_ATTR_1 [clang::unsafe_buffer_usage]] +#define WRONG_ATTR_2 [[clang::unsafe_buffer_usage] +#define WRONG_ATTR_3 [[clang::unsafe_buffer_usag]] + +// The last defined macro for +// `[[clang::unsafe_buffer_usage]]` is still UNSAFE_ATTR_3 +void foo(int *p); +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"UNSAFE_ATTR_3 " +// CHECK: fix-it:{{.*}}:{[[@LINE-2]]:17-[[@LINE-2]]:17}:";\nvoid foo(std::span p)" Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-include-header/warn-unsafe-buffer-usage-fixits-header-exists.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-include-header/warn-unsafe-buffer-usage-fixits-header-exists.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-include-header/warn-unsafe-buffer-usage-fixits-header-exists.cpp @@ -10,4 +10,4 @@ int tmp; tmp = p[5]; } -// CHECK: fix-it:"{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid unsafe_code(int *p) {return unsafe_code(std::span(p, <# size #>));}\n" +// CHECK: fix-it:"{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void unsafe_code(int *p) {return unsafe_code(std::span(p, <# size #>));}\n" Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-include-header/warn-unsafe-buffer-usage-fixits-parm-in-header.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-include-header/warn-unsafe-buffer-usage-fixits-parm-in-header.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-include-header/warn-unsafe-buffer-usage-fixits-parm-in-header.cpp @@ -7,7 +7,7 @@ #include "warn-unsafe-buffer-usage-fixits-parm-in-header.h" // CHECK-DAG: fix-it:"{{.*}}warn-unsafe-buffer-usage-fixits-parm-in-header.h":{1:1-1:1}:"#include \n" -// CHECK-DAG: fix-it:"{{.*}}warn-unsafe-buffer-usage-fixits-parm-in-header.h":{3:1-3:1}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" +// CHECK-DAG: fix-it:"{{.*}}warn-unsafe-buffer-usage-fixits-parm-in-header.h":{3:1-3:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK-DAG: fix-it:"{{.*}}warn-unsafe-buffer-usage-fixits-parm-in-header.h":{3:25-3:25}:";\nvoid unsafe_code(std::span p)" // CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-3]]:1-[[@LINE-3]]:1}:"#include \n" @@ -16,4 +16,4 @@ int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid unsafe_code(int *p) {return unsafe_code(std::span(p, <# size #>));}\n" +// CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void unsafe_code(int *p) {return unsafe_code(std::span(p, <# size #>));}\n" Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp @@ -46,11 +46,11 @@ int tmp; tmp = p[5]; } - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid foo(int *p) {return foo(std::span(p, <# size #>));}\n" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void foo(int *p) {return foo(std::span(p, <# size #>));}\n" // Similarly, `NS::bar` is distinct from `bar`: void bar(int *p); - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:3}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:19}:";\nvoid bar(std::span p)" } // end of namespace NS @@ -60,7 +60,7 @@ int tmp; tmp = p[5]; } -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid NS::bar(int *p) {return NS::bar(std::span(p, <# size #>));}\n" +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS::bar(int *p) {return NS::bar(std::span(p, <# size #>));}\n" namespace NESTED { void alpha(int); @@ -74,7 +74,7 @@ int tmp; tmp = p[5]; } - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:6}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid alpha(int *p) {return alpha(std::span(p, <# size #>));}\n" + // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:6}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void alpha(int *p) {return alpha(std::span(p, <# size #>));}\n" } } Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp @@ -2,15 +2,15 @@ namespace NS1 { void foo(int *); - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-2]]:18-[[@LINE-2]]:18}:";\nvoid foo(std::span)" namespace NS2 { void foo(int *); - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-2]]:20-[[@LINE-2]]:20}:";\nvoid foo(std::span)" namespace NS3 { void foo(int *); - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:7-[[@LINE-1]]:7}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:7-[[@LINE-1]]:7}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK-DAG: fix-it:"{{.*}}:{[[@LINE-2]]:22-[[@LINE-2]]:22}:";\nvoid foo(std::span)" } } @@ -23,21 +23,21 @@ int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid NS1::foo(int *p) {return NS1::foo(std::span(p, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS1::foo(int *p) {return NS1::foo(std::span(p, <# size #>));}\n" void NS1::NS2::foo(int *p) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:20-[[@LINE-1]]:26}:"std::span p" int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid NS1::NS2::foo(int *p) {return NS1::NS2::foo(std::span(p, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS1::NS2::foo(int *p) {return NS1::NS2::foo(std::span(p, <# size #>));}\n" void NS1::NS2::NS3::foo(int *p) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:31}:"std::span p" int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid NS1::NS2::NS3::foo(int *p) {return NS1::NS2::NS3::foo(std::span(p, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void NS1::NS2::NS3::foo(int *p) {return NS1::NS2::NS3::foo(std::span(p, <# size #>));}\n" void f(NS1::MyType * x) { @@ -45,4 +45,4 @@ NS1::MyType tmp; tmp = x[5]; } -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid f(NS1::MyType * x) {return f(std::span(x, <# size #>));}\n" +// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void f(NS1::MyType * x) {return f(std::span(x, <# size #>));}\n" Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp @@ -11,13 +11,13 @@ void f(); void simple(int *p); -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:20-[[@LINE-2]]:20}:";\nvoid simple(std::span p)" #else void simple(int *); -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} " // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:19-[[@LINE-2]]:19}:";\nvoid simple(std::span)" void simple(int *p) { @@ -25,7 +25,7 @@ int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid simple(int *p) {return simple(std::span(p, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void simple(int *p) {return simple(std::span(p, <# size #>));}\n" void twoParms(int *p, int * q) { @@ -34,21 +34,21 @@ int tmp; tmp = p[5] + q[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid twoParms(int *p, int * q) {return twoParms(std::span(p, <# size #>), q);}\n" -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:2-[[@LINE-2]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid twoParms(int *p, int * q) {return twoParms(p, std::span(q, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void twoParms(int *p, int * q) {return twoParms(std::span(p, <# size #>), q);}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:2-[[@LINE-2]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void twoParms(int *p, int * q) {return twoParms(p, std::span(q, <# size #>));}\n" void decayedArrayParm(int arr[]) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:23-[[@LINE-1]]:32}:"std::span arr" int tmp; tmp = arr[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid decayedArrayParm(int arr[]) {return decayedArrayParm(std::span(arr, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decayedArrayParm(int arr[]) {return decayedArrayParm(std::span(arr, <# size #>));}\n" void ptrToConst(const int * x) { // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:17-[[@LINE-1]]:30}:"std::span x" int tmp = x[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid ptrToConst(const int * x) {return ptrToConst(std::span(x, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void ptrToConst(const int * x) {return ptrToConst(std::span(x, <# size #>));}\n" #endif Index: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp =================================================================== --- clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp +++ clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp @@ -8,7 +8,7 @@ // FIXME: the fix-it above is incorrect int tmp = x[5]; // expected-note{{used in buffer access here}} } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid const_ptr(int * const x) {return const_ptr(std::span(x, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void const_ptr(int * const x) {return const_ptr(std::span(x, <# size #>));}\n" // FIXME: the fix-it above is incorrect void const_ptr_to_const(const int * const x) {// expected-warning{{'x' is an unsafe pointer used for buffer access}} expected-note{{change type of 'x' to 'std::span' to preserve bounds information}} @@ -16,7 +16,7 @@ // FIXME: the fix-it above is incorrect int tmp = x[5]; // expected-note{{used in buffer access here}} } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n#if __has_cpp_attribute(clang::unsafe_buffer_usage)\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\n#endif\nvoid const_ptr_to_const(const int * const x) {return const_ptr_to_const(std::span(x, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void const_ptr_to_const(const int * const x) {return const_ptr_to_const(std::span(x, <# size #>));}\n" // FIXME: the fix-it above is incorrect // We do not fix parameters participating unsafe operations for the