C++: Block flow by default.

This commit is contained in:
Mathias Vorreiter Pedersen
2024-02-15 10:17:20 +01:00
parent 625c47fa9c
commit 24a63ae94d
9 changed files with 97 additions and 59 deletions

View File

@@ -4,7 +4,10 @@ private import DataFlowUtil
private import DataFlowImplCommon as DataFlowImplCommon private import DataFlowImplCommon as DataFlowImplCommon
private import semmle.code.cpp.models.interfaces.Allocation as Alloc private import semmle.code.cpp.models.interfaces.Allocation as Alloc
private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow
private import semmle.code.cpp.models.interfaces.Taint as Taint
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
private import DataFlowPrivate private import DataFlowPrivate
private import ssa0.SsaInternals as SsaInternals0 private import ssa0.SsaInternals as SsaInternals0
import SsaInternalsCommon import SsaInternalsCommon
@@ -796,10 +799,47 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
) )
} }
private predicate inOut(FIO::FunctionInput input, FIO::FunctionOutput output) {
exists(int indirectionIndex |
input.isQualifierObject(indirectionIndex) and
output.isQualifierObject(indirectionIndex)
or
exists(int i |
input.isParameterDeref(i, indirectionIndex) and
output.isParameterDeref(i, indirectionIndex)
)
)
}
/**
* Holds if there should not be use-use flow out of `n` (or a conversion that
* flows to `n`).
*/
private predicate modeledFlowBarrier(Node n) {
exists(FIO::FunctionInput input, FIO::FunctionOutput output, CallInstruction call |
n = callInput(call, input) and
inOut(input, output) and
exists(callOutput(call, output))
|
call.getStaticCallTarget().(DataFlow::DataFlowFunction).hasDataFlow(_, output)
or
call.getStaticCallTarget().(Taint::TaintFunction).hasTaintFlow(_, output)
)
or
exists(Operand operand, Instruction instr, Node n0, int indirectionIndex |
modeledFlowBarrier(n0) and
nodeHasInstruction(n0, instr, indirectionIndex) and
conversionFlow(operand, instr, false, _) and
nodeHasOperand(n, operand, indirectionIndex)
)
}
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */ /** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
predicate ssaFlow(Node nodeFrom, Node nodeTo) { predicate ssaFlow(Node nodeFrom, Node nodeTo) {
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse | exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and nodeFrom != nodeTo ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
not modeledFlowBarrier(nFrom) and
nodeFrom != nodeTo
| |
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
) )

View File

@@ -238,8 +238,6 @@ irFlow
| test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp | | test.cpp:382:48:382:54 | source1 | test.cpp:385:8:385:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp | | test.cpp:388:53:388:59 | source1 | test.cpp:392:8:392:10 | tmp |
| test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp | | test.cpp:388:53:388:59 | source1 | test.cpp:394:10:394:12 | tmp |
| test.cpp:399:7:399:9 | definition of tmp | test.cpp:401:8:401:10 | tmp |
| test.cpp:405:7:405:9 | definition of tmp | test.cpp:408:8:408:10 | tmp |
| test.cpp:416:7:416:11 | definition of local | test.cpp:418:8:418:12 | local | | test.cpp:416:7:416:11 | definition of local | test.cpp:418:8:418:12 | local |
| test.cpp:417:16:417:20 | intRefSource output argument | test.cpp:418:8:418:12 | local | | test.cpp:417:16:417:20 | intRefSource output argument | test.cpp:418:8:418:12 | local |
| test.cpp:422:7:422:11 | definition of local | test.cpp:424:8:424:12 | local | | test.cpp:422:7:422:11 | definition of local | test.cpp:424:8:424:12 | local |

View File

@@ -398,14 +398,14 @@ void flowThroughMemcpy_blockvar_with_local_flow(int source1, int b) {
void cleanedByMemcpy_ssa(int clean1) { // currently modeled with BlockVar, not SSA void cleanedByMemcpy_ssa(int clean1) { // currently modeled with BlockVar, not SSA
int tmp; int tmp;
memcpy(&tmp, &clean1, sizeof tmp); memcpy(&tmp, &clean1, sizeof tmp);
sink(tmp); // $ SPURIOUS: ast,ir sink(tmp); // $ SPURIOUS: ast
} }
void cleanedByMemcpy_blockvar(int clean1) { void cleanedByMemcpy_blockvar(int clean1) {
int tmp; int tmp;
int *capture = &tmp; int *capture = &tmp;
memcpy(&tmp, &clean1, sizeof tmp); memcpy(&tmp, &clean1, sizeof tmp);
sink(tmp); // $ SPURIOUS: ast,ir sink(tmp); // $ SPURIOUS: ast
} }
void intRefSource(int &ref_source); void intRefSource(int &ref_source);

View File

@@ -71,11 +71,11 @@ void test_pair()
sink(i.second); // $ MISSING: ast,ir sink(i.second); // $ MISSING: ast,ir
sink(i); // $ ast,ir sink(i); // $ ast,ir
sink(j.first); sink(j.first);
sink(j.second); // $ SPURIOUS: ast,ir sink(j.second); // $ SPURIOUS: ast
sink(j); // $ SPURIOUS: ast,ir sink(j); // $ SPURIOUS: ast
sink(k.first); sink(k.first);
sink(k.second); // $ SPURIOUS: ast,ir sink(k.second); // $ SPURIOUS: ast
sink(k); // $ SPURIOUS: ast,ir sink(k); // $ SPURIOUS: ast
sink(l.first); sink(l.first);
sink(l.second); // $ MISSING: ast,ir sink(l.second); // $ MISSING: ast,ir
sink(l); // $ ast,ir sink(l); // $ ast,ir
@@ -179,11 +179,11 @@ void test_map()
m14.insert(std::make_pair("b", source())); m14.insert(std::make_pair("b", source()));
m14.insert(std::make_pair("c", source())); m14.insert(std::make_pair("c", source()));
m14.insert(std::make_pair("d", "d")); m14.insert(std::make_pair("d", "d"));
sink(m14.lower_bound("b")); // $ ast,ir=179:33 ast,ir=180:33 sink(m14.lower_bound("b")); // $ ast=179:33 ast=180:33 MISSING: ir=179:33 ir=180:33
sink(m14.upper_bound("b")); // $ ast,ir=179:33 ast,ir=180:33 sink(m14.upper_bound("b")); // $ ast=179:33 ast=180:33 MISSING: ir=179:33 ir=180:33
sink(m14.equal_range("b").first); // $ MISSING: ast,ir sink(m14.equal_range("b").first); // $ MISSING: ast,ir
sink(m14.equal_range("b").second); // $ MISSING: ast,ir sink(m14.equal_range("b").second); // $ MISSING: ast,ir
sink(m14.upper_bound("c")); // $ SPURIOUS: ast,ir=179:33 ast,ir=180:33 sink(m14.upper_bound("c")); // $ SPURIOUS: ast=179:33 ast=180:33
sink(m14.equal_range("c").second); sink(m14.equal_range("c").second);
// swap // swap
@@ -196,10 +196,10 @@ void test_map()
sink(m18); // $ ast,ir sink(m18); // $ ast,ir
m15.swap(m16); m15.swap(m16);
m17.swap(m18); m17.swap(m18);
sink(m15); // $ SPURIOUS: ast,ir sink(m15); // $ SPURIOUS: ast
sink(m16); // $ ast,ir sink(m16); // $ ast,ir
sink(m17); // $ ast,ir sink(m17); // $ ast,ir
sink(m18); // $ SPURIOUS: ast,ir sink(m18); // $ SPURIOUS: ast
// merge // merge
std::map<char *, char *> m19, m20, m21, m22; std::map<char *, char *> m19, m20, m21, m22;
@@ -213,7 +213,7 @@ void test_map()
sink(m22); // $ ast,ir sink(m22); // $ ast,ir
m19.merge(m20); m19.merge(m20);
m21.merge(m22); m21.merge(m22);
sink(m19); // $ ast,ir sink(m19); // $ ast
sink(m20); sink(m20);
sink(m21); // $ ast,ir sink(m21); // $ ast,ir
sink(m22); // $ ast,ir sink(m22); // $ ast,ir
@@ -222,11 +222,11 @@ void test_map()
std::map<char *, char *> m23; std::map<char *, char *> m23;
m23.insert(std::pair<char *, char *>(source(), source())); m23.insert(std::pair<char *, char *>(source(), source()));
m23.insert(std::pair<char *, char *>(source(), source())); m23.insert(std::pair<char *, char *>(source(), source()));
sink(m23); // $ ast,ir=223:49 ast,ir=224:49 sink(m23); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
sink(m23.erase(m23.begin())); // $ ast,ir=223:49 ast,ir=224:49 sink(m23.erase(m23.begin())); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
sink(m23); // $ ast,ir=223:49 ast,ir=224:49 sink(m23); // $ ast=223:49 ast=224:49 ir MISSING: ir=223:49 ir=224:49
m23.clear(); m23.clear();
sink(m23); // $ SPURIOUS: ast,ir=223:49 ast,ir=224:49 sink(m23); // $ SPURIOUS: ast=223:49 ast=224:49 ir
// emplace, emplace_hint // emplace, emplace_hint
std::map<char *, char *> m24, m25; std::map<char *, char *> m24, m25;
@@ -345,10 +345,10 @@ void test_unordered_map()
sink(m18); // $ ast,ir sink(m18); // $ ast,ir
m15.swap(m16); m15.swap(m16);
m17.swap(m18); m17.swap(m18);
sink(m15); // $ SPURIOUS: ast,ir sink(m15); // $ SPURIOUS: ast
sink(m16); // $ ast,ir sink(m16); // $ ast,ir
sink(m17); // $ ast,ir sink(m17); // $ ast,ir
sink(m18); // $ SPURIOUS: ast,ir sink(m18); // $ SPURIOUS: ast
// merge // merge
std::unordered_map<char *, char *> m19, m20, m21, m22; std::unordered_map<char *, char *> m19, m20, m21, m22;
@@ -362,7 +362,7 @@ void test_unordered_map()
sink(m22); // $ ast,ir sink(m22); // $ ast,ir
m19.merge(m20); m19.merge(m20);
m21.merge(m22); m21.merge(m22);
sink(m19); // $ ast,ir sink(m19); // $ ast MISSING: ir
sink(m20); sink(m20);
sink(m21); // $ ast,ir sink(m21); // $ ast,ir
sink(m22); // $ ast,ir sink(m22); // $ ast,ir
@@ -371,11 +371,11 @@ void test_unordered_map()
std::unordered_map<char *, char *> m23; std::unordered_map<char *, char *> m23;
m23.insert(std::pair<char *, char *>(source(), source())); m23.insert(std::pair<char *, char *>(source(), source()));
m23.insert(std::pair<char *, char *>(source(), source())); m23.insert(std::pair<char *, char *>(source(), source()));
sink(m23); // $ ast,ir=372:49 ast,ir=373:49 sink(m23); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
sink(m23.erase(m23.begin())); // $ ast,ir=372:49 ast,ir=373:49 sink(m23.erase(m23.begin())); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
sink(m23); // $ ast,ir=372:49 ast,ir=373:49 sink(m23); // $ ast=372:49 ast=373:49 ir MISSING: ir=372:49 ir=373:49
m23.clear(); m23.clear();
sink(m23); // $ SPURIOUS: ast,ir=372:49 ast,ir=373:49 sink(m23); // $ SPURIOUS: ast=372:49 ast=373:49 ir
// emplace, emplace_hint // emplace, emplace_hint
std::unordered_map<char *, char *> m24, m25; std::unordered_map<char *, char *> m24, m25;
@@ -395,7 +395,7 @@ void test_unordered_map()
sink(m26); sink(m26);
sink(m26.try_emplace("abc", source()).first); sink(m26.try_emplace("abc", source()).first);
sink(m26.try_emplace("abc", source()).second); // $ MISSING: ast,ir=396:30 sink(m26.try_emplace("abc", source()).second); // $ MISSING: ast,ir=396:30
sink(m26); // $ ast,ir=396:30 SPURIOUS: ast,ir=397:30 sink(m26); // $ ast=396:30 ir MISSING: ir=396:30 SPURIOUS: ast=397:30
sink(m27.try_emplace(m27.begin(), "abc", "def")); sink(m27.try_emplace(m27.begin(), "abc", "def"));
sink(m27); sink(m27);
sink(m27.try_emplace(m27.begin(), "abc", source())); // $ ast,ir sink(m27.try_emplace(m27.begin(), "abc", source())); // $ ast,ir

View File

@@ -66,8 +66,8 @@ void test_set()
s11.insert("a"); s11.insert("a");
s11.insert(source()); s11.insert(source());
s11.insert("c"); s11.insert("c");
sink(s11.lower_bound("b")); // $ ast,ir sink(s11.lower_bound("b")); // $ ast MISSING: ir
sink(s11.upper_bound("b")); // $ ast,ir sink(s11.upper_bound("b")); // $ ast MISSING: ir
sink(s11.equal_range("b").first); // $ MISSING: ast,ir sink(s11.equal_range("b").first); // $ MISSING: ast,ir
sink(s11.equal_range("b").second); // $ MISSING: ast,ir sink(s11.equal_range("b").second); // $ MISSING: ast,ir
@@ -81,10 +81,10 @@ void test_set()
sink(s15); // $ ast,ir sink(s15); // $ ast,ir
s12.swap(s13); s12.swap(s13);
s14.swap(s15); s14.swap(s15);
sink(s12); // $ SPURIOUS: ast,ir sink(s12); // $ SPURIOUS: ast
sink(s13); // $ ast,ir sink(s13); // $ ast,ir
sink(s14); // $ ast,ir sink(s14); // $ ast,ir
sink(s15); // $ SPURIOUS: ast,ir sink(s15); // $ SPURIOUS: ast
// merge // merge
std::set<char *> s16, s17, s18, s19; std::set<char *> s16, s17, s18, s19;
@@ -98,7 +98,7 @@ void test_set()
sink(s19); // $ ast,ir sink(s19); // $ ast,ir
s16.merge(s17); s16.merge(s17);
s18.merge(s19); s18.merge(s19);
sink(s16); // $ ast,ir sink(s16); // $ ast MISSING: ir
sink(s17); sink(s17);
sink(s18); // $ ast,ir sink(s18); // $ ast,ir
sink(s19); // $ ast,ir sink(s19); // $ ast,ir
@@ -107,11 +107,11 @@ void test_set()
std::set<char *> s20; std::set<char *> s20;
s20.insert(source()); s20.insert(source());
s20.insert(source()); s20.insert(source());
sink(s20); // $ ast,ir=108:13 ast,ir=109:13 sink(s20); // $ ast=108:13 ast=109:13 ir MISSING: ir=108:13 ir=109:13
sink(s20.erase(s20.begin())); // $ ast,ir=108:13 ast,ir=109:13 sink(s20.erase(s20.begin())); // $ ast=108:13 ast=109:13 ir MISSING: ir=108:13 ir=109:13
sink(s20); // $ ast,ir=108:13 ast,ir=109:13 sink(s20); // $ ir ast=108:13 ast=109:13 MISSING: ir=108:13 ir=109:13
s20.clear(); s20.clear();
sink(s20); // $ SPURIOUS: ast,ir=108:13 ast,ir=109:13 sink(s20); // $ SPURIOUS: ir ast=108:13 ast=109:13
// emplace, emplace_hint // emplace, emplace_hint
std::set<char *> s21, s22; std::set<char *> s21, s22;
@@ -193,10 +193,10 @@ void test_unordered_set()
sink(s15); // $ ast,ir sink(s15); // $ ast,ir
s12.swap(s13); s12.swap(s13);
s14.swap(s15); s14.swap(s15);
sink(s12); // $ SPURIOUS: ast,ir sink(s12); // $ SPURIOUS: ast
sink(s13); // $ ast,ir sink(s13); // $ ast,ir
sink(s14); // $ ast,ir sink(s14); // $ ast,ir
sink(s15); // $ SPURIOUS: ast,ir sink(s15); // $ SPURIOUS: ast
// merge // merge
std::unordered_set<char *> s16, s17, s18, s19; std::unordered_set<char *> s16, s17, s18, s19;
@@ -210,7 +210,7 @@ void test_unordered_set()
sink(s19); // $ ast,ir sink(s19); // $ ast,ir
s16.merge(s17); s16.merge(s17);
s18.merge(s19); s18.merge(s19);
sink(s16); // $ ast,ir sink(s16); // $ ast MISSING: ir
sink(s17); sink(s17);
sink(s18); // $ ast,ir sink(s18); // $ ast,ir
sink(s19); // $ ast,ir sink(s19); // $ ast,ir
@@ -219,11 +219,11 @@ void test_unordered_set()
std::unordered_set<char *> s20; std::unordered_set<char *> s20;
s20.insert(source()); s20.insert(source());
s20.insert(source()); s20.insert(source());
sink(s20); // $ ast,ir=220:13 ast,ir=221:13 sink(s20); // $ ir ast=220:13 ast=221:13 MISSING: ir=220:13 ir=221:13
sink(s20.erase(s20.begin())); // $ ast,ir=220:13 ast,ir=221:13 sink(s20.erase(s20.begin())); // $ ast=220:13 ast=221:13 ir MISSING: ir=220:13 ir=221:13
sink(s20); // $ ast,ir=220:13 ast,ir=221:13 sink(s20); // $ ast=220:13 ast=221:13 ir MISSING: ir=220:13 ir=221:13
s20.clear(); s20.clear();
sink(s20); // $ SPURIOUS: ast,ir=220:13 ast,ir=221:13 sink(s20); // $ SPURIOUS: ast=220:13 ast=221:13 ir
// emplace, emplace_hint // emplace, emplace_hint
std::unordered_set<char *> s21, s22; std::unordered_set<char *> s21, s22;

View File

@@ -203,7 +203,7 @@ void test_string_assign() {
sink(s5); // $ ast,ir sink(s5); // $ ast,ir
sink(s6.assign(s1)); sink(s6.assign(s1));
sink(s6); // $ SPURIOUS: ast,ir sink(s6); // $ SPURIOUS: ast
} }
void test_string_insert() { void test_string_insert() {
@@ -280,9 +280,9 @@ void test_string_swap() {
s4.swap(s3); s4.swap(s3);
sink(s1); // $ ast,ir sink(s1); // $ ast,ir
sink(s2); // $ SPURIOUS: ast,ir sink(s2); // $ SPURIOUS: ast
sink(s3); // $ ast,ir sink(s3); // $ ast,ir
sink(s4); // $ SPURIOUS: ast,ir sink(s4); // $ SPURIOUS: ast
} }
void test_string_clear() { void test_string_clear() {
@@ -495,7 +495,7 @@ void test_string_iterator_methods()
sink(h); // $ ast,ir sink(h); // $ ast,ir
sink(s6.assign(s5.cbegin(), s5.cend())); sink(s6.assign(s5.cbegin(), s5.cend()));
sink(s6); // $ SPURIOUS: ast,ir sink(s6); // $ SPURIOUS: ast
} }
} }

View File

@@ -50,7 +50,7 @@ void test_stringstream_string(int amount)
ss7.str(source()); ss7.str(source());
ss7.str("abc"); // (overwrites) ss7.str("abc"); // (overwrites)
sink(ss6); // $ ast,ir sink(ss6); // $ ast,ir
sink(ss7); // $ SPURIOUS: ast,ir sink(ss7); // $ SPURIOUS: ast
sink(ss8.put('a')); sink(ss8.put('a'));
sink(ss9.put(ns_char::source())); // $ ast,ir sink(ss9.put(ns_char::source())); // $ ast,ir
@@ -118,9 +118,9 @@ void test_stringstream_swap()
ss4.swap(ss3); ss4.swap(ss3);
sink(ss1); // $ ast,ir sink(ss1); // $ ast,ir
sink(ss2); // $ SPURIOUS: ast,ir sink(ss2); // $ SPURIOUS: ast
sink(ss3); // $ ast,ir sink(ss3); // $ ast,ir
sink(ss4); // $ SPURIOUS: ast,ir sink(ss4); // $ SPURIOUS: ast
} }
void test_stringstream_in() void test_stringstream_in()
@@ -217,7 +217,7 @@ void test_getline()
sink(ss1.getline(b3, 1000)); sink(ss1.getline(b3, 1000));
sink(b1); sink(b1);
sink(b2); // $ ast,ir sink(b2); // $ ast,ir
sink(b3); // $ SPURIOUS: ast,ir sink(b3); // $ SPURIOUS: ast
sink(ss1.getline(b4, 1000, ' ')); sink(ss1.getline(b4, 1000, ' '));
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
@@ -225,7 +225,7 @@ void test_getline()
sink(ss1.getline(b6, 1000, ' ')); sink(ss1.getline(b6, 1000, ' '));
sink(b4); sink(b4);
sink(b5); // $ ast,ir sink(b5); // $ ast,ir
sink(b6); // $ SPURIOUS: ast,ir sink(b6); // $ SPURIOUS: ast
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
sink(b7); // $ ast,ir sink(b7); // $ ast,ir
@@ -237,7 +237,7 @@ void test_getline()
sink(getline(ss1, s3)); sink(getline(ss1, s3));
sink(s1); sink(s1);
sink(s2); // $ ast,ir sink(s2); // $ ast,ir
sink(s3); // $ SPURIOUS: ast,ir sink(s3); // $ SPURIOUS: ast
sink(getline(ss1, s4, ' ')); sink(getline(ss1, s4, ' '));
sink(getline(ss2, s5, ' ')); // $ ast,ir sink(getline(ss2, s5, ' ')); // $ ast,ir
@@ -245,7 +245,7 @@ void test_getline()
sink(getline(ss1, s6, ' ')); sink(getline(ss1, s6, ' '));
sink(s4); sink(s4);
sink(s5); // $ ast,ir sink(s5); // $ ast,ir
sink(s6); // $ SPURIOUS: ast,ir sink(s6); // $ SPURIOUS: ast
sink(getline(getline(ss2, s7), s8)); // $ ast,ir sink(getline(getline(ss2, s7), s8)); // $ ast,ir
sink(s7); // $ ast,ir sink(s7); // $ ast,ir

View File

@@ -212,7 +212,7 @@ void test_swap() {
std::swap(x, y); std::swap(x, y);
sink(x); // $ SPURIOUS: ast,ir sink(x); // $ SPURIOUS: ast
sink(y); // $ ast,ir sink(y); // $ ast,ir
} }
@@ -756,5 +756,5 @@ void call_sprintf_twice(char* path, char* data) {
void test_call_sprintf() { void test_call_sprintf() {
char path[10]; char path[10];
call_sprintf_twice(path, indirect_source()); call_sprintf_twice(path, indirect_source());
sink(*path); // $ ir ast sink(*path); // $ ast MISSING: ir
} }

View File

@@ -114,10 +114,10 @@ void test_vector_swap() {
v1.swap(v2); v1.swap(v2);
v3.swap(v4); v3.swap(v4);
sink(v1); // $ SPURIOUS: ast,ir sink(v1); // $ SPURIOUS: ast
sink(v2); // $ ast,ir sink(v2); // $ ast,ir
sink(v3); // $ ast,ir sink(v3); // $ ast,ir
sink(v4); // $ SPURIOUS: ast,ir sink(v4); // $ SPURIOUS: ast
} }
void test_vector_clear() { void test_vector_clear() {
@@ -138,7 +138,7 @@ void test_vector_clear() {
sink(v1); // $ SPURIOUS: ast,ir sink(v1); // $ SPURIOUS: ast,ir
sink(v2); // $ ast,ir sink(v2); // $ ast,ir
sink(v3); // $ ast,ir sink(v3); // $ SPURIOUS: ast
sink(v4); sink(v4);
} }