summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Analysis/CFG.cpp7
-rw-r--r--clang/lib/Analysis/ConstructionContext.cpp6
-rw-r--r--clang/test/Analysis/cfg-rich-constructors.cpp72
3 files changed, 85 insertions, 0 deletions
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 34d40162275..66019329a3b 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -2367,6 +2367,13 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
if (!boundType.isNull()) calleeType = boundType;
}
+ // FIXME: Once actually implemented, this construction context layer should
+ // include the number of the argument as well.
+ for (auto Arg: C->arguments()) {
+ findConstructionContexts(
+ ConstructionContextLayer::create(cfg->getBumpVectorContext(), C), Arg);
+ }
+
// If this is a call to a no-return function, this stops the block here.
bool NoReturn = getFunctionExtInfo(*calleeType).getNoReturn();
diff --git a/clang/lib/Analysis/ConstructionContext.cpp b/clang/lib/Analysis/ConstructionContext.cpp
index 9f3c00b2bc9..8656a1bbe09 100644
--- a/clang/lib/Analysis/ConstructionContext.cpp
+++ b/clang/lib/Analysis/ConstructionContext.cpp
@@ -79,6 +79,9 @@ const ConstructionContext *ConstructionContext::createFromLayers(
ParentLayer->getTriggerStmt()))) {
return create<TemporaryObjectConstructionContext>(C, BTE, MTE);
}
+ // This is a constructor into a function argument. Not implemented yet.
+ if (auto *CE = dyn_cast<CallExpr>(ParentLayer->getTriggerStmt()))
+ return nullptr;
// This is C++17 copy-elided construction into return statement.
if (auto *RS = dyn_cast<ReturnStmt>(ParentLayer->getTriggerStmt())) {
assert(!RS->getRetValue()->getType().getCanonicalType()
@@ -114,6 +117,9 @@ const ConstructionContext *ConstructionContext::createFromLayers(
assert(TopLayer->isLast());
return create<SimpleReturnedValueConstructionContext>(C, RS);
}
+ // This is a constructor into a function argument. Not implemented yet.
+ if (auto *CE = dyn_cast<CallExpr>(TopLayer->getTriggerStmt()))
+ return nullptr;
llvm_unreachable("Unexpected construction context with statement!");
} else if (const CXXCtorInitializer *I = TopLayer->getTriggerInit()) {
assert(TopLayer->isLast());
diff --git a/clang/test/Analysis/cfg-rich-constructors.cpp b/clang/test/Analysis/cfg-rich-constructors.cpp
index 51eca122292..eaaa5786f83 100644
--- a/clang/test/Analysis/cfg-rich-constructors.cpp
+++ b/clang/test/Analysis/cfg-rich-constructors.cpp
@@ -693,3 +693,75 @@ void implicitConstructionConversionFromFunctionValueWithLifetimeExtension() {
}
} // end namespace implicit_constructor_conversion
+
+namespace argument_constructors {
+class D {
+public:
+ D();
+ ~D();
+};
+
+void useC(C c);
+void useCByReference(const C &c);
+void useD(D d);
+void useDByReference(const D &d);
+
+// FIXME: Find construction context for the argument.
+// CHECK: void passArgument()
+// CHECK: 1: useC
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(class C))
+// CXX11-NEXT: 3: C() (CXXConstructExpr, [B1.4], class C)
+// CXX11-NEXT: 4: [B1.3]
+// CXX11-NEXT: 5: [B1.4] (CXXConstructExpr, class C)
+// CXX11-NEXT: 6: [B1.2]([B1.5])
+// CXX17-NEXT: 3: C() (CXXConstructExpr, class C)
+// CXX17-NEXT: 4: [B1.2]([B1.3])
+void passArgument() {
+ useC(C());
+}
+
+// CHECK: void passArgumentByReference()
+// CHECK: 1: useCByReference
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class C &))
+// CHECK-NEXT: 3: C() (CXXConstructExpr, [B1.5], class C)
+// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, NoOp, const class C)
+// CHECK-NEXT: 5: [B1.4]
+// CHECK-NEXT: 6: [B1.2]([B1.5])
+void passArgumentByReference() {
+ useCByReference(C());
+}
+
+// FIXME: Find construction context for the argument.
+// CHECK: void passArgumentWithDestructor()
+// CHECK: 1: useD
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(class argument_constructors::D))
+// CXX11-NEXT: 3: argument_constructors::D() (CXXConstructExpr, [B1.4], [B1.6], class argument_constructors::D)
+// CXX11-NEXT: 4: [B1.3] (BindTemporary)
+// CXX11-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CXX11-NEXT: 6: [B1.5]
+// CXX11-NEXT: 7: [B1.6] (CXXConstructExpr, class argument_constructors::D)
+// CXX11-NEXT: 8: [B1.7] (BindTemporary)
+// CXX11-NEXT: 9: [B1.2]([B1.8])
+// CXX11-NEXT: 10: ~argument_constructors::D() (Temporary object destructor)
+// CXX11-NEXT: 11: ~argument_constructors::D() (Temporary object destructor)
+// CXX17-NEXT: 3: argument_constructors::D() (CXXConstructExpr, class argument_constructors::D)
+// CXX17-NEXT: 4: [B1.3] (BindTemporary)
+// CXX17-NEXT: 5: [B1.2]([B1.4])
+// CXX17-NEXT: 6: ~argument_constructors::D() (Temporary object destructor)
+void passArgumentWithDestructor() {
+ useD(D());
+}
+
+// CHECK: void passArgumentWithDestructorByReference()
+// CHECK: 1: useDByReference
+// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, void (*)(const class argumen
+// CHECK-NEXT: 3: argument_constructors::D() (CXXConstructExpr, [B1.4], [B1.6], class argument_c
+// CHECK-NEXT: 4: [B1.3] (BindTemporary)
+// CHECK-NEXT: 5: [B1.4] (ImplicitCastExpr, NoOp, const class argument_constructors::D)
+// CHECK-NEXT: 6: [B1.5]
+// CHECK-NEXT: 7: [B1.2]([B1.6])
+// CHECK-NEXT: 8: ~argument_constructors::D() (Temporary object destructor)
+void passArgumentWithDestructorByReference() {
+ useDByReference(D());
+}
+} // end namespace argument_constructors
OpenPOWER on IntegriCloud