Skip to content

[ClangImporter] fix crash when importing macros with bitwise operators #3629

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 20 additions & 8 deletions lib/ClangImporter/ImportMacro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,21 +476,33 @@ static ValueDecl *importMacro(ClangImporter::Implementation &impl,

auto firstInteger = firstValue.getInt();
auto secondInteger = secondValue.getInt();
auto firstBitWidth = firstInteger.getBitWidth();
auto secondBitWidth = secondInteger.getBitWidth();
auto type = firstConstant.second;

clang::APValue value;
if (tokenI[1].is(clang::tok::pipe)) {
if (firstInteger.getBitWidth() == secondInteger.getBitWidth()) {
value = clang::APValue(firstInteger | secondInteger);
} else {
return nullptr;
if (firstBitWidth < secondBitWidth) {
firstInteger = firstInteger.extend(secondBitWidth);
type = secondConstant.second;
} else if (secondBitWidth < firstBitWidth) {
secondInteger = secondInteger.extend(firstBitWidth);
type = firstConstant.second;
}
firstInteger.setIsUnsigned(true);
secondInteger.setIsUnsigned(true);
value = clang::APValue(firstInteger | secondInteger);
} else if (tokenI[1].is(clang::tok::amp)) {
if (firstInteger.getBitWidth() == secondInteger.getBitWidth()) {
value = clang::APValue(firstInteger & secondInteger);
} else {
return nullptr;
if (firstBitWidth < secondBitWidth) {
firstInteger = firstInteger.extend(secondBitWidth);
type = secondConstant.second;
} else if (secondBitWidth < firstBitWidth) {
secondInteger = secondInteger.extend(firstBitWidth);
type = firstConstant.second;
}
firstInteger.setIsUnsigned(true);
secondInteger.setIsUnsigned(true);
value = clang::APValue(firstInteger & secondInteger);
} else if (tokenI[1].is(clang::tok::pipepipe)) {
auto firstBool = firstInteger.getBoolValue();
auto secondBool = firstInteger.getBoolValue();
Expand Down
2 changes: 2 additions & 0 deletions test/IDE/Inputs/mock-sdk/Foo.annotated.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ class <loc>FooClassDerived</loc> : <ref:Class>FooClassBase</ref>, <ref:Protocol>
<decl:Var>var <loc>FOO_MACRO_11</loc>: <ref:Struct>Int</ref> { get }</decl>
<decl:Var>var <loc>FOO_MACRO_OR</loc>: <ref:Struct>Int32</ref> { get }</decl>
<decl:Var>var <loc>FOO_MACRO_AND</loc>: <ref:Struct>Int32</ref> { get }</decl>
<decl:Var>var <loc>FOO_MACRO_BITWIDTH</loc>: <ref:Struct>UInt64</ref> { get }</decl>
<decl:Var>var <loc>FOO_MACRO_SIGNED</loc>: <ref:Struct>Int32</ref> { get }</decl>
<decl:Var>var <loc>FOO_MACRO_REDEF_1</loc>: <ref:Struct>Int32</ref> { get }</decl>
<decl:Var>var <loc>FOO_MACRO_REDEF_2</loc>: <ref:Struct>Int32</ref> { get }</decl>
<decl:Func>func <loc>theLastDeclInFoo()</loc></decl>
Expand Down
1 change: 1 addition & 0 deletions test/IDE/Inputs/mock-sdk/Foo.framework/Headers/Foo.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ typedef int typedef_int_t;
#define FOO_MACRO_OR (FOO_MACRO_2 | FOO_MACRO_6)
#define FOO_MACRO_AND (FOO_MACRO_2 & FOO_MACRO_6)
#define FOO_MACRO_BITWIDTH (FOO_MACRO_4 & FOO_MACRO_5)
#define FOO_MACRO_SIGNED (FOO_MACRO_2 & FOO_MACRO_4)

#define FOO_MACRO_UNDEF_1 0
#undef FOO_MACRO_UNDEF_1
Expand Down
2 changes: 2 additions & 0 deletions test/IDE/Inputs/mock-sdk/Foo.printed.recursive.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ var FOO_MACRO_10: Int16 { get }
var FOO_MACRO_11: Int { get }
var FOO_MACRO_OR: Int32 { get }
var FOO_MACRO_AND: Int32 { get }
var FOO_MACRO_BITWIDTH: UInt64 { get }
var FOO_MACRO_SIGNED: Int32 { get }
var FOO_MACRO_REDEF_1: Int32 { get }
var FOO_MACRO_REDEF_2: Int32 { get }
func theLastDeclInFoo()
Expand Down
2 changes: 2 additions & 0 deletions test/IDE/Inputs/mock-sdk/Foo.printed.txt
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ var FOO_MACRO_10: Int16 { get }
var FOO_MACRO_11: Int { get }
var FOO_MACRO_OR: Int32 { get }
var FOO_MACRO_AND: Int32 { get }
var FOO_MACRO_BITWIDTH: UInt64 { get }
var FOO_MACRO_SIGNED: Int32 { get }

var FOO_MACRO_REDEF_1: Int32 { get }

Expand Down
2 changes: 1 addition & 1 deletion test/IDE/complete_from_clang_framework.swift
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func testCompleteModuleQualifiedFoo2() {
Foo#^CLANG_QUAL_FOO_2^#
// If the number of results below changes, then you need to add a result to the
// list below.
// CLANG_QUAL_FOO_2: Begin completions, 73 items
// CLANG_QUAL_FOO_2: Begin completions, 75 items
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassBase[#FooClassBase#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .FooClassDerived[#FooClassDerived#]{{; name=.+$}}
// CLANG_QUAL_FOO_2-DAG: Decl[Class]/OtherModule[Foo]: .ClassWithInternalProt[#ClassWithInternalProt#]{{; name=.+$}}
Expand Down