Author: ziqingluo-90 Date: 2023-07-15T16:11:37-07:00 New Revision: a07a6f6c74a03405eccdcd3832acb2187d8b9c21
URL: https://github.com/llvm/llvm-project/commit/a07a6f6c74a03405eccdcd3832acb2187d8b9c21 DIFF: https://github.com/llvm/llvm-project/commit/a07a6f6c74a03405eccdcd3832acb2187d8b9c21.diff LOG: Re-land "5b012bf5ab5fcb840fe7f6c8664b8981ce6f24f3" Removed dependency on `clangSema` from UnsafeBufferAnalysis. Added: clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-attributes-spelling.cpp Modified: clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h clang/lib/Analysis/UnsafeBufferUsage.cpp clang/lib/Sema/AnalysisBasedWarnings.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h index 617bc7c77c5653..6766ba8ec27777 100644 --- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h +++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h @@ -46,14 +46,9 @@ class UnsafeBufferUsageHandler { /// Returns a reference to the `Preprocessor`: virtual bool isSafeBufferOptOut(const SourceLocation &Loc) 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; - } + getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc, + StringRef WSSuffix = "") const = 0; }; // This function invokes the analysis and allows the caller to react to it diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp index d8caa683c1e5e1..c8c1452a8f5543 100644 --- a/clang/lib/Analysis/UnsafeBufferUsage.cpp +++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp @@ -1290,6 +1290,14 @@ static StringRef getEndOfLine() { 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<char> Txt; @@ -1755,14 +1763,6 @@ static bool hasConflictingOverload(const FunctionDecl *FD) { return !FD->getDeclContext()->lookup(FD->getDeclName()).isSingleResult(); } -// Returns the text representation of clang::unsafe_buffer_usage attribute. -static std::string getUnsafeBufferUsageAttributeText() { - static const char *const RawAttr = "[[clang::unsafe_buffer_usage]]"; - std::stringstream SS; - SS << RawAttr << getEndOfLine().str(); - return SS.str(); -} - // For a `FunDecl`, one of whose `ParmVarDecl`s is being changed to have a new // type, this function produces fix-its to make the change self-contained. Let // 'F' be the entity defined by the original `FunDecl` and "NewF" be the entity @@ -1809,7 +1809,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText, // FIXME: need to make this conflict checking better: if (hasConflictingOverload(FD)) return std::nullopt; - + const SourceManager &SM = Ctx.getSourceManager(); const LangOptions &LangOpts = Ctx.getLangOpts(); // FIXME Respect indentation of the original code. @@ -1859,7 +1859,7 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText, // A lambda that creates the text representation of a function definition with // the original signature: const auto OldOverloadDefCreator = - [&Handler, &SM, + [&SM, &Handler, &LangOpts](const FunctionDecl *FD, unsigned ParmIdx, StringRef NewTypeText) -> std::optional<std::string> { std::stringstream SS; @@ -1869,7 +1869,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText, if (auto FDPrefix = getRangeText( SourceRange(FD->getBeginLoc(), FD->getBody()->getBeginLoc()), SM, LangOpts)) - SS << getUnsafeBufferUsageAttributeText() << FDPrefix->str() << "{"; + SS << Handler.getUnsafeBufferUsageAttributeTextAt(FD->getBeginLoc(), " ") + << FDPrefix->str() << "{"; else return std::nullopt; // Append: "return" func-name "(" @@ -1889,8 +1890,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText, "A parameter of a function definition has no name"); if (i == ParmIdx) // This is our spanified paramter! - SS << NewTypeText.str() << "(" << Parm->getIdentifier()->getName().str() - << ", " << Handler.getUserFillPlaceHolder("size") << ")"; + SS << NewTypeText.str() << "(" << Parm->getIdentifier()->getName().str() << ", " + << getUserFillPlaceHolder("size") << ")"; else SS << Parm->getIdentifier()->getName().str(); if (i != NumParms - 1) @@ -1921,7 +1922,8 @@ createOverloadsForFixedParams(unsigned ParmIdx, StringRef NewTyText, // Adds the unsafe-buffer attribute (if not already there) to `FReDecl`: if (!FReDecl->hasAttr<UnsafeBufferUsageAttr>()) { FixIts.emplace_back(FixItHint::CreateInsertion( - FReDecl->getBeginLoc(), getUnsafeBufferUsageAttributeText())); + FReDecl->getBeginLoc(), Handler.getUnsafeBufferUsageAttributeTextAt( + FReDecl->getBeginLoc(), " "))); } // Inserts a declaration with the new signature to the end of `FReDecl`: if (auto NewOverloadDecl = @@ -2013,7 +2015,7 @@ static FixItList fixVariableWithSpan(const VarDecl *VD, (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 diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp index de0feaa125f25c..43b13e0ec4d24e 100644 --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -2281,6 +2281,31 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler { bool isSafeBufferOptOut(const SourceLocation &Loc) const override { return S.PP.isSafeBufferOptOut(S.getSourceManager(), Loc); } + + // Returns the text representation of clang::unsafe_buffer_usage attribute. + // `WSSuffix` holds customized "white-space"s, e.g., newline or whilespace + // characters. + std::string + getUnsafeBufferUsageAttributeTextAt(SourceLocation Loc, + StringRef WSSuffix = "") const override { + 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(); + } }; } // namespace diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-attributes-spelling.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-attributes-spelling.cpp new file mode 100644 index 00000000000000..1b2f8bc9fa1b81 --- /dev/null +++ b/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 -fsafe-buffer-usage-suggestions -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<int>)" + + +#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<int>)" + + +#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<int>)" + +#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<int>)" + +#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<int>)" + +#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<int> 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<int> p)" diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp index 3bc3f4e333499f..e63ccfb77dd1ec 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-overload.cpp @@ -46,11 +46,11 @@ namespace NS { int tmp; tmp = p[5]; } - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid foo(int *p) {return foo(std::span<int>(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<int>(p, <# size #>));}\n" // Similarly, `NS::bar` is distinct from `bar`: void bar(int *p); - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:3}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\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<int> p)" } // end of namespace NS @@ -60,7 +60,7 @@ void NS::bar(int *p) { int tmp; tmp = p[5]; } -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS::bar(int *p) {return NS::bar(std::span<int>(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<int>(p, <# size #>));}\n" namespace NESTED { void alpha(int); @@ -74,7 +74,7 @@ namespace NESTED { int tmp; tmp = p[5]; } - // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:6-[[@LINE-1]]:6}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid alpha(int *p) {return alpha(std::span<int>(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<int>(p, <# size #>));}\n" } } diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp index 5b68fc531d3a6c..f07264915e5620 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span-qualified-names.cpp +++ b/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}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\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<int>)" namespace NS2 { void foo(int *); - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:5-[[@LINE-1]]:5}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\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<int>)" namespace NS3 { void foo(int *); - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:7-[[@LINE-1]]:7}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\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<int>)" } } @@ -23,21 +23,21 @@ void NS1::foo(int *p) { int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS1::foo(int *p) {return NS1::foo(std::span<int>(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<int>(p, <# size #>));}\n" void NS1::NS2::foo(int *p) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:20-[[@LINE-1]]:26}:"std::span<int> p" int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS1::NS2::foo(int *p) {return NS1::NS2::foo(std::span<int>(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<int>(p, <# size #>));}\n" void NS1::NS2::NS3::foo(int *p) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:31}:"std::span<int> p" int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid NS1::NS2::NS3::foo(int *p) {return NS1::NS2::NS3::foo(std::span<int>(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<int>(p, <# size #>));}\n" void f(NS1::MyType * x) { @@ -45,4 +45,4 @@ void f(NS1::MyType * x) { NS1::MyType tmp; tmp = x[5]; } -// CHECK: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid f(NS1::MyType * x) {return f(std::span<NS1::MyType>(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<NS1::MyType>(x, <# size #>));}\n" diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp index bb9deecaefec48..cef6afd5933b3c 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-span.cpp @@ -6,13 +6,13 @@ #define INCLUDE_ME void simple(int *p); -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\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<int> p)" #else void simple(int *); -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\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<int>)" void simple(int *p) { @@ -20,7 +20,7 @@ void simple(int *p) { int tmp; tmp = p[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid simple(int *p) {return simple(std::span<int>(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<int>(p, <# size #>));}\n" void twoParms(int *p, int * q) { @@ -29,14 +29,14 @@ void twoParms(int *p, int * q) { int tmp; tmp = p[5] + q[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid twoParms(int *p, int * q) {return twoParms(std::span<int>(p, <# size #>), q);}\n" -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:2-[[@LINE-2]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid twoParms(int *p, int * q) {return twoParms(p, std::span<int>(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<int>(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<int>(q, <# size #>));}\n" void ptrToConst(const int * x) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:17-[[@LINE-1]]:30}:"std::span<int const> x" int tmp = x[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid ptrToConst(const int * x) {return ptrToConst(std::span<int const>(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<int const>(x, <# size #>));}\n" // The followings test cases where multiple FileIDs maybe involved // when the analyzer loads characters from source files. @@ -50,7 +50,7 @@ void FUN_NAME(macro_defined_name)(int * x) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:35-[[@LINE-1]]:42}:"std::span<int> x" int tmp = x[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid FUN_NAME(macro_defined_name)(int * x) {return FUN_NAME(macro_defined_name)(std::span<int>(x, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void FUN_NAME(macro_defined_name)(int * x) {return FUN_NAME(macro_defined_name)(std::span<int>(x, <# size #>));}\n" // The followings test various type specifiers @@ -59,13 +59,13 @@ namespace { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:24-[[@LINE-1]]:49}:"std::span<unsigned long long int> p" auto tmp = p[5]; } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid simpleSpecifier(unsigned long long int *p) {return simpleSpecifier(std::span<unsigned long long int>(p, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void simpleSpecifier(unsigned long long int *p) {return simpleSpecifier(std::span<unsigned long long int>(p, <# size #>));}\n" void attrParm([[maybe_unused]] int * p) { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:34-[[@LINE-1]]:41}:"std::span<int> p" int tmp = p[5]; } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid attrParm({{\[}}{{\[}}maybe_unused{{\]}}{{\]}} int * p) {return attrParm(std::span<int>(p, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void attrParm({{\[}}{{\[}}maybe_unused{{\]}}{{\]}} int * p) {return attrParm(std::span<int>(p, <# size #>));}\n" using T = unsigned long long int; @@ -73,7 +73,7 @@ namespace { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:31-[[@LINE-1]]:36}:"std::span<T> p" int tmp = p[5]; } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid usingTypenameSpecifier(T * p) {return usingTypenameSpecifier(std::span<T>(p, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void usingTypenameSpecifier(T * p) {return usingTypenameSpecifier(std::span<T>(p, <# size #>));}\n" typedef unsigned long long int T2; @@ -81,7 +81,7 @@ namespace { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:31}:"std::span<T2> p" int tmp = p[5]; } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid typedefSpecifier(T2 * p) {return typedefSpecifier(std::span<T2>(p, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void typedefSpecifier(T2 * p) {return typedefSpecifier(std::span<T2>(p, <# size #>));}\n" class SomeClass { } C; @@ -90,7 +90,7 @@ namespace { // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:27-[[@LINE-1]]:52}:"std::span<class SomeClass const> p" if (++p) {} } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid classTypeSpecifier(const class SomeClass * p) {return classTypeSpecifier(std::span<class SomeClass const>(p, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void classTypeSpecifier(const class SomeClass * p) {return classTypeSpecifier(std::span<class SomeClass const>(p, <# size #>));}\n" struct { // anon @@ -113,9 +113,9 @@ namespace { if (++r) {} if (++rr) {} } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid decltypeSpecifier(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n{{.*}}decltype(NAMED_S) ** rr) {return decltypeSpecifier(std::span<decltype(C)>(p, <# size #>), q, r, rr);}\n - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:4-[[@LINE-2]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid decltypeSpecifier(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n{{.*}}decltype(NAMED_S) ** rr) {return decltypeSpecifier(p, q, std::span<decltype(NAMED_S)>(r, <# size #>), rr);}\n" - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-3]]:4-[[@LINE-3]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid decltypeSpecifier(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n{{.*}}decltype(NAMED_S) ** rr) {return decltypeSpecifier(p, q, r, std::span<decltype(NAMED_S) *>(rr, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decltypeSpecifier(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n{{.*}}decltype(NAMED_S) ** rr) {return decltypeSpecifier(std::span<decltype(C)>(p, <# size #>), q, r, rr);}\n + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:4-[[@LINE-2]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decltypeSpecifier(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n{{.*}}decltype(NAMED_S) ** rr) {return decltypeSpecifier(p, q, std::span<decltype(NAMED_S)>(r, <# size #>), rr);}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-3]]:4-[[@LINE-3]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decltypeSpecifier(decltype(C) * p, decltype(ANON_S) * q, decltype(NAMED_S) * r,\n{{.*}}decltype(NAMED_S) ** rr) {return decltypeSpecifier(p, q, r, std::span<decltype(NAMED_S) *>(rr, <# size #>));}\n" #define MACRO_TYPE(T) long T @@ -125,8 +125,8 @@ namespace { int tmp = p[5]; tmp = q[5]; } - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid macroType(unsigned MACRO_TYPE(int) * p, unsigned MACRO_TYPE(long) * q) {return macroType(std::span<unsigned MACRO_TYPE(int)>(p, <# size #>), q);}\n" - // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:4-[[@LINE-2]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid macroType(unsigned MACRO_TYPE(int) * p, unsigned MACRO_TYPE(long) * q) {return macroType(p, std::span<unsigned MACRO_TYPE(long)>(q, <# size #>));}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:4-[[@LINE-1]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void macroType(unsigned MACRO_TYPE(int) * p, unsigned MACRO_TYPE(long) * q) {return macroType(std::span<unsigned MACRO_TYPE(int)>(p, <# size #>), q);}\n" + // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-2]]:4-[[@LINE-2]]:4}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void macroType(unsigned MACRO_TYPE(int) * p, unsigned MACRO_TYPE(long) * q) {return macroType(p, std::span<unsigned MACRO_TYPE(long)>(q, <# size #>));}\n" } // The followings test various declarators: @@ -135,7 +135,7 @@ void decayedArray(int a[]) { int tmp; tmp = a[5]; } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid decayedArray(int a[]) {return decayedArray(std::span<int>(a, <# size #>));}\n" +// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void decayedArray(int a[]) {return decayedArray(std::span<int>(a, <# size #>));}\n" void decayedArrayOfArray(int a[10][10]) { // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]] diff --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp index bc918a7b53e9cf..f5be80b518ad32 100644 --- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp +++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-fixits-parm-unsupported.cpp @@ -5,13 +5,13 @@ void const_ptr(int * const x) { // expected-warning{{'x' is an unsafe pointer us // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:16-[[@LINE-1]]:29}:"std::span<int> const x" int tmp = x[5]; // expected-note{{used in buffer access here}} } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid const_ptr(int * const x) {return const_ptr(std::span<int>(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<int>(x, <# size #>));}\n" 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}} // CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:25-[[@LINE-1]]:44}:"std::span<int const> const x" int tmp = x[5]; // expected-note{{used in buffer access here}} } -// CHECK-DAG: fix-it:{{.*}}:{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid const_ptr_to_const(const int * const x) {return const_ptr_to_const(std::span<int const>(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<int const>(x, <# size #>));}\n" typedef struct {int x;} NAMED_UNNAMED_STRUCT; // an unnamed struct type named by a typedef typedef struct {int x;} * PTR_TO_ANON; // pointer to an unnamed struct @@ -24,7 +24,7 @@ void namedPointeeType(NAMED_UNNAMED_STRUCT * p) { // expected-warning{{'p' is a // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:10}:"(p = p.subspan(1)).data()" } } -// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}}\nvoid namedPointeeType(NAMED_UNNAMED_STRUCT * p) {return namedPointeeType(std::span<NAMED_UNNAMED_STRUCT>(p, <# size #>));}\n" +// CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:2-[[@LINE-1]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void namedPointeeType(NAMED_UNNAMED_STRUCT * p) {return namedPointeeType(std::span<NAMED_UNNAMED_STRUCT>(p, <# size #>));}\n" // We CANNOT fix a pointer to an unnamed type // CHECK-NOT: fix-it: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits