// RUN: %clang_analyze_cc1 -triple=x86_64-unknown-unknown \ // RUN: -analyzer-checker debug.ExprInspection,core -Wno-error=invalid-gnu-asm-cast -w %s -verify int clang_analyzer_eval(int); void clang_analyzer_dump(int); void clang_analyzer_dump_ptr(void *); int global; void testRValueOutput() { int origVal = global; __asm__("" : "=r"(((int)(global)))); // don't crash on rvalue output operand int newVal = global; // Value "after" the invalidation. clang_analyzer_eval(origVal == newVal); // expected-warning{{TRUE}} expected-warning{{FALSE}} } void *MyMemcpy(void *d, const void *s, const int n) { asm volatile ( "cld\n rep movsb\n" :: "S" (s), "D" (d), "c" (n) : "memory" ); return d; } void testInlineAsmMemcpy(void) { int a, b = 10, c; MyMemcpy(&a, &b, sizeof(b)); c = a; // no-warning } void testInlineAsmMemcpyArray(void) { int a[10], b[10] = {}, c; MyMemcpy(&a, &b, sizeof(b)); c = a[8]; // no-warning } void testInlineAsmMemcpyUninit(void) { int a[10], b[10] = {}, c; MyMemcpy(&a[1], &b[1], sizeof(b) - sizeof(b[1])); c = a[0]; // FIXME: should be warning about uninitialized value, but invalidateRegions() also // invalidates super region. } void testInlineAsmMemcpyUninitLoop(const void *src, unsigned long len) { int a[10], c; unsigned long toCopy = sizeof(a) < len ? sizeof(a) : len; MyMemcpy(a, src, toCopy); // Use index 1, since before use of invalidateRegions in VisitGCCAsmStmt, engine bound unknown SVal only to // first element. c = a[1]; // no-warning } void testAsmWithVoidPtrArgument() { extern void *globalVoidPtr; clang_analyzer_dump(*(int *)globalVoidPtr); // expected-warning-re {{reg_${{[0-9]+}}},0 S64b,int}>}} clang_analyzer_dump_ptr(globalVoidPtr); // expected-warning-re {{&SymRegion{reg_${{[0-9]+}}}}} asm ("" : : "a"(globalVoidPtr)); // no crash clang_analyzer_dump(*(int *)globalVoidPtr); // expected-warning {{derived_}} clang_analyzer_dump_ptr(globalVoidPtr); // expected-warning-re {{&SymRegion{reg_${{[0-9]+}}}}} }