vsavchenko created this revision. vsavchenko added reviewers: NoQ, xazax.hun, martong, steakhal, Szelethus, ASDenysPetrov, manas, RedDocMD. Herald added subscribers: dkrupp, donat.nagy, mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware. vsavchenko requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
rdar://76948312 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D104716 Files: clang/lib/StaticAnalyzer/Core/CallEvent.cpp clang/test/Analysis/transparent_union_bug.c
Index: clang/test/Analysis/transparent_union_bug.c =================================================================== --- /dev/null +++ clang/test/Analysis/transparent_union_bug.c @@ -0,0 +1,42 @@ +// RUN: %clang_analyze_cc1 -analyze -triple x86_64-apple-darwin10 \ +// RUN: -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_warnIfReached(); +void clang_analyzer_printState(); + +typedef struct { + int value; +} Struct; + +typedef union { + Struct *ptr; + long num; +} __attribute__((transparent_union)) Alias; + +void foo(Struct *x); +void foo(Alias y) { + if (y.ptr == 0) { + // no-crash + } + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} +void foobar(long z); +void foobar(Alias z) { + clang_analyzer_printState(); + if (z.num != 42) { + // no-crash + } + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} + +void foobaz(Alias x) { + if (x.ptr == 0) { + // no-crash + } + clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}} +} +void bar(Struct arg) { + foo(&arg); + foobar(42); + foobaz(&arg); +} Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/CallEvent.cpp +++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -47,6 +47,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" @@ -466,6 +467,46 @@ llvm_unreachable("unknown callable kind"); } +static bool isTransparentUnion(QualType T) { + const RecordType *UT = T->getAsUnionType(); + return UT && UT->getDecl()->hasAttr<TransparentUnionAttr>(); +} + +static bool isTransparentUnion(SVal Value, const ASTContext &Context) { + Optional<QualType> T = Value.getType(Context); + return T && isTransparentUnion(*T); +} + +// In some cases, symbolic cases should be transformed before we associate +// them with parameters. This function incapsulates such cases. +static SVal process(SVal Value, const ParmVarDecl *Parameter, + SValBuilder &SVB) { + QualType ParamType = Parameter->getType(); + + // Transparent unions allow users to easily convert values of union field + // types into union-typed objects. + // + // Also, more importantly, they allow users to define functions with different + // different parameter types, substituting types matching transparent union + // field types with the union type itself. + // + // Here, we check specifically for latter cases and prevent binding + // field-typed values to union-typed regions. + if (isTransparentUnion(ParamType) && + // Let's check that we indeed trying to bind different types. + !isTransparentUnion(Value, SVB.getContext())) { + BasicValueFactory &BVF = SVB.getBasicValueFactory(); + + llvm::ImmutableList<SVal> CompoundSVals = BVF.getEmptySValList(); + CompoundSVals = BVF.prependSVal(Value, CompoundSVals); + + // Wrap it with compound value. + return SVB.makeCompoundVal(ParamType, CompoundSVals); + } + + return Value; +} + static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx, CallEvent::BindingsTy &Bindings, SValBuilder &SVB, @@ -493,7 +534,7 @@ if (!ArgVal.isUnknown()) { Loc ParamLoc = SVB.makeLoc( MRMgr.getParamVarRegion(Call.getOriginExpr(), Idx, CalleeCtx)); - Bindings.push_back(std::make_pair(ParamLoc, ArgVal)); + Bindings.push_back(std::make_pair(ParamLoc, process(ArgVal, *I, SVB))); } }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits