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

Reply via email to