djtodoro updated this revision to Diff 188110. djtodoro added a comment. Herald added a subscriber: jdoerfert.
- Handle all kinds of expressions when mark a param's modification CHANGES SINCE LAST ACTION https://reviews.llvm.org/D58035/new/ https://reviews.llvm.org/D58035 Files: include/clang/AST/Decl.h lib/CodeGen/CGDebugInfo.cpp lib/Sema/SemaExpr.cpp lib/Serialization/ASTReaderDecl.cpp lib/Serialization/ASTWriterDecl.cpp test/CodeGen/dbginfo-var-change-templates.cpp test/CodeGen/debug-info-varchange.c
Index: test/CodeGen/debug-info-varchange.c =================================================================== --- /dev/null +++ test/CodeGen/debug-info-varchange.c @@ -0,0 +1,35 @@ +// RUN: %clang -femit-param-entry-values -emit-llvm -S -g %s -o - | FileCheck %s + +// CHECK: !DILocalVariable(name: "a", arg: 1, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}, flags: DIFlagArgumentNotModified) +// CHECK: !DILocalVariable(name: "b", arg: 2, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}) +// CHECK: !DILocalVariable(name: "test_s", arg: 3, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}, flags: DIFlagArgumentNotModified) +// CHECK: !DILocalVariable(name: "test_s2", arg: 4, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}) +// CHECK: !DILocalVariable(name: "x", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}) +// CHECK: !DILocalVariable(name: "y", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}) + +typedef struct s { + int m; + int n; +}S; + +void foo (int a, int b, + S test_s, S test_s2) +{ + b++; + b = a + 1; + if (b>4) + test_s2.m = 434; +} + +int main() +{ + S test_s = {4, 5}; + + int x = 5; + int y = 6; + + foo(x , y, test_s, test_s); + + return 0; +} + Index: test/CodeGen/dbginfo-var-change-templates.cpp =================================================================== --- /dev/null +++ test/CodeGen/dbginfo-var-change-templates.cpp @@ -0,0 +1,24 @@ +// RUN: %clang -femit-param-entry-values -emit-llvm -S -g %s -o - | FileCheck %s +// CHECK: !DILocalVariable(name: "a", arg: 1, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}) +// CHECK: !DILocalVariable(name: "b", arg: 2, scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: {{.*}}, flags: DIFlagArgumentNotModified) + +template <class T> +__attribute__((noinline)) +T GetMin (T a, T b) { + T result; + ++a; + result = (a < b) ? a : b; + return result; +} + +int baa () { + int i=5, j=6, k; + k=GetMin<int>(i,j); + + if (i == k) + ++k; + else + --k; + + return k; +} Index: lib/Serialization/ASTWriterDecl.cpp =================================================================== --- lib/Serialization/ASTWriterDecl.cpp +++ lib/Serialization/ASTWriterDecl.cpp @@ -1033,6 +1033,7 @@ Record.push_back(D->hasUninstantiatedDefaultArg()); if (D->hasUninstantiatedDefaultArg()) Record.AddStmt(D->getUninstantiatedDefaultArg()); + Record.push_back(D->isArgumentKnownToBeModified()); Code = serialization::DECL_PARM_VAR; assert(!D->isARCPseudoStrong()); // can be true of ImplicitParamDecl @@ -1046,6 +1047,7 @@ !D->isImplicit() && !D->isUsed(false) && !D->isInvalidDecl() && + !D->isArgumentKnownToBeModified() && !D->isReferenced() && D->getAccess() == AS_none && !D->isModulePrivate() && @@ -2011,6 +2013,7 @@ Abv->Add(BitCodeAbbrevOp(0)); // KNRPromoted Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg Abv->Add(BitCodeAbbrevOp(0)); // HasUninstantiatedDefaultArg + Abv->Add(BitCodeAbbrevOp(0)); // IsArgumentKnownToBeModified // Type Source Info Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc Index: lib/Serialization/ASTReaderDecl.cpp =================================================================== --- lib/Serialization/ASTReaderDecl.cpp +++ lib/Serialization/ASTReaderDecl.cpp @@ -1441,7 +1441,7 @@ PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt(); if (Record.readInt()) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Record.readExpr()); - + PD->ParmVarDeclBits.IsArgumentKnownToBeModified = Record.readInt(); // FIXME: If this is a redeclaration of a function from another module, handle // inheritance of default arguments. } Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -16,6 +16,7 @@ #include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/EvaluatedExprVisitor.h" @@ -11276,6 +11277,30 @@ DiagnoseConstAssignment(S, E, Loc); } +/// Traverse an expression and find declaration ref, if any. +static bool HasDeclRef(const Expr *E, const DeclRefExpr *&DeclRef) { + if ((DeclRef = dyn_cast_or_null<DeclRefExpr>(E))) + return true; + + for (const Stmt *SubStmt : E->children()) + if (const auto *SubExpr = dyn_cast_or_null<Expr>(SubStmt)) + if (HasDeclRef(SubExpr, DeclRef)) + return true; + + return false; +} + +/// Argument's value might be modified, so update the info. +static void EmitArgumentsValueModification(Expr *E) { + const DeclRefExpr *LHSDeclRef; + if (HasDeclRef(E, LHSDeclRef)) { + const ValueDecl *Decl = LHSDeclRef->getDecl(); + if (const auto *PD = dyn_cast_or_null<ParmVarDecl>(Decl)) + if (!PD->isArgumentKnownToBeModified()) + const_cast<ParmVarDecl*>(PD)->setIsArgumentKnownToBeModified(); + } +} + /// CheckForModifiableLvalue - Verify that E is a modifiable lvalue. If not, /// emit an error and return true. If so, return false. static bool CheckForModifiableLvalue(Expr *E, SourceLocation Loc, Sema &S) { @@ -11288,8 +11313,10 @@ &Loc); if (IsLV == Expr::MLV_ClassTemporary && IsReadonlyMessage(E, S)) IsLV = Expr::MLV_InvalidMessageExpression; - if (IsLV == Expr::MLV_Valid) + if (IsLV == Expr::MLV_Valid) { + EmitArgumentsValueModification(E); return false; + } unsigned DiagID = 0; bool NeedType = false; @@ -11341,6 +11368,7 @@ S.Diag(Loc, DiagID) << E->getSourceRange() << Assign; // We need to preserve the AST regardless, so migration tool // can do its job. + EmitArgumentsValueModification(E); return false; } } @@ -11381,8 +11409,13 @@ break; case Expr::MLV_IncompleteType: case Expr::MLV_IncompleteVoidType: - return S.RequireCompleteType(Loc, E->getType(), - diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E); + { + bool NeedCompleteType = S.RequireCompleteType(Loc, E->getType(), + diag::err_typecheck_incomplete_type_not_modifiable_lvalue, E); + if (!NeedCompleteType) + EmitArgumentsValueModification(E); + return NeedCompleteType; + } case Expr::MLV_DuplicateVectorComponents: DiagID = diag::err_typecheck_duplicate_vector_components_not_mlvalue; break; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -3778,6 +3778,12 @@ if (VD->isImplicit()) Flags |= llvm::DINode::FlagArtificial; + if (const auto *PD = dyn_cast<ParmVarDecl>(VD)) { + auto &CGOpts = CGM.getCodeGenOpts(); + if (CGOpts.EnableParamEntryValues && !PD->isArgumentKnownToBeModified()) + Flags |= llvm::DINode::FlagArgumentNotModified; + } + auto Align = getDeclAlignIfRequired(VD, CGM.getContext()); unsigned AddressSpace = CGM.getContext().getTargetAddressSpace(VD->getType()); Index: include/clang/AST/Decl.h =================================================================== --- include/clang/AST/Decl.h +++ include/clang/AST/Decl.h @@ -905,6 +905,9 @@ /// Whether this parameter is an ObjC method parameter or not. unsigned IsObjCMethodParam : 1; + /// Whether this parameter is known to be modified throughout a function. + unsigned IsArgumentKnownToBeModified : 1; + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. /// Otherwise, the number of function parameter scopes enclosing /// the function parameter scope in which this parameter was @@ -1560,6 +1563,7 @@ assert(ParmVarDeclBits.DefaultArgKind == DAK_None); assert(ParmVarDeclBits.IsKNRPromoted == false); assert(ParmVarDeclBits.IsObjCMethodParam == false); + assert(ParmVarDeclBits.IsArgumentKnownToBeModified == false); setDefaultArg(DefArg); } @@ -1593,6 +1597,13 @@ return ParmVarDeclBits.IsObjCMethodParam; } + bool isArgumentKnownToBeModified() const { + return ParmVarDeclBits.IsArgumentKnownToBeModified; + } + void setIsArgumentKnownToBeModified() { + ParmVarDeclBits.IsArgumentKnownToBeModified = true; + } + unsigned getFunctionScopeDepth() const { if (ParmVarDeclBits.IsObjCMethodParam) return 0; return ParmVarDeclBits.ScopeDepthOrObjCQuals;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits