diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 3cc54048188f..9acff8227228 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -746,6 +746,10 @@ void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { VisitValueDecl(DD); DD->setInnerLocStart(ReadSourceLocation(Record, Idx)); + + if (Record[Idx++]) // hasBoundsExpr + DD->setBoundsExpr(Reader.ReadBoundsExpr(F)); + if (Record[Idx++]) { // hasExtInfo DeclaratorDecl::ExtInfo *Info = new (Reader.getContext()) DeclaratorDecl::ExtInfo(); diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index a923d276fe9b..81fa0f01e255 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -501,6 +501,11 @@ void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { VisitValueDecl(D); Record.AddSourceLocation(D->getInnerLocStart()); + + Record.push_back(D->hasBoundsExpr()); + if (D->hasBoundsExpr()) + Record.AddStmt(D->getBoundsExpr()); + Record.push_back(D->hasExtInfo()); if (D->hasExtInfo()) Record.AddQualifierInfo(*D->getExtInfo()); @@ -728,6 +733,7 @@ void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { !D->isReferenced() && !D->isModulePrivate() && !D->getBitWidth() && + !D->hasBoundsExpr() && !D->hasExtInfo() && D->getDeclName()) AbbrevToUse = Writer.getDeclObjCIvarAbbrev(); @@ -862,6 +868,7 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { !D->isModulePrivate() && !D->getBitWidth() && !D->hasInClassInitializer() && + !D->hasBoundsExpr() && !D->hasExtInfo() && !ObjCIvarDecl::classofKind(D->getKind()) && !ObjCAtDefsFieldDecl::classofKind(D->getKind()) && @@ -940,6 +947,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) { !D->isModulePrivate() && !needsAnonymousDeclarationNumber(D) && D->getDeclName().getNameKind() == DeclarationName::Identifier && + !D->hasBoundsExpr() && !D->hasExtInfo() && D->getFirstDecl() == D->getMostRecentDecl() && D->getInitStyle() == VarDecl::CInit && @@ -980,6 +988,7 @@ void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { // know are true of all PARM_VAR_DECLs. if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && + !D->hasBoundsExpr() && !D->hasExtInfo() && !D->isImplicit() && !D->isUsed(false) && @@ -1235,6 +1244,7 @@ void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && D->getDeclName().getNameKind() == DeclarationName::Identifier && + !D->hasBoundsExpr() && !D->hasExtInfo() && !D->hasInheritedPrototype() && D->hasWrittenPrototype()) @@ -1714,6 +1724,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc + Abv->Add(BitCodeAbbrevOp(0)); // hasBoundsExpr Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable @@ -1747,6 +1758,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc + Abv->Add(BitCodeAbbrevOp(0)); // hasBoundsExpr Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // FieldDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable @@ -1878,6 +1890,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc + Abv->Add(BitCodeAbbrevOp(0)); // hasBoundsExpr Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // VarDecl Abv->Add(BitCodeAbbrevOp(0)); // StorageClass @@ -1954,6 +1967,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc + Abv->Add(BitCodeAbbrevOp(0)); // hasBoundsExpr Abv->Add(BitCodeAbbrevOp(0)); // hasExtInfo // VarDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // StorageClass @@ -2002,6 +2016,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type // DeclaratorDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart + Abv->Add(BitCodeAbbrevOp(0)); // hasBoundsExpr Abv->Add(BitCodeAbbrevOp(0)); // HasExtInfo // FunctionDecl Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS diff --git a/test/CheckedC/pch.c b/test/CheckedC/pch.c index 0f7681a4dc7c..ec14ac35d81d 100644 --- a/test/CheckedC/pch.c +++ b/test/CheckedC/pch.c @@ -10,60 +10,108 @@ // RUN: %clang_cc1 -fcheckedc-extension -emit-pch -o %t %S/pch.h // RUN: %clang_cc1 -fcheckedc-extension -include-pch %t -fsyntax-only -verify -verify-ignore-unexpected=note %s -// Bounds Expressions on globals +// +// Bounds Expressions on global variables +// // CountBounds -one_element_array arr1 = (int[1]){ 0 }; +_Array_ptr one_arr : count(1 + 1); // expected-error{{variable redeclaration has conflicting bounds}} +_Array_ptr one_arr : count(1); + +// Byte Count +_Array_ptr byte_arr : byte_count(sizeof(int)); // NullaryBounds -null_array arr2 = (int[]){ 0 }; +_Array_ptr null_arr : count(1); // expected-error{{variable redeclaration has conflicting bounds}} +_Array_ptr null_arr : bounds(none); // RangeBounds -ranged_array arr3 = two_arr; +int two_arr[2]; +_Array_ptr ranged_arr : bounds(&one_arr, &one_arr + 1); //expected-error{{variable redeclaration has conflicting bounds}} +_Array_ptr ranged_arr : bounds(&two_arr, &two_arr + 1); // InteropTypeBoundsAnnotation -int seven = 7; -integer_pointer seven_pointer1 = &seven; -_Ptr seven_pointer2 = &seven; +int* int_ptr : itype(_Array_ptr); // expected-error{{variable redeclaration has conflicting bounds}} +int* int_ptr : itype(_Ptr); +int* int_ptr; +// // Bounds Expressions on functions -int accepts_singleton(_Array_ptr one_arr : count(1)) { - return one_arr[0]; -} -void uses_accepts_singleton(void) { - _Array_ptr singleton : count(1) = (int[1]) { 0 }; - int x = accepts_singleton(singleton); -} +// + +// CountBounds +int count_fn(_Array_ptr arr : count(2)); // expected-error{{function redeclaration has conflicting parameter bounds}} +int count_fn(_Array_ptr arr : count(1)); +_Array_ptr count_fn2(void) : count(2); // expected-error{{function redeclaration has conflicting return bounds}} +_Array_ptr count_fn2(void) : count(1); + +// Byte Count +int byte_count_fn(_Array_ptr arr : byte_count(sizeof(int) + 1)); // expected-error{{function redeclaration has conflicting parameter bounds}} +int byte_count_fn(_Array_ptr arr : byte_count(sizeof(int))); +_Array_ptr byte_count_fn2(void) : byte_count(sizeof(int) + 1); // expected-error{{function redeclaration has conflicting return bounds}} +_Array_ptr byte_count_fn2(void) : byte_count(sizeof(int)); + +// NullaryBounds +int none_fn(_Array_ptr null_arr : count(1)); // expected-error{{function redeclaration has conflicting parameter bounds}} +int none_fn(_Array_ptr null_arr : bounds(none)); +_Array_ptr none_fn2(void) : count(1); // expected-error{{function redeclaration has conflicting return bounds}} +_Array_ptr none_fn2(void) : bounds(none); // RangeBounds + PositionalParamater -int sum_array(_Array_ptr start : bounds(start, end), _Array_ptr end) { - return 0; +int range_fn(_Array_ptr start : bounds(start, end - 1), _Array_ptr end); // expected-error{{function redeclaration has conflicting parameter bounds}} +int range_fn(_Array_ptr start : bounds(start, end), _Array_ptr end); +_Array_ptr range_fn2(_Array_ptr start) : bounds(start, start + 1); // expected-error{{function redeclaration has conflicting return bounds}} +_Array_ptr range_fn2(_Array_ptr start) : bounds(start, start); + +// CountBounds + PositionalParameter +int pos_fn(int len, _Array_ptr str : count(len + 1)); // expected-error{{function redeclaration has conflicting parameter bounds}} +int pos_fn(int len, _Array_ptr str : count(len)); +_Array_ptr pos_fn2(int len) : count(len + 1); // expected-error{{function redeclaration has conflicting return bounds}} +_Array_ptr pos_fn2(int len) : count(len); + +// InteropTypeBoundsAnnotation +int int_val(int *ptr : itype(_Array_ptr)); // expected-error{{function redeclaration has conflicting parameter bounds}} +int int_val(int *ptr : itype(_Ptr)); +int int_val(int *ptr); +int* int_val2(void) : itype(_Array_ptr); // expected-error{{function redeclaration has conflicting return bounds}} +int* int_val2(void) : itype(_Ptr); +int* int_val2(void); + + +// +// Bounds Expressions on Struct Members +// + +// CountBounds +struct S1; +void uses_S1(struct S1 data) { + _Array_ptr arr : count(5) = data.arr; } -void uses_sum_array(void) { - _Array_ptr pair : count(2) = (int[2]) { 0,1 }; - int x = sum_array(pair, pair+1); + +// Byte Count +struct S2; +void uses_S2(struct S2 data) { + _Array_ptr arr : byte_count(sizeof(int) * 5) = data.arr; } -// PositionalParameter -int str_last(int len, _Array_ptr str : count(len)) { - return 0; +// NullaryBounds +struct S3; +void uses_S3(struct S3 data) { + _Array_ptr arr : bounds(none) = data.arr; } -void uses_str_last(void) { - _Array_ptr str : count(3) = (char[3]){ 'a', 'b', 'c' }; - int last = str_last(3, str); + +// RangeBounds +struct S4; +void uses_S4(struct S4 data) { + _Array_ptr arr : bounds(data.arr, data.arr + 5) = data.arr; } // InteropTypeBoundsAnnotation -int int_val(int *ptr : itype(_Ptr)) { - return 0; -} -void uses_int_val(void) { +struct S5; +void uses_S5(struct S5 data) { + // Tests assigning a `_Ptr` into an `int* : itype(_Ptr)` + // This should be valid, according to the spec. int i = 3; - _Ptr i_star = &i; - int i2 = int_val(i_star); -} - -// Dropping bounds errors -int accepts_pair(_Array_ptr two_arr) { // expected-error{{function redeclaration dropped bounds for parameter}} - return 3; + _Ptr ip = &i; + data.i = ip; } \ No newline at end of file diff --git a/test/CheckedC/pch.h b/test/CheckedC/pch.h index 34b6a78ef0d1..169f3c591064 100644 --- a/test/CheckedC/pch.h +++ b/test/CheckedC/pch.h @@ -1,39 +1,78 @@ // Used with the pch.c test -// Bounds Expressions on globals +// +// Bounds Expressions on global variables +// // CountBounds _Array_ptr one_arr : count(1); -typedef typeof(one_arr) one_element_array; + +// Byte Count +_Array_ptr byte_arr : byte_count(sizeof(int)); // NullaryBounds _Array_ptr null_arr : bounds(none); -typedef typeof(null_arr) null_array; // RangeBounds -int two_arr[2] = { 0, 0 }; +int two_arr[2]; _Array_ptr ranged_arr : bounds(&two_arr, &two_arr + 1); -typedef typeof(ranged_arr) ranged_array; // InteropTypeBoundsAnnotation int* int_ptr : itype(_Ptr); -typedef typeof(int_ptr) integer_pointer; - +// // Bounds Expressions on functions -int accepts_singleton(_Array_ptr one_arr : count(1)); +// + +// CountBounds +int count_fn(_Array_ptr arr : count(1)); +_Array_ptr count_fn2(void) : count(1); + +// Byte Count +int byte_count_fn(_Array_ptr arr : byte_count(sizeof(int))); +_Array_ptr byte_count_fn2(void) : byte_count(sizeof(int)); // NullaryBounds -int accepts_null(_Array_ptr null_arr : bounds(none)); +int none_fn(_Array_ptr null_arr : bounds(none)); +_Array_ptr none_fn2(void) : bounds(none); // RangeBounds + PositionalParameter -int sum_array(_Array_ptr start : bounds(start, end) , _Array_ptr end); +int range_fn(_Array_ptr start : bounds(start, end), _Array_ptr end); +_Array_ptr range_fn2(_Array_ptr start) : bounds(start, start); -// PositionalParameter -int str_last(int len, _Array_ptr str : count(len)); +// CountBounds + PositionalParameter +int pos_fn(int len, _Array_ptr str : count(len)); +_Array_ptr pos_fn2(int len) : count(len); // InteropTypeBoundsAnnotation int int_val(int *ptr : itype(_Ptr)); +int* int_val2(void) : itype(_Ptr); + +// +// Bounds Expressions on Struct Members +// + +// CountBounds +struct S1 { + _Array_ptr arr : count(5); +}; + +// Byte Count +struct S2 { + _Array_ptr arr : byte_count(sizeof(int) * 5); +}; + +// NullaryBounds +struct S3 { + _Array_ptr arr : bounds(none); +}; -// dropping bounds errors -int accepts_pair(_Array_ptr two_arr : count(2)); \ No newline at end of file +// RangeBounds +struct S4 { + _Array_ptr arr : bounds(arr, arr + 5); +}; + +// InteropTypeBoundsAnnotation +struct S5 { + int* i : itype(_Ptr); +};