|
15 | 15 |
|
16 | 16 | import cpp |
17 | 17 | import codingstandards.c.misra |
18 | | -import codingstandards.cpp.rules.deadcode.DeadCode |
| 18 | +import codingstandards.cpp.alertreporting.HoldsForAllCopies |
| 19 | +import codingstandards.cpp.deadcode.UselessAssignments |
19 | 20 |
|
20 | | -classMisraCDeadCodeQueryextendsDeadCodeSharedQuery{ |
21 | | -MisraCDeadCodeQuery(){this= DeadCodePackage::deadCodeQuery()} |
| 21 | +/** |
| 22 | + * Gets an explicit cast from `e` if one exists. |
| 23 | + */ |
| 24 | +CastgetExplicitCast(Expre){ |
| 25 | +exists(Conversionc|c=e.getExplicitlyConverted()| |
| 26 | +result=c |
| 27 | +or |
| 28 | +result=c.(ParenthesisExpr).getExpr() |
| 29 | +) |
| 30 | +} |
| 31 | + |
| 32 | +classExprStmtExprextendsExpr{ |
| 33 | +ExprStmtExpr(){exists(ExprStmtes|es.getExpr()=this)} |
| 34 | +} |
| 35 | + |
| 36 | +/** |
| 37 | + * An "operation" as defined by MISRA C Rule 2.2 that is dead, i.e. it's removal has no effect on |
| 38 | + * the behaviour of the program. |
| 39 | + */ |
| 40 | +classDeadOperationInstanceextendsExpr{ |
| 41 | +stringdescription; |
| 42 | + |
| 43 | +DeadOperationInstance(){ |
| 44 | +// Exclude cases nested within macro expansions, because the code may be "live" in other |
| 45 | +// expansions |
| 46 | +isNotWithinMacroExpansion(this)and |
| 47 | +exists(ExprStmtExpre| |
| 48 | +ifexists(getExplicitCast(e)) |
| 49 | +then |
| 50 | +this=getExplicitCast(e)and |
| 51 | +// void conversions are permitted |
| 52 | +notgetExplicitCast(e)instanceofVoidConversionand |
| 53 | +description="Cast operation is unused" |
| 54 | +else( |
| 55 | +this=eand |
| 56 | +( |
| 57 | +ifeinstanceofAssignment |
| 58 | +then |
| 59 | +exists(SsaDefinitionsd,LocalScopeVariablev| |
| 60 | +e=sd.getDefinition()and |
| 61 | +sd.getDefiningValue(v).isPure()and |
| 62 | +// The definition is useless |
| 63 | +isUselessSsaDefinition(sd,v)and |
| 64 | +description="Assignment to "+v.getName()+" is unused and has no side effects" |
| 65 | +) |
| 66 | +else( |
| 67 | +e.isPure()and |
| 68 | +description="Result of operation is unused and has no side effects" |
| 69 | +) |
| 70 | +) |
| 71 | +) |
| 72 | +) |
| 73 | +} |
| 74 | + |
| 75 | +stringgetDescription(){result=description} |
22 | 76 | } |
| 77 | + |
| 78 | +classDeadOperation= HoldsForAllCopies<DeadOperationInstance,Expr>::LogicalResultElement; |
| 79 | + |
| 80 | +from |
| 81 | +DeadOperationdeadOperation,DeadOperationInstanceinstance,stringmessage,Elementexplainer, |
| 82 | +stringexplainerDescription |
| 83 | +where |
| 84 | +notisExcluded(instance, DeadCodePackage::deadCodeQuery())and |
| 85 | +instance=deadOperation.getAnElementInstance()and |
| 86 | +ifinstanceinstanceofFunctionCall |
| 87 | +then |
| 88 | +message=instance.getDescription()+" from call to function $@"and |
| 89 | +explainer=instance.(FunctionCall).getTarget()and |
| 90 | +explainerDescription=explainer.(Function).getName() |
| 91 | +else( |
| 92 | +message=instance.getDescription()and |
| 93 | +// Ignore the explainer |
| 94 | +explainer=instanceand |
| 95 | +explainerDescription="" |
| 96 | +) |
| 97 | +selectdeadOperation,message+".",explainer,explainerDescription |