|
20 | 20 | #include "clang/AST/OperationKinds.h" |
21 | 21 | #include "clang/AST/Stmt.h" |
22 | 22 | #include "clang/AST/StmtVisitor.h" |
23 | | -#include "clang/AST/Type.h" |
24 | 23 | #include "clang/Analysis/FlowSensitive/ASTOps.h" |
25 | 24 | #include "clang/Analysis/FlowSensitive/AdornedCFG.h" |
26 | 25 | #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" |
27 | 26 | #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" |
28 | 27 | #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" |
29 | 28 | #include "clang/Analysis/FlowSensitive/RecordOps.h" |
30 | | -#include "clang/Analysis/FlowSensitive/StorageLocation.h" |
31 | 29 | #include "clang/Analysis/FlowSensitive/Value.h" |
32 | 30 | #include "clang/Basic/Builtins.h" |
33 | | -#include "clang/Basic/LLVM.h" |
34 | 31 | #include "clang/Basic/OperatorKinds.h" |
35 | 32 | #include "llvm/Support/Casting.h" |
36 | 33 | #include <assert.h> |
@@ -290,7 +287,7 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { |
290 | 287 | } |
291 | 288 | } |
292 | 289 |
|
293 | | - void VisitCastExpr(const CastExpr *S) { |
| 290 | + void VisitImplicitCastExpr(const ImplicitCastExpr *S) { |
294 | 291 | const Expr *SubExpr = S->getSubExpr(); |
295 | 292 | assert(SubExpr != nullptr); |
296 | 293 |
|
@@ -320,70 +317,17 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { |
320 | 317 | break; |
321 | 318 | } |
322 | 319 |
|
323 | | - case CK_BaseToDerived: { |
324 | | - // This is a cast of (single-layer) pointer or reference to a record type. |
325 | | - // We should now model the fields for the derived type. |
326 | | - |
327 | | - // Get the RecordStorageLocation for the record object underneath. |
328 | | - RecordStorageLocation *Loc = nullptr; |
329 | | - if (S->getType()->isPointerType()) { |
330 | | - auto *PV = Env.get<PointerValue>(*SubExpr); |
331 | | - assert(PV != nullptr); |
332 | | - if (PV == nullptr) |
333 | | - break; |
334 | | - Loc = cast<RecordStorageLocation>(&PV->getPointeeLoc()); |
335 | | - } else { |
336 | | - assert(S->getType()->isRecordType()); |
337 | | - if (SubExpr->isGLValue()) { |
338 | | - Loc = Env.get<RecordStorageLocation>(*SubExpr); |
339 | | - } else { |
340 | | - Loc = &Env.getResultObjectLocation(*SubExpr); |
341 | | - } |
342 | | - } |
343 | | - if (!Loc) { |
344 | | - // Nowhere to add children or propagate from, so we're done. |
345 | | - break; |
346 | | - } |
347 | | - |
348 | | - // Get the derived record type underneath the reference or pointer. |
349 | | - QualType Derived = S->getType().getNonReferenceType(); |
350 | | - if (Derived->isPointerType()) { |
351 | | - Derived = Derived->getPointeeType(); |
352 | | - } |
353 | | - |
354 | | - // Add children to the storage location for fields (including synthetic |
355 | | - // fields) of the derived type and initialize their values. |
356 | | - for (const FieldDecl *Field : |
357 | | - Env.getDataflowAnalysisContext().getModeledFields(Derived)) { |
358 | | - assert(Field != nullptr); |
359 | | - QualType FieldType = Field->getType(); |
360 | | - if (FieldType->isReferenceType()) { |
361 | | - Loc->addChild(*Field, nullptr); |
362 | | - } else { |
363 | | - Loc->addChild(*Field, &Env.createStorageLocation(FieldType)); |
364 | | - } |
365 | | - |
366 | | - for (const auto &Entry : |
367 | | - Env.getDataflowAnalysisContext().getSyntheticFields(Derived)) { |
368 | | - Loc->addSyntheticField(Entry.getKey(), |
369 | | - Env.createStorageLocation(Entry.getValue())); |
370 | | - } |
371 | | - } |
372 | | - Env.initializeFieldsWithValues(*Loc, Derived); |
373 | | - |
374 | | - // Fall through to propagate SubExpr's StorageLocation to the CastExpr. |
375 | | - [[fallthrough]]; |
376 | | - } |
377 | 320 | case CK_IntegralCast: |
378 | 321 | // FIXME: This cast creates a new integral value from the |
379 | 322 | // subexpression. But, because we don't model integers, we don't |
380 | 323 | // distinguish between this new value and the underlying one. If integer |
381 | 324 | // modeling is added, then update this code to create a fresh location and |
382 | 325 | // value. |
383 | 326 | case CK_UncheckedDerivedToBase: |
384 | | - case CK_DerivedToBase: |
385 | 327 | case CK_ConstructorConversion: |
386 | 328 | case CK_UserDefinedConversion: |
| 329 | + // FIXME: Add tests that excercise CK_UncheckedDerivedToBase, |
| 330 | + // CK_ConstructorConversion, and CK_UserDefinedConversion. |
387 | 331 | case CK_NoOp: { |
388 | 332 | // FIXME: Consider making `Environment::getStorageLocation` skip noop |
389 | 333 | // expressions (this and other similar expressions in the file) instead |
@@ -740,6 +684,15 @@ class TransferVisitor : public ConstStmtVisitor<TransferVisitor> { |
740 | 684 | propagateValue(*SubExpr, *S, Env); |
741 | 685 | } |
742 | 686 |
|
| 687 | + void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) { |
| 688 | + if (S->getCastKind() == CK_NoOp) { |
| 689 | + const Expr *SubExpr = S->getSubExpr(); |
| 690 | + assert(SubExpr != nullptr); |
| 691 | + |
| 692 | + propagateValueOrStorageLocation(*SubExpr, *S, Env); |
| 693 | + } |
| 694 | + } |
| 695 | + |
743 | 696 | void VisitConditionalOperator(const ConditionalOperator *S) { |
744 | 697 | const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr()); |
745 | 698 | const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr()); |
|
0 commit comments