diff --git a/clang/include/clang/3C/ConstraintVariables.h b/clang/include/clang/3C/ConstraintVariables.h index 68ac8c9c9b3d..49e293d02baf 100644 --- a/clang/include/clang/3C/ConstraintVariables.h +++ b/clang/include/clang/3C/ConstraintVariables.h @@ -316,7 +316,7 @@ class PointerVariableConstraint : public ConstraintVariable { bool hasSomeSizedArr() const; bool isTypedef(void); - void setTypedef(TypedefNameDecl *TypedefType, std::string); + void setTypedef(TypedefNameDecl *T, std::string S); // Return true if this constraint had an itype in the original source code. bool srcHasItype() const override { @@ -387,6 +387,8 @@ class PointerVariableConstraint : public ConstraintVariable { return S->getKind() == PointerVariable; } + std::string gatherQualStrings(void) const; + std::string mkString(const EnvironmentMap &E, bool EmitName = true, bool ForItype = false, bool EmitPointee = false, bool UnmaskTypedef = false) const override; diff --git a/clang/include/clang/3C/ProgramInfo.h b/clang/include/clang/3C/ProgramInfo.h index 898938aeddf2..04c8e1de703b 100644 --- a/clang/include/clang/3C/ProgramInfo.h +++ b/clang/include/clang/3C/ProgramInfo.h @@ -81,8 +81,8 @@ class ProgramVariableAdder { virtual bool seenTypedef(PersistentSourceLoc PSL) = 0; - virtual void addTypedef(PersistentSourceLoc PSL, bool ShouldCheck) = 0; - + virtual void addTypedef(PersistentSourceLoc PSL, bool CanRewriteDef, + TypedefDecl *TD, ASTContext &C) = 0; protected: virtual AVarBoundsInfo &getABoundsInfo() = 0; @@ -170,11 +170,12 @@ class ProgramInfo : public ProgramVariableAdder { void unifyIfTypedef(const clang::Type *, clang::ASTContext &, clang::DeclaratorDecl *, PVConstraint *); - std::pair lookupTypedef(PersistentSourceLoc PSL); + CVarOption lookupTypedef(PersistentSourceLoc PSL); bool seenTypedef(PersistentSourceLoc PSL); - void addTypedef(PersistentSourceLoc PSL, bool ShouldCheck); + void addTypedef(PersistentSourceLoc PSL, bool CanRewriteDef, TypedefDecl *TD, + ASTContext& C); private: // List of constraint variables for declarations, indexed by their location in @@ -182,13 +183,10 @@ class ProgramInfo : public ProgramVariableAdder { // analysis from compilation unit to compilation unit. VariableMap Variables; - // Map storing constraint information for typedefed types, - // The set contains all the constraint variables that also use this typedef. - // TODO this could be replaced w/ a single CVar. - // The bool informs the rewriter whether or not this typedef should be - // rewritten. It will be false for typedefs we don't support rewritting, - // such as typedefs that are pointers to anonymous structs. - std::map> TypedefVars; + // Map storing constraint information for typedefed types + // The set contains all the constraint variables that also use this tyepdef + // rewritten. + std::map TypedefVars; // Map with the same purpose as the Variables map, this stores constraint // variables for non-declaration expressions. diff --git a/clang/lib/3C/ConstraintBuilder.cpp b/clang/lib/3C/ConstraintBuilder.cpp index 4b48584bf53b..3a97297284e1 100644 --- a/clang/lib/3C/ConstraintBuilder.cpp +++ b/clang/lib/3C/ConstraintBuilder.cpp @@ -562,8 +562,8 @@ class VariableAdderVisitor : public RecursiveASTVisitor { if (!VarAdder.seenTypedef(PSL)) // Add this typedef to the program info, if it contains a ptr to // an anonymous struct we mark as not being rewritable - VarAdder.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD)); - + VarAdder.addTypedef(PSL, !PtrToStructDef::containsPtrToStructDef(TD), + TD, *Context); return true; } diff --git a/clang/lib/3C/ConstraintVariables.cpp b/clang/lib/3C/ConstraintVariables.cpp index 9945128b2547..1f664e50893d 100644 --- a/clang/lib/3C/ConstraintVariables.cpp +++ b/clang/lib/3C/ConstraintVariables.cpp @@ -654,12 +654,18 @@ void PointerVariableConstraint::setTypedef(TypedefNameDecl *T, std::string S) { // variables and potentially nested function pointer declaration. Produces a // string that can be replaced in the source code. +std::string PointerVariableConstraint::gatherQualStrings(void) const { + std::ostringstream S; + getQualString(0, S); + return S.str(); +} + std::string PointerVariableConstraint::mkString(const EnvironmentMap &E, bool EmitName, bool ForItype, bool EmitPointee, bool UnmaskTypedef) const { if (IsTypedef && !UnmaskTypedef) { - return TypedefString + + return gatherQualStrings() + TypedefString + (EmitName && getName() != RETVAR ? (" " + getName()) : " "); } @@ -814,14 +820,16 @@ std::string PointerVariableConstraint::mkString(const EnvironmentMap &E, EndStrs.push_front(" " + getName()); } - if (EmittedBase == false) { + if (!EmittedBase) { // If we have a FV pointer, then our "base" type is a function pointer. // type. if (FV) { Ss << FV->mkString(E); } else if (TypedefLevelInfo.HasTypedef) { + std::ostringstream Buf; + getQualString(TypedefLevelInfo.TypedefLevel, Buf); auto Name = TypedefLevelInfo.TypedefName; - Ss << Name; + Ss << Buf.str() << Name; } else { Ss << BaseType; } @@ -1407,6 +1415,9 @@ std::string FunctionVariableConstraint::mkString(const EnvironmentMap &E, bool UnmaskTypedef) const { std::string Ret = ReturnVar.mkTypeStr(E); std::string Itype = ReturnVar.mkItypeStr(E); + // This is done to rewrite the typedef of a function proto + if (UnmaskTypedef && EmitName) + Ret += Name; Ret = Ret + "("; std::vector ParmStrs; for (const auto &I : this->ParamVars) @@ -1420,10 +1431,8 @@ std::string FunctionVariableConstraint::mkString(const EnvironmentMap &E, Ss << ParmStrs.back(); Ret = Ret + Ss.str() + ")"; - } else { + } else Ret = Ret + "void)"; - } - return Ret + Itype; } diff --git a/clang/lib/3C/DeclRewriter.cpp b/clang/lib/3C/DeclRewriter.cpp index 745485396ac8..9178f4643dd0 100644 --- a/clang/lib/3C/DeclRewriter.cpp +++ b/clang/lib/3C/DeclRewriter.cpp @@ -53,21 +53,19 @@ void DeclRewriter::rewriteDecls(ASTContext &Context, ProgramInfo &Info, SVI.TraverseDecl(D); if (const auto &TD = dyn_cast(D)) { auto PSL = PersistentSourceLoc::mkPSL(TD, Context); - // Don't rewrite base types like int. - if (!TD->getUnderlyingType()->isBuiltinType()) { - const auto Pair = Info.lookupTypedef(PSL); - const auto VSet = Pair.first; - if (!VSet.empty()) { // We ignore typedefs that are never used. - const auto Var = VSet.begin(); + if (!TD->getUnderlyingType()->isBuiltinType()) { // Don't rewrite base types like int + const auto O = Info.lookupTypedef(PSL); + if (O.hasValue()) { + const auto &Var = O.getValue(); const auto &Env = Info.getConstraints().getVariables(); - if ((*Var)->anyChanges(Env)) { - std::string NewTy = - getStorageQualifierString(D) + - (*Var)->mkString(Info.getConstraints().getVariables(), false, - false, false, true) + - " " + TD->getNameAsString(); - RewriteThese.insert(new TypedefDeclReplacement(TD, nullptr, NewTy)); - } + if (Var.anyChanges(Env)) { + std::string newTy = + getStorageQualifierString(D) + + Var.mkString(Info.getConstraints().getVariables(), true, + false, false, true); + RewriteThese.insert( + new TypedefDeclReplacement(TD, nullptr, newTy)); + } } } } @@ -208,8 +206,8 @@ void DeclRewriter::rewriteParmVarDecl(ParmVarDeclReplacement *N) { } } -void DeclRewriter::rewriteTypedefDecl(TypedefDeclReplacement *TDR, - RSet &ToRewrite) { + +void DeclRewriter::rewriteTypedefDecl(TypedefDeclReplacement *TDR, RSet &ToRewrite) { rewriteSingleDecl(TDR, ToRewrite); } diff --git a/clang/lib/3C/ProgramInfo.cpp b/clang/lib/3C/ProgramInfo.cpp index 7fb08b6cd9f4..f6429f341063 100644 --- a/clang/lib/3C/ProgramInfo.cpp +++ b/clang/lib/3C/ProgramInfo.cpp @@ -695,17 +695,15 @@ void ProgramInfo::addVariable(clang::DeclaratorDecl *D, Variables[PLoc] = NewCV; } -void ProgramInfo::unifyIfTypedef(const Type *Ty, ASTContext &Context, - DeclaratorDecl *Decl, PVConstraint *P) { - if (const auto *const TDT = dyn_cast(Ty)) { - auto *Decl = TDT->getDecl(); - auto PSL = PersistentSourceLoc::mkPSL(Decl, Context); - auto &Pair = TypedefVars[PSL]; - CVarSet &Bounds = Pair.first; - if (Pair.second) { - P->setTypedef(Decl, Decl->getNameAsString()); +void ProgramInfo::unifyIfTypedef(const Type* Ty, ASTContext& Context, DeclaratorDecl* Decl, PVConstraint* P) { + if (const auto* TDT = dyn_cast(Ty)) { + auto* TDecl = TDT->getDecl(); + auto PSL = PersistentSourceLoc::mkPSL(TDecl, Context); + auto O = lookupTypedef(PSL); + if (O.hasValue()) { + auto *Bounds = &O.getValue(); + P->setTypedef(TDecl, TDecl->getNameAsString()); constrainConsVarGeq(P, Bounds, CS, &PSL, Same_to_Same, true, this); - Bounds.insert(P); } } } @@ -1092,7 +1090,7 @@ ProgramInfo::getTypeParamBindings(CallExpr *CE, ASTContext *C) const { return TypeParamBindings.at(PSL); } -std::pair ProgramInfo::lookupTypedef(PersistentSourceLoc PSL) { +CVarOption ProgramInfo::lookupTypedef(PersistentSourceLoc PSL) { return TypedefVars[PSL]; } @@ -1100,7 +1098,23 @@ bool ProgramInfo::seenTypedef(PersistentSourceLoc PSL) { return TypedefVars.count(PSL) != 0; } -void ProgramInfo::addTypedef(PersistentSourceLoc PSL, bool ShouldCheck) { - CVarSet Empty; - TypedefVars[PSL] = make_pair(Empty, ShouldCheck); +void ProgramInfo::addTypedef(PersistentSourceLoc PSL, bool CanRewriteDef, + TypedefDecl* TD, ASTContext &C) { + auto Name = TD->getNameAsString(); + ConstraintVariable* V = nullptr; + const auto T = TD->getUnderlyingType(); + if (isa(T) || isa(T)) + V = new FunctionVariableConstraint(T.getTypePtr(), + nullptr, Name, *this, C); + else + V = new PointerVariableConstraint(T, nullptr, Name, *this, C); + auto *const Rsn = + !CanRewriteDef ? + "Unable to rewrite a typedef with multiple names" + : "Declaration in non-writable file"; + if (!(CanRewriteDef && canWrite(PSL.getFileName()))) { + V->constrainToWild(this->getConstraints(), Rsn, &PSL); + } + constrainWildIfMacro(V, TD->getLocation(), &PSL); + this->TypedefVars[PSL] = {*V}; } diff --git a/clang/test/3C/base_subdir/canwrite_constraints.c b/clang/test/3C/base_subdir/canwrite_constraints.c index 2454687229dd..b0c16ed4601e 100644 --- a/clang/test/3C/base_subdir/canwrite_constraints.c +++ b/clang/test/3C/base_subdir/canwrite_constraints.c @@ -31,3 +31,13 @@ int *bar(int *q) { foo(q); return foo_var; } + + +int gar(intptr a) { + int* b = a; + //CHECK_LOWER: int* b = a; + //CHECK_HIGHER: _Ptr b = a; + return *b; +} + + diff --git a/clang/test/3C/basic_checks.c b/clang/test/3C/basic_checks.c index d36b82186fa4..8948a3326725 100644 --- a/clang/test/3C/basic_checks.c +++ b/clang/test/3C/basic_checks.c @@ -39,7 +39,7 @@ void mut_pa(PA p) { p->a = 0; p->b = 1; } -//CHECK: void mut_pa(_Ptr p) { +//CHECK: void mut_pa(PA p) { void pa_driver(void) { A a = {0}; @@ -49,7 +49,7 @@ void pa_driver(void) { } //CHECK: void pa_driver(void) { //CHECK-NEXT: A a = {0}; -//CHECK-NEXT: _Ptr b = &a; +//CHECK-NEXT: PA b = &a; int *id(int *a) { return a; diff --git a/clang/test/3C/canwrite_constraints.h b/clang/test/3C/canwrite_constraints.h index dcd3704f1f28..48508be528a2 100644 --- a/clang/test/3C/canwrite_constraints.h +++ b/clang/test/3C/canwrite_constraints.h @@ -29,6 +29,11 @@ void atol_like() { inline void no_op() {} // CHECK_HIGHER: inline void no_op() _Checked {} +// In the lower case, this should stay wild +// In the higher case, this should solve to checked +// expected-warning@+1 {{Declaration in non-writable file}} +typedef int* intptr; +// CHECK_HIGHER: typedef _Ptr intptr; // Test the unwritable cast internal warning // (https://github.com/correctcomputation/checkedc-clang/issues/454) using the // known bug with itypes and function pointers diff --git a/clang/test/3C/root_cause.c b/clang/test/3C/root_cause.c index 1d0db1a4db32..ce9bab9fecaf 100644 --- a/clang/test/3C/root_cause.c +++ b/clang/test/3C/root_cause.c @@ -41,3 +41,8 @@ void test1() { extern int *glob; // expected-warning {{External global variable glob has no definition}} void (*f)(void *); // expected-warning {{Default void* type}} + +typedef struct { + int x; + float f; +} A, *PA; // expected-warning {{Unable to rewrite a typedef with multiple names}} diff --git a/clang/test/3C/simple_locals.c b/clang/test/3C/simple_locals.c index b1880b992898..a5d6c77ce9a8 100644 --- a/clang/test/3C/simple_locals.c +++ b/clang/test/3C/simple_locals.c @@ -200,8 +200,8 @@ void dfnk(int a, int b) { } //CHECK: void dfnk(int a, int b) { //CHECK-NEXT: A j; -//CHECK-NEXT: _Ptr k = &j; -//CHECK-NEXT: _Ptr<_Ptr> u = &k; +//CHECK-NEXT: PA k = &j; +//CHECK-NEXT: PPA u = &k; void adsfse(void) { int a = 0; diff --git a/clang/test/3C/typedefs.c b/clang/test/3C/typedefs.c index 5b114da81237..04070c483106 100644 --- a/clang/test/3C/typedefs.c +++ b/clang/test/3C/typedefs.c @@ -31,6 +31,8 @@ intptr bar(intptr x) { return x; } +typedef int* integer; +//CHECK: typedef _Ptr integer; int foo(void) { //CHECK: int foo(void) { int x = 3; @@ -43,6 +45,14 @@ int foo(void) { bad b = (int*) 3; //CHECK: bad b = (int*) 3; badP b2 = (intptr*) 3; + typedef int nat; + const nat z = 3; + const nat* cnstp = &z; + //CHECK: _Ptr cnstp = &z; + int w = 34; + const integer c = &w; + //CHECK: const integer c = &w; + return *p; } @@ -65,7 +75,18 @@ void barfoo(intptr x) { *x = 5; } +#define MYDECL typedef int* ZZZ; +MYDECL +void zzz(void) { + int x = 3; + ZZZ z = &x; +} +typedef int * * const a; +//CHECK: typedef const _Ptr<_Ptr> a; +void xxx(void) { + a b; +}