[cfe-dev] Found a bug - maybe?

Chris Lattner clattner at apple.com
Mon Jun 7 09:07:00 PDT 2010


On Jun 7, 2010, at 8:33 AM, Jeffrey Yasskin wrote:

> (buffer - 4) causes undefined behavior, per [expr.add]: "if the
> expression P points to the i-th element of an array ob ject, the
> expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the
> value n) point to, respectively, the i + n-th and i - n-th elements of
> the array object, provided they exist."

Right, a portable way to do this is to do the comparison on "(uintptr_t)P" instead of on P.

-Chris

> 
> Instcombine actually does the damage here, turning
> 
> define i32 @main() {
> entry:
>  %retval = alloca i32, align 4                   ; <i32*> [#uses=2]
>  store i32 0, i32* %retval
>  br i1 icmp ugt (i8* getelementptr inbounds ([2 x i8]*
> @_ZZ4mainE6buffer, i32 0, i32 0), i8* getelementptr inbounds ([2 x
> i8]* @_ZZ4mainE6buffer, i32 0, i32 -4)), label %if.then, label
> %if.else
> 
> if.then:                                          ; preds = %entry
>  %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10
> x i8]* @.str, i32 0, i32 0)) ; <i32> [#uses=0]
>  br label %if.end
> 
> if.else:                                          ; preds = %entry
>  %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
> ([10 x i8]* @.str1, i32 0, i32 0)) ; <i32> [#uses=0]
>  br label %if.end
> 
> if.end:                                           ; preds = %if.else, %if.then
>  %0 = load i32* %retval                          ; <i32> [#uses=1]
>  ret i32 %0
> }
> 
> 
> into
> 
> 
> 
> define i32 @main() {
> entry:
>  %retval = alloca i32, align 4                   ; <i32*> [#uses=2]
>  store i32 0, i32* %retval
>  br i1 false, label %if.then, label %if.else
> 
> if.then:                                          ; preds = %entry
>  br label %if.end
> 
> if.else:                                          ; preds = %entry
>  %call1 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds
> ([10 x i8]* @.str1, i32 0, i32 0)) ; <i32> [#uses=0]
>  br label %if.end
> 
> if.end:                                           ; preds = %if.else, %if.then
>  %0 = load i32* %retval                          ; <i32> [#uses=1]
>  ret i32 %0
> }
> 
> 
> On Sun, Jun 6, 2010 at 9:09 PM, Clark Gaebel <cg.wowus.cg at gmail.com> wrote:
>> Here's a reduced test case. Strangely enough, if I change buffer to be of
>> size 1, this code works fine.
>> 
>> clark at clark-server ~/test $ clang++ --version
>> clang version 1.1 (branches/release_27)
>> Target: x86_64-pc-linux-gnu
>> Thread model: posix
>> clark at clark-server ~/test $ cat foo.cpp
>> #include <cstdio> // For printf.
>> 
>> int main()
>> {
>>        const char buffer[] = {
>>                0x00, 0x11
>>        };
>> 
>>        if(buffer > (buffer - 4))
>>                printf("SUCCESS!\n");
>>        else
>>                printf("FAILURE!\n");
>> }
>> 
>> clark at clark-server ~/test $ clang++ -O0 foo.cpp && ./a.out
>> SUCCESS!
>> clark at clark-server ~/test $ clang++ -O2 foo.cpp && ./a.out
>> FAILURE!
>> 
>> 
>> On 06/07/10 00:03, Clark Gaebel wrote:
>> 
>> A picture is worth a thousand words (and by picture, I mean shell
>> output). This is with
>> 
>>    clark at clark-server ~/test $ clang++ --version
>>    clang version 1.1 (branches/release_27)
>>    Target: x86_64-pc-linux-gnu
>>    Thread model: posix
>>    clark at clark-server ~/test $ cat foo.cpp
>>    #include <cstdlib>
>>    #include <cstdio>
>> 
>>    struct ParseFailed {};
>> 
>>    int main()
>>    {
>>            bool succeeded = false;
>> 
>>            const char buffer[] = {
>>                    0x00, 0x11
>>            };
>> 
>>            try {
>>                    if(buffer > (buffer - 4))
>>                            throw ParseFailed();
>> 
>>                    succeeded = false;
>>            } catch(ParseFailed) {
>>                    succeeded = true;
>>            }
>> 
>>            if(succeeded)
>>                    printf("SUCCESS!\n");
>>            else
>>                    printf("FAILURE!\n");
>>    }
>> 
>>    clark at clark-server ~/test $ clang++ -O0 foo.cpp && ./a.out
>>    SUCCESS!
>>    clark at clark-server ~/test $ clang++ -O2 foo.cpp && ./a.out
>>    FAILURE!
>> 
>> What should I do? This little oddity popped up in one of my unit tests
>> while running my codebase through clang.
>> 
>> 
>> 
>> --
>> Regards,
>> -Clark
>> 
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>> 
>> 
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev





More information about the cfe-dev mailing list