Author: Balazs Benics Date: 2020-09-14T08:43:56+02:00 New Revision: 163863604f9c1ad3add238f9e8fb32cfd136f894
URL: https://github.com/llvm/llvm-project/commit/163863604f9c1ad3add238f9e8fb32cfd136f894 DIFF: https://github.com/llvm/llvm-project/commit/163863604f9c1ad3add238f9e8fb32cfd136f894.diff LOG: [analyzer] Evaluate PredefinedExpressions We did not evaluate such expressions, just returned `Unknown` for such cases. After this patch, we will be able to access a unique value identifying a template instantiation via the value of the `PRETTY_FUNCTION` predefined expression. Reviewed By: vsavchenko Differential Revision: https://reviews.llvm.org/D87004 Added: clang/test/Analysis/eval-predefined-exprs.cpp Modified: clang/lib/StaticAnalyzer/Core/Environment.cpp clang/lib/StaticAnalyzer/Core/SValBuilder.cpp Removed: ################################################################################ diff --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp b/clang/lib/StaticAnalyzer/Core/Environment.cpp index 556ff6af15de..cba20b967b6f 100644 --- a/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -116,6 +116,7 @@ SVal Environment::getSVal(const EnvironmentEntry &Entry, case Stmt::StringLiteralClass: case Stmt::TypeTraitExprClass: case Stmt::SizeOfPackExprClass: + case Stmt::PredefinedExprClass: // Known constants; defer to SValBuilder. return svalBuilder.getConstantVal(cast<Expr>(S)).getValue(); diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp index 32d2a3e30708..72b8ada1dfab 100644 --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -306,6 +306,14 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) { return makeLoc(getRegionManager().getStringRegion(SL)); } + case Stmt::PredefinedExprClass: { + const auto *PE = cast<PredefinedExpr>(E); + assert(PE->getFunctionName() && + "Since we analyze only instantiated functions, PredefinedExpr " + "should have a function name."); + return makeLoc(getRegionManager().getStringRegion(PE->getFunctionName())); + } + // Fast-path some expressions to avoid the overhead of going through the AST's // constant evaluator case Stmt::CharacterLiteralClass: { diff --git a/clang/test/Analysis/eval-predefined-exprs.cpp b/clang/test/Analysis/eval-predefined-exprs.cpp new file mode 100644 index 000000000000..cc48a264f2d3 --- /dev/null +++ b/clang/test/Analysis/eval-predefined-exprs.cpp @@ -0,0 +1,109 @@ +// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core,debug.ExprInspection -verify %s +// +// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=core,debug.ExprInspection -verify \ +// RUN: -triple i386-pc-win32 -fms-compatibility -fms-extensions -DANALYZER_MS %s + +template <typename T> +void clang_analyzer_dump(const T *); +void clang_analyzer_warnIfReached(); + +void builtin_unique_stable_name_of_lambda() { + auto y = [] {}; + clang_analyzer_dump(__builtin_unique_stable_name(y)); + // expected-warning@-1 {{&Element{"_ZTSZ36builtin_unique_stable_name_of_lambdavEUlvE11_12",0 S64b,char}}} +} + +template <typename T, auto Value, typename U> +void func(U param) { + clang_analyzer_dump(__func__); + clang_analyzer_dump(__FUNCTION__); + clang_analyzer_dump(__PRETTY_FUNCTION__); + // expected-warning@-3 {{&Element{"func",0 S64b,char}}} + // expected-warning@-3 {{&Element{"func",0 S64b,char}}} + // expected-warning@-3 {{&Element{"void func(U) [T = Class, Value = 42, U = char]",0 S64b,char}}} + +#ifdef ANALYZER_MS + clang_analyzer_dump(__FUNCDNAME__); + clang_analyzer_dump(L__FUNCTION__); + clang_analyzer_dump(__FUNCSIG__); + clang_analyzer_dump(L__FUNCSIG__); + // expected-warning@-4 {{&Element{"??$func@UClass@?1??foo@@YAXXZ@$0CK@D@@YAXD@Z",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"func",0 S64b,wchar_t}}} + // expected-warning@-4 {{&Element{"void __cdecl func(U) [T = Class, Value = 42, U = char]",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"void __cdecl func(U) [T = Class, Value = 42, U = char]",0 S64b,wchar_t}}} +#endif +} + +void foo() { + clang_analyzer_dump(__func__); + clang_analyzer_dump(__FUNCTION__); + clang_analyzer_dump(__PRETTY_FUNCTION__); + // expected-warning@-3 {{&Element{"foo",0 S64b,char}}} + // expected-warning@-3 {{&Element{"foo",0 S64b,char}}} + // expected-warning@-3 {{&Element{"void foo()",0 S64b,char}}} + +#ifdef ANALYZER_MS + clang_analyzer_dump(__FUNCDNAME__); + clang_analyzer_dump(L__FUNCTION__); + clang_analyzer_dump(__FUNCSIG__); + clang_analyzer_dump(L__FUNCSIG__); + // expected-warning@-4 {{&Element{"?foo@@YAXXZ",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"foo",0 S64b,wchar_t}}} + // expected-warning@-4 {{&Element{"void __cdecl foo(void)",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"void __cdecl foo(void)",0 S64b,wchar_t}}} +#endif + + func<struct Class, 42ull>('b'); // instantiate template +} + +void test_builtin_unique_stable_name(int a) { + clang_analyzer_dump(__builtin_unique_stable_name(a)); + // expected-warning@-1 {{&Element{"_ZTSi",0 S64b,char}}} +} + +struct A { + A() { + clang_analyzer_dump(__func__); + clang_analyzer_dump(__FUNCTION__); + clang_analyzer_dump(__PRETTY_FUNCTION__); + // expected-warning@-3 {{&Element{"A",0 S64b,char}}} + // expected-warning@-3 {{&Element{"A",0 S64b,char}}} + // expected-warning@-3 {{&Element{"A::A()",0 S64b,char}}} + +#ifdef ANALYZER_MS + clang_analyzer_dump(__FUNCDNAME__); + clang_analyzer_dump(L__FUNCTION__); + clang_analyzer_dump(__FUNCSIG__); + clang_analyzer_dump(L__FUNCSIG__); + // expected-warning@-4 {{&Element{"??0A@@QAE@XZ",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"A",0 S64b,wchar_t}}} + // expected-warning@-4 {{&Element{"__thiscall A::A(void)",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"__thiscall A::A(void)",0 S64b,wchar_t}}} +#endif + } + ~A() { + clang_analyzer_dump(__func__); + clang_analyzer_dump(__FUNCTION__); + clang_analyzer_dump(__PRETTY_FUNCTION__); + // expected-warning@-3 {{&Element{"~A",0 S64b,char}}} + // expected-warning@-3 {{&Element{"~A",0 S64b,char}}} + // expected-warning@-3 {{&Element{"A::~A()",0 S64b,char}}} + +#ifdef ANALYZER_MS + clang_analyzer_dump(__FUNCDNAME__); + clang_analyzer_dump(L__FUNCTION__); + clang_analyzer_dump(__FUNCSIG__); + clang_analyzer_dump(L__FUNCSIG__); + // expected-warning@-4 {{&Element{"??1A@@QAE@XZ",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"~A",0 S64b,wchar_t}}} + // expected-warning@-4 {{&Element{"__thiscall A::~A(void)",0 S64b,char}}} + // expected-warning@-4 {{&Element{L"__thiscall A::~A(void)",0 S64b,wchar_t}}} +#endif + } + + template <typename> int dependent() { + // We should not analyze dependent functions. + // Such functions have no function name of predefined expressions such as: '__func__' etc. + clang_analyzer_warnIfReached(); // no-warning + } +}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits