summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2021-12-06 23:14:19 -0800
committerTom Stellard <tstellar@redhat.com>2021-12-14 19:24:49 -0800
commitd904698b53e4f21a675d4ca0463843432ff4d590 (patch)
treeace821e7849a851adfcb6fc95f36984ab77f8161
parent5932c004778cf251302db0d46d1dfb247325ed3f (diff)
downloadllvm-d904698b53e4f21a675d4ca0463843432ff4d590.tar.gz
[Analysis] Ignore casts and unary ops for uninitialized values
A series of unary operators and casts may obscure the variable we're trying to analyze. Ignore them for the uninitialized value analysis. Other checks determine if the unary operators result in a valid l-value. Link: https://github.com/ClangBuiltLinux/linux/issues/1521 Reviewed By: nickdesaulniers Differential Revision: https://reviews.llvm.org/D114848 (cherry picked from commit c4582a689c2c74e0635309979176c7ada086f066)
-rw-r--r--clang/lib/Analysis/UninitializedValues.cpp17
-rw-r--r--clang/test/Analysis/uninit-asm-goto.cpp12
2 files changed, 25 insertions, 4 deletions
diff --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index 67cd39728c35..a38ae34f4b81 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -591,8 +591,8 @@ public:
if (AtPredExit == MayUninitialized) {
// If the predecessor's terminator is an "asm goto" that initializes
- // the variable, then it won't be counted as "initialized" on the
- // non-fallthrough paths.
+ // the variable, then don't count it as "initialized" on the indirect
+ // paths.
CFGTerminator term = Pred->getTerminator();
if (const auto *as = dyn_cast_or_null<GCCAsmStmt>(term.getStmt())) {
const CFGBlock *fallthrough = *Pred->succ_begin();
@@ -810,13 +810,22 @@ void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) {
if (!as->isAsmGoto())
return;
- for (const Expr *o : as->outputs())
- if (const VarDecl *VD = findVar(o).getDecl())
+ ASTContext &C = ac.getASTContext();
+ for (const Expr *O : as->outputs()) {
+ const Expr *Ex = stripCasts(C, O);
+
+ // Strip away any unary operators. Invalid l-values are reported by other
+ // semantic analysis passes.
+ while (const auto *UO = dyn_cast<UnaryOperator>(Ex))
+ Ex = stripCasts(C, UO->getSubExpr());
+
+ if (const VarDecl *VD = findVar(Ex).getDecl())
if (vals[VD] != Initialized)
// If the variable isn't initialized by the time we get here, then we
// mark it as potentially uninitialized for those cases where it's used
// on an indirect path, where it's not guaranteed to be defined.
vals[VD] = MayUninitialized;
+ }
}
void TransferFunctions::VisitObjCMessageExpr(ObjCMessageExpr *ME) {
diff --git a/clang/test/Analysis/uninit-asm-goto.cpp b/clang/test/Analysis/uninit-asm-goto.cpp
index 43438dc589be..9da21584ec86 100644
--- a/clang/test/Analysis/uninit-asm-goto.cpp
+++ b/clang/test/Analysis/uninit-asm-goto.cpp
@@ -57,3 +57,15 @@ fallthrough:
indirect:
return -2;
}
+
+// test6: Expect no diagnostics.
+int test6(unsigned int *x) {
+ unsigned int val;
+
+ // See through casts and unary operators.
+ asm goto("nop" : "=r" (*(unsigned int *)(&val)) ::: indirect);
+ *x = val;
+ return 0;
+indirect:
+ return -1;
+}