@@ -750,12 +750,19 @@ PointerVariableConstraint::mkString(Constraints &CS,
750750 UNPACK_OPTS (EmitName, ForItype, EmitPointee, UnmaskTypedef, UseName,
751751 ForItypeBase);
752752
753+ // This function has become pretty ad-hoc and has a number of known bugs: see
754+ // https://github.com/correctcomputation/checkedc-clang/issues/703. We hope to
755+ // overhaul it in the future.
756+
753757 // The name field encodes if this variable is the return type for a function.
754758 // TODO: store this information in a separate field.
755759 bool IsReturn = getName () == RETVAR;
756760
757- if (UseName.empty ())
761+ if (UseName.empty ()) {
758762 UseName = getName ();
763+ if (UseName.empty ())
764+ EmitName = false ;
765+ }
759766
760767 if (IsTypedef && !UnmaskTypedef) {
761768 std::string QualTypedef = gatherQualStrings () + TypedefString;
@@ -782,13 +789,9 @@ PointerVariableConstraint::mkString(Constraints &CS,
782789 bool EmittedBase = false ;
783790 // Have we emitted the name of the variable yet?
784791 bool EmittedName = false ;
785- // Was the last variable an Array?
786- bool PrevArr = false ;
787- // Is the entire type so far an array?
788- bool AllArrays = true ;
789792 if (!EmitName || IsReturn)
790793 EmittedName = true ;
791- uint32_t TypeIdx = 0 ;
794+ int TypeIdx = 0 ;
792795
793796 // If we've set a GenericIndex for void, it means we're converting it into
794797 // a generic function so give it the default generic type name.
@@ -802,16 +805,15 @@ PointerVariableConstraint::mkString(Constraints &CS,
802805 }
803806
804807 auto It = Vars.begin ();
805- auto I = 0 ;
806808 // Skip over first pointer level if only emitting pointee string.
807809 // This is needed when inserting type arguments.
808810 if (EmitPointee)
809811 ++It;
810812 // Iterate through the vars(), but if we have an internal typedef, then stop
811813 // once you reach the typedef's level.
812814 for (; It != Vars.end () && IMPLIES (TypedefLevelInfo.HasTypedef ,
813- I < TypedefLevelInfo.TypedefLevel );
814- ++It, I ++) {
815+ TypeIdx < TypedefLevelInfo.TypedefLevel );
816+ ++It, TypeIdx ++) {
815817 const auto &V = *It;
816818 ConstAtom *C = nullptr ;
817819 if (ForItypeBase) {
@@ -833,21 +835,23 @@ PointerVariableConstraint::mkString(Constraints &CS,
833835 if (!ForItype && InferredGenericIndex == -1 && isVoidPtr ())
834836 K = Atom::A_Wild;
835837
836- if (PrevArr && ArrSizes.at (TypeIdx).first != O_SizedArray && !EmittedName) {
837- EmittedName = true ;
838+ // In a case like `_Ptr<TYPE> p[2]`, the ` p[2]` needs to end up _after_ the
839+ // `>`, so we need to push the ` p[2]` onto EndStrs _before_ the code below
840+ // pushes the `>`. In general, before we visit a checked pointer level (not
841+ // a checked array level), we need to transfer any pending array levels and
842+ // emit the name (if applicable).
843+ if (K != Atom::A_Wild && ArrSizes.at (TypeIdx).first != O_SizedArray) {
838844 addArrayAnnotations (ConstArrs, EndStrs);
839- EndStrs.push_front (" " + UseName);
845+ if (!EmittedName) {
846+ EmittedName = true ;
847+ EndStrs.push_front (" " + UseName);
848+ }
840849 }
841- PrevArr = ArrSizes.at (TypeIdx).first == O_SizedArray;
842850
843851 switch (K) {
844852 case Atom::A_Ptr:
845853 getQualString (TypeIdx, Ss);
846854
847- // We need to check and see if this level of variable
848- // is constrained by a bounds safe interface. If it is,
849- // then we shouldn't re-write it.
850- AllArrays = false ;
851855 EmittedBase = false ;
852856 Ss << " _Ptr<" ;
853857 EndStrs.push_front (" >" );
@@ -861,38 +865,28 @@ PointerVariableConstraint::mkString(Constraints &CS,
861865 // we should substitute [K].
862866 if (emitArraySize (ConstArrs, TypeIdx, K))
863867 break ;
864- AllArrays = false ;
865- // We need to check and see if this level of variable
866- // is constrained by a bounds safe interface. If it is,
867- // then we shouldn't re-write it.
868868 EmittedBase = false ;
869869 Ss << " _Array_ptr<" ;
870870 EndStrs.push_front (" >" );
871871 break ;
872872 case Atom::A_NTArr:
873+ // If this is an NTArray.
874+ getQualString (TypeIdx, Ss);
873875 if (emitArraySize (ConstArrs, TypeIdx, K))
874876 break ;
875- AllArrays = false ;
876- // This additional check is to prevent fall-through from the array.
877- if (K == Atom::A_NTArr) {
878- // If this is an NTArray.
879- getQualString (TypeIdx, Ss);
880877
881- // We need to check and see if this level of variable
882- // is constrained by a bounds safe interface. If it is,
883- // then we shouldn't re-write it.
884- EmittedBase = false ;
885- Ss << " _Nt_array_ptr<" ;
886- EndStrs.push_front (" >" );
887- break ;
888- }
889- LLVM_FALLTHROUGH;
878+ EmittedBase = false ;
879+ Ss << " _Nt_array_ptr<" ;
880+ EndStrs.push_front (" >" );
881+ break ;
890882 // If there is no array in the original program, then we fall through to
891883 // the case where we write a pointer value.
892884 case Atom::A_Wild:
893885 if (emitArraySize (ConstArrs, TypeIdx, K))
894886 break ;
895- AllArrays = false ;
887+ // FIXME: This code emits wild pointer levels with the outermost on the
888+ // left. The outermost should be on the right
889+ // (https://github.com/correctcomputation/checkedc-clang/issues/161).
896890 if (FV != nullptr ) {
897891 FptrInner << " *" ;
898892 getQualString (TypeIdx, FptrInner);
@@ -912,35 +906,19 @@ PointerVariableConstraint::mkString(Constraints &CS,
912906 llvm_unreachable (" impossible" );
913907 break ;
914908 }
915- TypeIdx++;
916- }
917-
918- // If the previous variable was an array or
919- // if we are leaving an array run, we need to emit the
920- // annotation for a stack-array
921- if (PrevArr && !ConstArrs.empty ())
922- addArrayAnnotations (ConstArrs, EndStrs);
923-
924- // If the whole type is an array so far, and we haven't emitted
925- // a name yet, then emit the name so that it appears before
926- // the the stack array type.
927- if (PrevArr && !EmittedName && AllArrays) {
928- EmittedName = true ;
929- EndStrs.push_front (" " + UseName);
930909 }
931910
932911 if (!EmittedBase) {
933912 // If we have a FV pointer, then our "base" type is a function pointer type.
934913 if (FV) {
935- if (Ss.str ().empty ()) {
936- if (!EmittedName) {
937- FptrInner << UseName;
938- EmittedName = true ;
939- }
940- for (std::string Str : EndStrs)
941- FptrInner << Str;
942- EndStrs.clear ();
914+ if (!EmittedName) {
915+ FptrInner << UseName;
916+ EmittedName = true ;
943917 }
918+ std::deque<std::string> FptrEndStrs;
919+ addArrayAnnotations (ConstArrs, FptrEndStrs);
920+ for (std::string Str : FptrEndStrs)
921+ FptrInner << Str;
944922 bool EmitFVName = !FptrInner.str ().empty ();
945923 if (EmitFVName)
946924 Ss << FV->mkString (CS, MKSTRING_OPTS (UseName = FptrInner.str (),
@@ -958,27 +936,20 @@ PointerVariableConstraint::mkString(Constraints &CS,
958936 }
959937 }
960938
961- // Add closing elements to type
962- for (std::string Str : EndStrs) {
963- Ss << Str;
964- }
965-
966939 // No space after itype.
967- if (!EmittedName && !UseName. empty () ) {
940+ if (!EmittedName) {
968941 if (!StringRef (Ss.str ()).endswith (" *" ))
969942 Ss << " " ;
970943 Ss << UseName;
971944 }
972945
973- // Final array dropping.
974- if (!ConstArrs.empty ()) {
975- std::deque<std::string> ArrStrs;
976- addArrayAnnotations (ConstArrs, ArrStrs);
977- for (std::string Str : ArrStrs)
978- Ss << Str;
946+ // Add closing elements to type
947+ addArrayAnnotations (ConstArrs, EndStrs);
948+ for (std::string Str : EndStrs) {
949+ Ss << Str;
979950 }
980951
981- if (IsReturn && !ForItype)
952+ if (IsReturn && !ForItype && ! StringRef (Ss. str ()). endswith ( " * " ) )
982953 Ss << " " ;
983954
984955 return Ss.str ();
0 commit comments