[clang] 1638636 - [analyzer] Evaluate PredefinedExpressions
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Sun Sep 13 23:44:34 PDT 2020
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 at -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 at -3 {{&Element{"func",0 S64b,char}}}
+ // expected-warning at -3 {{&Element{"func",0 S64b,char}}}
+ // expected-warning at -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 at -4 {{&Element{"??$func at UClass@?1??foo@@YAXXZ@$0CK at D@@YAXD at Z",0 S64b,char}}}
+ // expected-warning at -4 {{&Element{L"func",0 S64b,wchar_t}}}
+ // expected-warning at -4 {{&Element{"void __cdecl func(U) [T = Class, Value = 42, U = char]",0 S64b,char}}}
+ // expected-warning at -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 at -3 {{&Element{"foo",0 S64b,char}}}
+ // expected-warning at -3 {{&Element{"foo",0 S64b,char}}}
+ // expected-warning at -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 at -4 {{&Element{"?foo@@YAXXZ",0 S64b,char}}}
+ // expected-warning at -4 {{&Element{L"foo",0 S64b,wchar_t}}}
+ // expected-warning at -4 {{&Element{"void __cdecl foo(void)",0 S64b,char}}}
+ // expected-warning at -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 at -1 {{&Element{"_ZTSi",0 S64b,char}}}
+}
+
+struct A {
+ A() {
+ clang_analyzer_dump(__func__);
+ clang_analyzer_dump(__FUNCTION__);
+ clang_analyzer_dump(__PRETTY_FUNCTION__);
+ // expected-warning at -3 {{&Element{"A",0 S64b,char}}}
+ // expected-warning at -3 {{&Element{"A",0 S64b,char}}}
+ // expected-warning at -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 at -4 {{&Element{"??0A@@QAE at XZ",0 S64b,char}}}
+ // expected-warning at -4 {{&Element{L"A",0 S64b,wchar_t}}}
+ // expected-warning at -4 {{&Element{"__thiscall A::A(void)",0 S64b,char}}}
+ // expected-warning at -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 at -3 {{&Element{"~A",0 S64b,char}}}
+ // expected-warning at -3 {{&Element{"~A",0 S64b,char}}}
+ // expected-warning at -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 at -4 {{&Element{"??1A@@QAE at XZ",0 S64b,char}}}
+ // expected-warning at -4 {{&Element{L"~A",0 S64b,wchar_t}}}
+ // expected-warning at -4 {{&Element{"__thiscall A::~A(void)",0 S64b,char}}}
+ // expected-warning at -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
+ }
+};
More information about the cfe-commits
mailing list