diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index c8c688668480..34a84700502b 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -4753,7 +4753,7 @@ class PositionalParameterExpr : public Expr { } explicit PositionalParameterExpr(EmptyShell Empty) : - Expr(InteropTypeBoundsAnnotationClass, Empty) { + Expr(PositionalParameterExprClass, Empty) { } diff --git a/lib/Serialization/ASTReaderStmt.cpp b/lib/Serialization/ASTReaderStmt.cpp index 15e6929dcbd5..fe267cf249b1 100644 --- a/lib/Serialization/ASTReaderStmt.cpp +++ b/lib/Serialization/ASTReaderStmt.cpp @@ -984,6 +984,7 @@ void ASTStmtReader::VisitInteropTypeBoundsAnnotation( InteropTypeBoundsAnnotation *E) { VisitExpr(E); E->setKind((BoundsExpr::Kind)Record[Idx++]); + E->setTypeInfoAsWritten(GetTypeSourceInfo(Record, Idx)); E->StartLoc = ReadSourceLocation(Record, Idx); E->EndLoc = ReadSourceLocation(Record, Idx); } diff --git a/lib/Serialization/ASTWriterStmt.cpp b/lib/Serialization/ASTWriterStmt.cpp index e17dec88a591..3a54ff7b1dd1 100644 --- a/lib/Serialization/ASTWriterStmt.cpp +++ b/lib/Serialization/ASTWriterStmt.cpp @@ -913,7 +913,7 @@ void ASTStmtWriter::VisitAtomicExpr(AtomicExpr *E) { void ASTStmtWriter::VisitCountBoundsExpr(CountBoundsExpr *E) { VisitExpr(E); Record.push_back(E->getKind()); - VisitExpr(E->getCountExpr()); + Record.AddStmt(E->getCountExpr()); Record.AddSourceLocation(E->getStartLoc()); Record.AddSourceLocation(E->getRParenLoc()); Code = serialization::EXPR_COUNT_BOUNDS_EXPR; @@ -930,8 +930,8 @@ void ASTStmtWriter::VisitNullaryBoundsExpr(NullaryBoundsExpr *E) { void ASTStmtWriter::VisitRangeBoundsExpr(RangeBoundsExpr *E) { VisitExpr(E); Record.push_back(E->getKind()); - VisitExpr(E->getLowerExpr()); - VisitExpr(E->getUpperExpr()); + Record.AddStmt(E->getLowerExpr()); + Record.AddStmt(E->getUpperExpr()); Record.AddSourceLocation(E->getStartLoc()); Record.AddSourceLocation(E->getRParenLoc()); Code = serialization::EXPR_RANGE_BOUNDS_EXPR; @@ -941,6 +941,7 @@ void ASTStmtWriter::VisitInteropTypeBoundsAnnotation( InteropTypeBoundsAnnotation *E) { VisitExpr(E); Record.push_back(E->getKind()); + Record.AddTypeSourceInfo(E->getTypeInfoAsWritten()); Record.AddSourceLocation(E->getStartLoc()); Record.AddSourceLocation(E->getLocEnd()); Code = serialization::EXPR_INTEROPTYPE_BOUNDS_ANNOTATION; diff --git a/test/CheckedC/pch.c b/test/CheckedC/pch.c new file mode 100644 index 000000000000..0f7681a4dc7c --- /dev/null +++ b/test/CheckedC/pch.c @@ -0,0 +1,69 @@ +// This tests compiling a CheckedC file using Pre-Compiled Headers (PCH) +// To do so, we compile and verify this file against a header twice, once directly, and once via PCH +// If everything is working, both will succeed or fail together. If not, PCH is broken. +// PCH is one of the few places where AST Deserialization is used. + +// Test this without PCH +// RUN: %clang_cc1 -fcheckedc-extension -include %S/pch.h -fsyntax-only -verify -verify-ignore-unexpected=note %s + +// Test PCH (so we know our changes to AST deserialization haven't broken it) +// 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 + +// CountBounds +one_element_array arr1 = (int[1]){ 0 }; + +// NullaryBounds +null_array arr2 = (int[]){ 0 }; + +// RangeBounds +ranged_array arr3 = two_arr; + +// InteropTypeBoundsAnnotation +int seven = 7; +integer_pointer seven_pointer1 = &seven; +_Ptr seven_pointer2 = &seven; + +// 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); +} + +// RangeBounds + PositionalParamater +int sum_array(_Array_ptr start : bounds(start, end), _Array_ptr end) { + return 0; +} +void uses_sum_array(void) { + _Array_ptr pair : count(2) = (int[2]) { 0,1 }; + int x = sum_array(pair, pair+1); +} + +// PositionalParameter +int str_last(int len, _Array_ptr str : count(len)) { + return 0; +} +void uses_str_last(void) { + _Array_ptr str : count(3) = (char[3]){ 'a', 'b', 'c' }; + int last = str_last(3, str); +} + +// InteropTypeBoundsAnnotation +int int_val(int *ptr : itype(_Ptr)) { + return 0; +} +void uses_int_val(void) { + 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; +} \ No newline at end of file diff --git a/test/CheckedC/pch.h b/test/CheckedC/pch.h new file mode 100644 index 000000000000..34b6a78ef0d1 --- /dev/null +++ b/test/CheckedC/pch.h @@ -0,0 +1,39 @@ +// Used with the pch.c test + +// Bounds Expressions on globals + +// CountBounds +_Array_ptr one_arr : count(1); +typedef typeof(one_arr) one_element_array; + +// NullaryBounds +_Array_ptr null_arr : bounds(none); +typedef typeof(null_arr) null_array; + +// RangeBounds +int two_arr[2] = { 0, 0 }; +_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)); + +// NullaryBounds +int accepts_null(_Array_ptr null_arr : bounds(none)); + +// RangeBounds + PositionalParameter +int sum_array(_Array_ptr start : bounds(start, end) , _Array_ptr end); + +// PositionalParameter +int str_last(int len, _Array_ptr str : count(len)); + +// InteropTypeBoundsAnnotation +int int_val(int *ptr : itype(_Ptr)); + +// dropping bounds errors +int accepts_pair(_Array_ptr two_arr : count(2)); \ No newline at end of file